diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 237089364..0eb709e29 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -64,6 +64,10 @@ jobs:
run: |
./mvnw -V clean install -f ci.ant --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false -DskipTests
./mvnw -V clean install -f ci.common --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false -DskipTests
+ # Run tests that require a minimum of Java 17 or later
+ - name: Run tests that require a minimum of Java 17 or later
+ if: ${{ matrix.java == '17' || matrix.java == '21'}}
+ run: ./mvnw -V verify --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false -Ponline-its -D"invoker.streamLogsOnFailures"=true -D"invoker.test"="*setup*,*springboot-3-*" -Druntime=${{ matrix.RUNTIME }} -DruntimeVersion="${{ matrix.RUNTIME_VERSION }}"
# Run tests
- name: Run tests
run: ./mvnw -V verify --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false -Ponline-its -D"invoker.streamLogsOnFailures"=true -Druntime=${{ matrix.RUNTIME }} -DruntimeVersion="${{ matrix.RUNTIME_VERSION }}"
@@ -112,6 +116,10 @@ jobs:
- name: Install ci.common
working-directory: C:/ci.common
run: .\mvnw.cmd -V clean install --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false -DskipTests
+ # Run tests that require a minimum of Java 17 or later
+ - name: Run tests that require a minimum of Java 17 or later
+ if: ${{ matrix.java == '17' || matrix.java == '21'}}
+ run: .\mvnw.cmd -V verify -Ponline-its --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false -D"invoker.streamLogsOnFailures"=true -D"invoker.test"="*setup*,*springboot-3-*" -Druntime=${{ matrix.RUNTIME }} -DruntimeVersion="${{ matrix.RUNTIME_VERSION }}"
# Run tests
- name: Run tests
working-directory: C:/ci.maven
diff --git a/docs/spring-boot-support.md b/docs/spring-boot-support.md
index 9d06ee3ed..a28df2aa2 100644
--- a/docs/spring-boot-support.md
+++ b/docs/spring-boot-support.md
@@ -15,10 +15,15 @@ The `server.xml` provided by the `serverXmlFile` parameter or located in the `co
| Feature | Description |
| ------- | ----------- |
| springBoot-1.5 | Required to support applications with Spring Boot version 1.5.x. |
-| springBoot-2.0 | Required to support applications with Spring Boot version 2.0.x and above. |
+| springBoot-2.0 | Required to support applications with Spring Boot version 2.0.x. |
+| springBoot-3.0 | Required to support applications with Spring Boot version 3.x. |
The Liberty features that support the Spring Boot starters can be found [here](https://www.ibm.com/support/knowledgecenter/SSAW57_liberty/com.ibm.websphere.wlp.nd.multiplatform.doc/ae/rwlp_springboot.html). They should be enabled in the `server.xml` along with the appropriate Spring Boot feature.
+### Java Support
+
+The Spring Boot version 3.x requires Java 17 or above.
+
### Example
To use the `liberty-maven-plugin` to install a Spring Boot application packaged as a Spring Boot Uber JAR, include the appropriate XML in the `plugins` section of your `pom.xml`.
diff --git a/liberty-maven-plugin/pom.xml b/liberty-maven-plugin/pom.xml
index 99c5cfd76..b08472af1 100644
--- a/liberty-maven-plugin/pom.xml
+++ b/liberty-maven-plugin/pom.xml
@@ -223,6 +223,7 @@
binary-scanner-it/pom.xml
+ springboot-3-tests/pom.xml
dev-container-it/pom.xml
@@ -263,6 +264,7 @@
server-param-configdir-not-override-it/pom.xml
install-features-it/pom.xml
binary-scanner-it/pom.xml
+ springboot-3-tests/pom.xml
dev-container-it/pom.xml
@@ -303,6 +305,7 @@
dev-container-it/pom.xml
generate-features-it/pom.xml
binary-scanner-it/pom.xml
+ springboot-3-tests/pom.xml
@@ -347,6 +350,7 @@
install-features-it/pom.xml
generate-features-it/pom.xml
binary-scanner-it/pom.xml
+ springboot-3-tests/pom.xml
diff --git a/liberty-maven-plugin/src/it/springboot-3-tests/pom.xml b/liberty-maven-plugin/src/it/springboot-3-tests/pom.xml
new file mode 100644
index 000000000..321abfb93
--- /dev/null
+++ b/liberty-maven-plugin/src/it/springboot-3-tests/pom.xml
@@ -0,0 +1,30 @@
+
+
+
+ 4.0.0
+
+
+ io.openliberty.tools.it
+ tests
+ 1.0-SNAPSHOT
+
+
+ springboot-3-tests
+ pom
+
+
+ UTF-8
+ UTF-8
+ 17
+ 17
+
+
+
+ springboot-3-appsdirectory-apps-it
+ springboot-3-appsdirectory-dropins-it
+
+
+
\ No newline at end of file
diff --git a/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-apps-it/pom.xml b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-apps-it/pom.xml
new file mode 100644
index 000000000..148318219
--- /dev/null
+++ b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-apps-it/pom.xml
@@ -0,0 +1,158 @@
+
+
+ 4.0.0
+
+ springboot-3-appsdirectory-apps-it
+ 1.0.0.Final
+ jar
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.1.3
+
+
+
+
+ UTF-8
+ UTF-8
+ 17
+ 17
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+
+ javax.xml.bind
+ jaxb-api
+ 2.3.1
+ provided
+
+
+ com.sun.xml.bind
+ jaxb-core
+ 2.3.0.1
+ provided
+
+
+ javax.activation
+ activation
+ 1.1.1
+ provided
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ exec
+
+
+
+
+ io.openliberty.tools
+ liberty-maven-plugin
+ @pom.version@
+
+
+
+ test
+ src/test/resources/server.xml
+
+ com.ibm.websphere.appserver.runtime
+ wlp-jakartaee10
+ 23.0.0.10
+ zip
+
+ apps
+ spring-boot-project
+
+
+
+
+ stop-server-before-clean
+ pre-clean
+
+ stop
+
+
+
+ create-server
+ prepare-package
+
+ install-server
+ create
+ install-feature
+
+
+
+ install-apps
+ package
+
+ deploy
+
+
+
+ test-start-server
+ pre-integration-test
+
+ test-start
+
+
+
+ test-stop-server
+ post-integration-test
+
+ test-stop
+
+
+
+
+
+
+ maven-failsafe-plugin
+ 3.1.2
+
+ alphabetical
+
+
+
+ default-integration-test
+ integration-test
+
+ integration-test
+
+
+
+ default-verify
+ verify
+
+ verify
+
+
+
+
+
+
+
+
diff --git a/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-apps-it/src/main/java/application/SpringBootApp.java b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-apps-it/src/main/java/application/SpringBootApp.java
new file mode 100644
index 000000000..3612be4a9
--- /dev/null
+++ b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-apps-it/src/main/java/application/SpringBootApp.java
@@ -0,0 +1,35 @@
+/**
+ * (C) Copyright IBM Corporation 2023.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package application;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@SpringBootApplication
+@RestController
+public class SpringBootApp {
+ public static void main(String[] args) {
+ SpringApplication.run(SpringBootApp.class, args);
+ }
+
+ @RequestMapping("/spring")
+ public String hello() {
+ return "HELLO SPRING BOOT!!";
+ }
+}
\ No newline at end of file
diff --git a/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-apps-it/src/test/java/application/InstallSpringBoot30AppIT.java b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-apps-it/src/test/java/application/InstallSpringBoot30AppIT.java
new file mode 100644
index 000000000..2525e2121
--- /dev/null
+++ b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-apps-it/src/test/java/application/InstallSpringBoot30AppIT.java
@@ -0,0 +1,37 @@
+/**
+ * (C) Copyright IBM Corporation 2023.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package application;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import org.junit.Test;
+
+public class InstallSpringBoot30AppIT {
+
+ @Test
+ public void testThinApplicationExistsInAppsDirectory() throws Exception {
+
+ File f = new File("target/liberty/wlp/usr/servers/test/apps/thin-springboot-3-appsdirectory-apps-it-1.0.0.Final-exec.jar");
+ assertTrue(f.getCanonicalFile() + " doesn't exist. Plugin failed to place the file at right destination.", f.exists());
+ }
+
+ @Test
+ public void testLibIndexCacheExists() throws Exception {
+ File f = new File("target/liberty/wlp/usr/shared/resources/lib.index.cache");
+ assertTrue(f.getCanonicalFile()+ " doesn't exist. Plugin failed to place the cache directory at right destination.", f.exists());
+ }
+}
\ No newline at end of file
diff --git a/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-apps-it/src/test/java/application/SpringBoot30RestEndpointIT.java b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-apps-it/src/test/java/application/SpringBoot30RestEndpointIT.java
new file mode 100644
index 000000000..ac3123679
--- /dev/null
+++ b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-apps-it/src/test/java/application/SpringBoot30RestEndpointIT.java
@@ -0,0 +1,49 @@
+/**
+ * (C) Copyright IBM Corporation 2023.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package application;
+
+import static org.junit.Assert.*;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import org.junit.Test;
+
+public class SpringBoot30RestEndpointIT {
+
+ @Test
+ public void testSpringRestBootEndpoint() throws Exception {
+
+ URL requestUrl = new URL("http://localhost:9080/spring/");
+ HttpURLConnection conn = (HttpURLConnection) requestUrl.openConnection();
+
+ if (conn != null) {
+ assertEquals("Expected response code not found.", 200, conn.getResponseCode());
+ }
+
+ StringBuffer response = new StringBuffer();
+
+ try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
+ String line;
+ while ((line = in.readLine()) != null) {
+ response.append(line);
+ }
+ }
+ assertEquals("Expected body not found.", "HELLO SPRING BOOT!!", response.toString());
+ }
+}
\ No newline at end of file
diff --git a/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-apps-it/src/test/resources/server.xml b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-apps-it/src/test/resources/server.xml
new file mode 100644
index 000000000..790a7c85a
--- /dev/null
+++ b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-apps-it/src/test/resources/server.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+ springBoot-3.0
+ servlet-6.0
+
+
+
+
+
\ No newline at end of file
diff --git a/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-dropins-it/pom.xml b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-dropins-it/pom.xml
new file mode 100644
index 000000000..d4311e3a2
--- /dev/null
+++ b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-dropins-it/pom.xml
@@ -0,0 +1,153 @@
+
+
+ 4.0.0
+
+ springboot-3-appsdirectory-dropins-it
+ 1.0.0.Final
+ jar
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.1.3
+
+
+
+
+ UTF-8
+ UTF-8
+ 17
+ 17
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+
+ javax.xml.bind
+ jaxb-api
+ 2.3.1
+ provided
+
+
+ com.sun.xml.bind
+ jaxb-core
+ 2.3.0.1
+ provided
+
+
+ javax.activation
+ activation
+ 1.1.1
+ provided
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ io.openliberty.tools
+ liberty-maven-plugin
+ @pom.version@
+
+
+
+ test
+ src/test/resources/server.xml
+
+ io.openliberty
+ openliberty-kernel
+ 23.0.0.10
+ zip
+
+ spring-boot-project
+
+
+
+
+ stop-server-before-clean
+ pre-clean
+
+ stop
+
+
+
+ create-server
+ prepare-package
+
+ install-server
+ create
+
+
+
+ install-apps
+ package
+
+ deploy
+
+
+
+ test-start-server
+ pre-integration-test
+
+ test-start
+
+
+
+ test-stop-server
+ post-integration-test
+
+ test-stop
+
+
+
+
+
+
+ maven-failsafe-plugin
+ 3.1.2
+
+ alphabetical
+
+
+
+ default-integration-test
+ integration-test
+
+ integration-test
+
+
+
+ default-verify
+ verify
+
+ verify
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-dropins-it/src/main/java/application/SpringBootApp.java b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-dropins-it/src/main/java/application/SpringBootApp.java
new file mode 100644
index 000000000..3612be4a9
--- /dev/null
+++ b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-dropins-it/src/main/java/application/SpringBootApp.java
@@ -0,0 +1,35 @@
+/**
+ * (C) Copyright IBM Corporation 2023.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package application;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@SpringBootApplication
+@RestController
+public class SpringBootApp {
+ public static void main(String[] args) {
+ SpringApplication.run(SpringBootApp.class, args);
+ }
+
+ @RequestMapping("/spring")
+ public String hello() {
+ return "HELLO SPRING BOOT!!";
+ }
+}
\ No newline at end of file
diff --git a/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-dropins-it/src/test/java/application/InstallSpringBoot30AppIT.java b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-dropins-it/src/test/java/application/InstallSpringBoot30AppIT.java
new file mode 100644
index 000000000..2e72ae978
--- /dev/null
+++ b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-dropins-it/src/test/java/application/InstallSpringBoot30AppIT.java
@@ -0,0 +1,37 @@
+/**
+ * (C) Copyright IBM Corporation 2023.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package application;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import org.junit.Test;
+
+public class InstallSpringBoot30AppIT {
+
+ @Test
+ public void testThinApplicationExistsInDropinsDirectory() throws Exception {
+
+ File f = new File("target/liberty/wlp/usr/servers/test/dropins/spring/thin-springboot-3-appsdirectory-dropins-it-1.0.0.Final.jar");
+ assertTrue(f.getCanonicalFile() + " doesn't exist. Plugin failed to place the file at right destination.", f.exists());
+ }
+
+ @Test
+ public void testLibIndexCacheExists() throws Exception {
+ File f = new File("target/liberty/wlp/usr/shared/resources/lib.index.cache");
+ assertTrue(f.getCanonicalFile()+ " doesn't exist. Plugin failed to place the cache directory at right destination.", f.exists());
+ }
+}
\ No newline at end of file
diff --git a/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-dropins-it/src/test/java/application/SpringBoot30RestEndpointIT.java b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-dropins-it/src/test/java/application/SpringBoot30RestEndpointIT.java
new file mode 100644
index 000000000..ac3123679
--- /dev/null
+++ b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-dropins-it/src/test/java/application/SpringBoot30RestEndpointIT.java
@@ -0,0 +1,49 @@
+/**
+ * (C) Copyright IBM Corporation 2023.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package application;
+
+import static org.junit.Assert.*;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import org.junit.Test;
+
+public class SpringBoot30RestEndpointIT {
+
+ @Test
+ public void testSpringRestBootEndpoint() throws Exception {
+
+ URL requestUrl = new URL("http://localhost:9080/spring/");
+ HttpURLConnection conn = (HttpURLConnection) requestUrl.openConnection();
+
+ if (conn != null) {
+ assertEquals("Expected response code not found.", 200, conn.getResponseCode());
+ }
+
+ StringBuffer response = new StringBuffer();
+
+ try (BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
+ String line;
+ while ((line = in.readLine()) != null) {
+ response.append(line);
+ }
+ }
+ assertEquals("Expected body not found.", "HELLO SPRING BOOT!!", response.toString());
+ }
+}
\ No newline at end of file
diff --git a/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-dropins-it/src/test/resources/server.xml b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-dropins-it/src/test/resources/server.xml
new file mode 100644
index 000000000..790a7c85a
--- /dev/null
+++ b/liberty-maven-plugin/src/it/springboot-3-tests/springboot-3-appsdirectory-dropins-it/src/test/resources/server.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+ springBoot-3.0
+ servlet-6.0
+
+
+
+
+
\ No newline at end of file
diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/applications/DeployMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/applications/DeployMojo.java
index 4fb56fdcb..01ed846e6 100644
--- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/applications/DeployMojo.java
+++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/applications/DeployMojo.java
@@ -123,9 +123,11 @@ private void installSpringBootApp() throws MojoExecutionException, IOException {
File libIndexCacheTarget = getLibIndexCacheTarget();
validateAppConfig(thinArchiveTarget.getCanonicalPath(), thinArchiveTarget.getName(), project.getArtifactId(), true);
+ installSpringBootFeatureIfNeeded(installDirectory);
invokeSpringBootUtilCommand(installDirectory, fatArchiveSrc.getCanonicalPath(), thinArchiveTarget.getCanonicalPath(), libIndexCacheTarget.getCanonicalPath());
} else {
- throw new MojoExecutionException(fatArchiveSrc.getCanonicalPath() +" file is not an executable archive. "
+ File fatArchive = SpringBootUtil.getSpringBootUberJARLocation(project, getLog()); // fatArchiveSrc can be null - so get location of file to use in message
+ throw new MojoExecutionException(fatArchive.getCanonicalPath() +" file is not an executable archive. "
+ "The repackage goal of the spring-boot-maven-plugin must be configured to run first in order to create the required executable archive.");
}
}
diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/applications/DeployMojoSupport.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/applications/DeployMojoSupport.java
index e1df929ed..7fc8222a8 100644
--- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/applications/DeployMojoSupport.java
+++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/applications/DeployMojoSupport.java
@@ -15,12 +15,15 @@
*/
package io.openliberty.tools.maven.applications;
+import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
+import java.io.InputStreamReader;
import java.text.MessageFormat;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.Validate;
import org.apache.maven.artifact.Artifact;
@@ -37,11 +40,16 @@
import io.openliberty.tools.maven.server.LooseAppSupport;
import io.openliberty.tools.maven.utils.CommonLogger;
import io.openliberty.tools.maven.utils.MavenProjectUtil;
+import io.openliberty.tools.maven.utils.SpringBootUtil;
import io.openliberty.tools.common.plugins.config.ApplicationXmlDocument;
import io.openliberty.tools.common.plugins.config.LooseApplication;
import io.openliberty.tools.common.plugins.config.LooseConfigData;
import io.openliberty.tools.common.plugins.config.ServerConfigDocument;
import io.openliberty.tools.common.plugins.util.DevUtil;
+import io.openliberty.tools.common.plugins.util.InstallFeatureUtil;
+import io.openliberty.tools.common.plugins.util.InstallFeatureUtil.ProductProperties;
+import io.openliberty.tools.common.plugins.util.OSUtil;
+import io.openliberty.tools.common.plugins.util.PluginExecutionException;
/**
* Support for installing and deploying applications to a Liberty server.
@@ -474,6 +482,70 @@ protected void invokeSpringBootUtilCommand(File installDirectory, String fatArch
springBootUtilTask.execute();
}
+ protected boolean isUtilityAvailable(File installDirectory, String utilityName) {
+ String utilFileName = OSUtil.isWindows() ? utilityName+".bat" : utilityName;
+ File installUtil = new File(installDirectory, "bin/"+utilFileName);
+ return installUtil.exists();
+ }
+
+ protected void installSpringBootFeatureIfNeeded(File installDirectory) throws MojoExecutionException {
+ Process pr = null;
+ BufferedReader in = null;
+ try {
+ if (!isUtilityAvailable(installDirectory, "springBootUtility") && isUtilityAvailable(installDirectory, "featureUtility")) {
+ String fileSuffix = OSUtil.isWindows() ? ".bat" : "";
+ File installUtil = new File(installDirectory, "bin/featureUtility"+fileSuffix);
+
+ // only install springBoot feature that matches required version
+ int springBootMajorVersion = SpringBootUtil.getSpringBootMavenPluginVersion(project);
+ String sbFeature = SpringBootUtil.getLibertySpringBootFeature(springBootMajorVersion);
+ if (sbFeature != null) {
+ getLog().info("Required springBootUtility not found in Liberty installation. Installing feature "+sbFeature+" to enable it.");
+ StringBuilder sb = new StringBuilder();
+ String installUtilCmd;
+ if (OSUtil.isWindows()) {
+ installUtilCmd = "\"" + installDirectory + "\\bin\\featureUtility.bat\"";
+ } else {
+ installUtilCmd = installDirectory + "/bin/featureUtility";
+ }
+ ProcessBuilder pb = new ProcessBuilder(installUtilCmd, "installFeature", sbFeature, "--acceptLicense");
+ pr = pb.start();
+
+ in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
+ String line;
+ while ((line = in.readLine()) != null) {
+ sb.append(line).append(System.lineSeparator());
+ }
+
+ boolean exited = pr.waitFor(300, TimeUnit.SECONDS);
+ if(!exited) { // Command did not exit in time
+ throw new MojoExecutionException("featureUtility command timed out");
+ }
+
+ int exitValue = pr.exitValue();
+ if (exitValue != 0) {
+ throw new MojoExecutionException("featureUtility exited with return code " + exitValue +". The featureUtility command run was `"+installUtil+" installFeature "+sbFeature+" --acceptLicense`");
+ }
+ }
+ }
+ } catch (IOException ex) {
+ throw new MojoExecutionException("featureUtility error: " + ex);
+ } catch (InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ throw new MojoExecutionException("featureUtility error: " + ex);
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ }
+ }
+ if (pr != null) {
+ pr.destroy();
+ }
+ }
+ }
+
protected boolean matches(Artifact artifact, Dependency assemblyArtifact) {
return artifact.getGroupId().equals(assemblyArtifact.getGroupId())
&& artifact.getArtifactId().equals(assemblyArtifact.getArtifactId())
diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/utils/MavenProjectUtil.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/utils/MavenProjectUtil.java
index a18899daa..514ca7990 100644
--- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/utils/MavenProjectUtil.java
+++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/utils/MavenProjectUtil.java
@@ -207,7 +207,10 @@ public static File getManifestFile(MavenProject proj, String pluginArtifactId) {
*/
public static int getMajorPluginVersion(MavenProject project, String pluginKey) {
Plugin plugin = project.getPlugin(pluginKey);
- return Character.getNumericValue(plugin.getVersion().charAt(0));
+ if (plugin != null) {
+ return Character.getNumericValue(plugin.getVersion().charAt(0));
+ }
+ return 0;
}
}
diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/utils/SpringBootUtil.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/utils/SpringBootUtil.java
index bfa23ee63..aaf608b67 100644
--- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/utils/SpringBootUtil.java
+++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/utils/SpringBootUtil.java
@@ -1,5 +1,5 @@
/**
- * (C) Copyright IBM Corporation 2018, 2020.
+ * (C) Copyright IBM Corporation 2018, 2023.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,13 +25,22 @@
public class SpringBootUtil {
/**
- * Checks that the plugin exists for the given pluginKey.
+ * Checks that the spring-boot-maven-plugin repackage goal execution exists.
*
*/
public static boolean doesSpringBootRepackageGoalExecutionExist(MavenProject project) {
return MavenProjectUtil.doesPluginGoalExecutionExist(project, "org.springframework.boot:spring-boot-maven-plugin", "repackage");
}
+ /**
+ * Returns the major version number of the configured spring-boot-maven-plugin, or zero if not configured.
+ *
+ */
+ public static int getSpringBootMavenPluginVersion(MavenProject project) {
+ return MavenProjectUtil.getMajorPluginVersion(project, "org.springframework.boot:spring-boot-maven-plugin");
+
+ }
+
/**
* Read the value of the classifier configuration parameter from the
* spring-boot-maven-plugin
@@ -69,7 +78,11 @@ public static File getSpringBootUberJAR(MavenProject project, Log log) {
return fatArchive;
}
- log.warn("Spring Boot Uber JAR was not found in expected location: " + fatArchive.getAbsolutePath());
+ if (fatArchive.exists()) {
+ log.warn("The file at the following location is not a Spring Boot Uber JAR: " + fatArchive.getAbsolutePath());
+ } else {
+ log.warn("Spring Boot Uber JAR was not found in expected location: " + fatArchive.getAbsolutePath());
+ }
return null;
}
@@ -97,4 +110,23 @@ public static File getSpringBootUberJARLocation(MavenProject project, Log log) {
}
+ /*
+ * Returns the required Open Liberty springBoot feature given the passed springBootMajorVersion.
+ */
+ public static String getLibertySpringBootFeature(int springBootMajorVersion) {
+ if (isSpringBoot1(springBootMajorVersion)) {
+ return "springBoot-1.5";
+ } else if (isSpringBoot2plus(springBootMajorVersion)) {
+ return "springBoot-"+springBootMajorVersion+".0";
+ }
+ return null;
+ }
+
+ public static boolean isSpringBoot1(int springBootMajorVersion) {
+ return springBootMajorVersion == 1;
+ }
+
+ public static boolean isSpringBoot2plus(int springBootMajorVersion) {
+ return springBootMajorVersion > 1;
+ }
}