From 0dcc92eb237bea33fae970e7f4bb6729e61aea06 Mon Sep 17 00:00:00 2001 From: Cheryl King Date: Wed, 20 Sep 2023 18:15:38 -0500 Subject: [PATCH 01/12] Add support for SpringBoot 3 --- .github/workflows/gradle.yml | 4 +- docs/spring-boot-support.md | 8 +- .../tools/gradle/LibertyTasks.groovy | 6 +- .../gradle/tasks/AbstractLibertyTask.groovy | 38 +++++- .../gradle/tasks/AbstractServerTask.groovy | 9 +- .../tools/gradle/tasks/DeployTask.groovy | 24 ++-- .../gradle/TestSpringBootApplication30.groovy | 122 ++++++++++++++++++ .../sample.springboot3/settings.gradle | 1 + .../java/com/ibm/test/springboot/App.java | 18 +++ .../src/main/liberty/config/server30.xml | 14 ++ .../src/main/resources/application.properties | 0 .../test_spring_boot_apps_30.gradle | 39 ++++++ ...test_spring_boot_classifier_apps_30.gradle | 43 ++++++ .../test_spring_boot_dropins_30.gradle | 48 +++++++ .../test_spring_boot_war_apps_30.gradle | 39 ++++++ ..._spring_boot_war_classifier_apps_30.gradle | 43 ++++++ 16 files changed, 431 insertions(+), 25 deletions(-) create mode 100644 src/test/groovy/io/openliberty/tools/gradle/TestSpringBootApplication30.groovy create mode 100644 src/test/resources/sample.springboot3/settings.gradle create mode 100644 src/test/resources/sample.springboot3/src/main/java/com/ibm/test/springboot/App.java create mode 100644 src/test/resources/sample.springboot3/src/main/liberty/config/server30.xml create mode 100644 src/test/resources/sample.springboot3/src/main/resources/application.properties create mode 100644 src/test/resources/sample.springboot3/test_spring_boot_apps_30.gradle create mode 100644 src/test/resources/sample.springboot3/test_spring_boot_classifier_apps_30.gradle create mode 100644 src/test/resources/sample.springboot3/test_spring_boot_dropins_30.gradle create mode 100644 src/test/resources/sample.springboot3/test_spring_boot_war_apps_30.gradle create mode 100644 src/test/resources/sample.springboot3/test_spring_boot_war_classifier_apps_30.gradle diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 86a805d9c..8b07fedd2 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -70,7 +70,7 @@ jobs: # Run tests - name: Run tests with Gradle on Ubuntu run: - ./gradlew clean install check -Druntime=${{ matrix.RUNTIME }} -DruntimeVersion="${{ matrix.RUNTIME_VERSION }}" --stacktrace --info + ./gradlew clean install check -P"test.exclude"="**/TestSpringBootApplication30*" -Druntime=${{ matrix.RUNTIME }} -DruntimeVersion="${{ matrix.RUNTIME_VERSION }}" --stacktrace --info # Copy build reports and upload artifact if build failed - name: Copy build/report/tests/test for upload if: ${{ failure() }} @@ -149,7 +149,7 @@ jobs: - name: Run tests with Gradle on Windows working-directory: C:/ci.gradle # LibertyTest is excluded because test0_run hangs - run: ./gradlew clean install check -P"test.exclude"="**/Polling*,**/LibertyTest*,**/GenerateFeaturesTest*" -Druntime=${{ matrix.RUNTIME }} -DruntimeVersion="${{ matrix.RUNTIME_VERSION }}" --stacktrace --info --no-daemon + run: ./gradlew clean install check -P"test.exclude"="**/Polling*,**/LibertyTest*,**/GenerateFeaturesTest*,**/TestSpringBootApplication30*" -Druntime=${{ matrix.RUNTIME }} -DruntimeVersion="${{ matrix.RUNTIME_VERSION }}" --stacktrace --info --no-daemon timeout-minutes: 75 # Copy build reports and upload artifact if build failed - name: Copy build/report/tests/test for upload diff --git a/docs/spring-boot-support.md b/docs/spring-boot-support.md index af2000ec5..69c939372 100644 --- a/docs/spring-boot-support.md +++ b/docs/spring-boot-support.md @@ -18,18 +18,20 @@ The `server.xml` file provided by the `configDirectory` or `serverXmlFile` param | 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.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. ### Gradle Compatibility -There is a known build conflict that Spring Boot Gradle plugin 1.5.x is incompatible with Gradle 5.x. As the Spring Boot 1.5.x plugin will not be updated to support Gradle 5.x, consider upgrading the Spring Boot plugin or downgrading Gradle. +The Spring Boot Gradle plugin 3.x requires Java 17 and a minimum of Gradle 7.5. There is a known build conflict that Spring Boot Gradle plugin 1.5.x is incompatible with Gradle 5.x. As the Spring Boot 1.5.x plugin will not be updated to support Gradle 5.x, consider upgrading the Spring Boot plugin or downgrading Gradle. | Spring Boot version | Advised Gradle version | | ------------------- | -------------- | -| 2.0.x | 4.x+ | +| 3.x | 7.5+ or 8.x | +| 2.x | 4.x+ | | 1.5.x | 2.9 or 3.x (Although we observed compatibility up to 4.10, proceed at your own risk)| Refer to the [current release Spring docs](https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/html/#introduction) to be advised on Gradle compatibility for the latest Spring Boot Gradle plugin. \ No newline at end of file diff --git a/src/main/groovy/io/openliberty/tools/gradle/LibertyTasks.groovy b/src/main/groovy/io/openliberty/tools/gradle/LibertyTasks.groovy index 10d896d60..888122d4a 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/LibertyTasks.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/LibertyTasks.groovy @@ -17,6 +17,7 @@ package io.openliberty.tools.gradle import io.openliberty.tools.gradle.extensions.ServerExtension import io.openliberty.tools.gradle.tasks.AbstractServerTask +import io.openliberty.tools.gradle.tasks.AbstractLibertyTask import org.gradle.api.Project import org.gradle.api.tasks.TaskDependency @@ -92,8 +93,9 @@ public class LibertyTasks { } project.deploy { - if (AbstractServerTask.findSpringBootVersion(project) != null) { - if (springBootVersion?.startsWith('2')) { + String springBootVersion = AbstractServerTask.findSpringBootVersion(project) + if (springBootVersion != null) { + if (AbstractLibertyTask.isSpringBoot2plus(springBootVersion)) { dependsOn 'bootJar' } else { //version 1.5.x dependsOn 'bootRepackage' diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractLibertyTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractLibertyTask.groovy index ec377ae0b..d43ec2a31 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractLibertyTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractLibertyTask.groovy @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corporation 2017, 2021. + * (C) Copyright IBM Corporation 2017, 2023. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -78,19 +78,51 @@ abstract class AbstractLibertyTask extends DefaultTask { return version } + protected static boolean isSpringBoot1(String springBootVersion) { + if (springBootVersion == null) { + return false + } + return springBootVersion.startsWith('1.') + } + + protected static boolean isSpringBoot2plus(String springBootVersion) { + if (springBootVersion == null) { + return false + } + if (springBootVersion.contains('.')) { + String majorVersion = springBootVersion.substring(0,springBootVersion.indexOf('.')) + try { + int majorVersionNumber = Integer.parseInt(majorVersion) + return majorVersionNumber > 1 + } catch (NumberFormatException e) { + } + } + return false + } + + protected static String getLibertySpringBootFeature(String springBootVersion) { + if (isSpringBoot1(springBootVersion)) { + return "springBoot-1.5" + } else if (isSpringBoot2plus(springBootVersion)) { + String majorVersion = springBootVersion.substring(0,springBootVersion.indexOf('.')) + return "springBoot-"+majorVersion+".0" + } + return null + } + protected static Task findSpringBootTask(Project project, String springBootVersion) { if (springBootVersion == null) { return null } Task task //Do not change the order of war and java - if (springBootVersion.startsWith('2.')) { + if (isSpringBoot2plus(springBootVersion)) { if (project.plugins.hasPlugin('war')) { task = project.bootWar } else if (project.plugins.hasPlugin('java')) { task = project.bootJar } - } else if (springBootVersion.startsWith('1.')) { + } else if (isSpringBoot1(springBootVersion)) { if (project.plugins.hasPlugin('war')) { task = project.war } else if (project.plugins.hasPlugin('java')) { diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractServerTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractServerTask.groovy index 5fbedf11d..4dfc079b0 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractServerTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractServerTask.groovy @@ -138,10 +138,9 @@ abstract class AbstractServerTask extends AbstractLibertyTask { } protected determineSpringBootBuildTask() { - if (springBootVersion ?. startsWith('2') ) { + if (isSpringBoot2plus(springBootVersion)) { return project.bootJar - } - else if ( springBootVersion ?. startsWith('1') ) { + } else if (isSpringBoot1(springBootVersion)) { return project.bootRepackage } } @@ -564,7 +563,7 @@ abstract class AbstractServerTask extends AbstractLibertyTask { } protected String getArchiveName(Task task){ - if (springBootVersion?.startsWith('1')) { + if (isSpringBoot1(springBootVersion)) { task = project.jar } if (server.stripVersion){ @@ -648,7 +647,7 @@ abstract class AbstractServerTask extends AbstractLibertyTask { appList.each { Object appObj -> Node application = new Node(null, 'application') if (appObj instanceof Task) { - if (springBootVersion?.startsWith('1')) { + if (isSpringBoot1(springBootVersion)) { appObj = project.jar } application.appendNode('appsDirectory', appDir) diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/DeployTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/DeployTask.groovy index a1a2f2039..9e4e386de 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/DeployTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/DeployTask.groovy @@ -165,10 +165,10 @@ class DeployTask extends AbstractServerTask { private String getArchiveOutputPath() { String archiveOutputPath; - if (springBootVersion.startsWith('2.')) { + if (isSpringBoot2plus(springBootVersion)) { archiveOutputPath = springBootTask.archivePath.getAbsolutePath() } - else if(springBootVersion.startsWith('1.')) { + else if(isSpringBoot1(springBootVersion)) { archiveOutputPath = springBootTask.archivePath.getAbsolutePath() if (project.bootRepackage.classifier != null && !project.bootRepackage.classifier.isEmpty()) { archiveOutputPath = archiveOutputPath.substring(0, archiveOutputPath.lastIndexOf(".")) + "-" + project.bootRepackage.classifier + "." + springBootTask.getArchiveExtension().get() @@ -223,14 +223,18 @@ class DeployTask extends AbstractServerTask { String fileSuffix = isWindows ? ".bat" : "" File installUtil = new File(getInstallDir(project), "bin/installUtility"+fileSuffix) - def installCommand = installUtil.toString() + " install springBoot-1.5 springBoot-2.0 --acceptLicense" - def sbuff = new StringBuffer() - def proc = installCommand.execute() - proc.consumeProcessOutput(sbuff, sbuff) - proc.waitFor() - logger.info(sbuff.toString()) - if (proc.exitValue()!=0) { - throw new GradleException("Error installing required spring boot support features.") + // only install springBoot feature that matches required version + String sbFeature = getLibertySpringBootFeature(springBootVersion) + if (sbFeature != null) { + def installCommand = installUtil.toString() + " install " + sbFeature + " --acceptLicense" + def sbuff = new StringBuffer() + def proc = installCommand.execute() + proc.consumeProcessOutput(sbuff, sbuff) + proc.waitFor() + logger.info(sbuff.toString()) + if (proc.exitValue()!=0) { + throw new GradleException("Error installing required spring boot support feature: "+sbFeature) + } } } } diff --git a/src/test/groovy/io/openliberty/tools/gradle/TestSpringBootApplication30.groovy b/src/test/groovy/io/openliberty/tools/gradle/TestSpringBootApplication30.groovy new file mode 100644 index 000000000..3572f9ace --- /dev/null +++ b/src/test/groovy/io/openliberty/tools/gradle/TestSpringBootApplication30.groovy @@ -0,0 +1,122 @@ +/* + * (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 io.openliberty.tools.gradle + +import groovy.xml.QName +import org.junit.* +import org.junit.rules.TestName + +public class TestSpringBootApplication30 extends AbstractIntegrationTest{ + static File resourceDir = new File("build/resources/test/sample.springboot3") + static String buildFilename = "springboot_3_archive.gradle" + + File buildDir; + + @Rule + public TestName testName = new TestName(); + + @Before + public void setup() { + buildDir = new File(integTestDir, "/" + testName.getMethodName()) + createDir(buildDir) + createTestProject(buildDir, resourceDir, testName.getMethodName() + '.gradle') + } + + @After + public void tearDown() throws Exception { + runTasks(buildDir,'libertyStop') + } + + + @Test + public void test_spring_boot_apps_30() { + try { + runTasks(buildDir, 'deploy', 'libertyStart') + + String webPage = new URL("http://localhost:9080").getText() + Assert.assertEquals("Did not get expected http response.","Hello!", webPage) + Assert.assertTrue('defaultServer/dropins has app deployed', + new File(buildDir, 'build/wlp/usr/servers/defaultServer/dropins').list().size() == 0) + Assert.assertTrue('no app in apps folder', + new File(buildDir, "build/wlp/usr/servers/defaultServer/apps/thin-${testName.getMethodName()}-1.0-SNAPSHOT.jar").exists() ) + } catch (Exception e) { + throw new AssertionError ("Fail on task deploy.", e) + } + } + + @Test + public void test_spring_boot_classifier_apps_30() { + try { + runTasks(buildDir, 'deploy', 'libertyStart') + + String webPage = new URL("http://localhost:9080").getText() + Assert.assertEquals("Did not get expected http response.","Hello!", webPage) + Assert.assertTrue('defaultServer/dropins has app deployed', + new File(buildDir, 'build/wlp/usr/servers/defaultServer/dropins').list().size() == 0) + Assert.assertTrue('no app in apps folder', + new File(buildDir, "build/wlp/usr/servers/defaultServer/apps/thin-${testName.getMethodName()}-1.0-SNAPSHOT-test.jar").exists() ) + } catch (Exception e) { + throw new AssertionError ("Fail on task deploy.", e) + } + } + + @Test + public void test_spring_boot_war_apps_30() { + try { + runTasks(buildDir, 'deploy', 'libertyStart') + + String webPage = new URL("http://localhost:9080").getText() + Assert.assertEquals("Did not get expected http response.","Hello!", webPage) + Assert.assertTrue('defaultServer/dropins has app deployed', + new File(buildDir, 'build/wlp/usr/servers/defaultServer/dropins').list().size() == 0) + Assert.assertTrue('no app in apps folder', + new File(buildDir, "build/wlp/usr/servers/defaultServer/apps/thin-${testName.getMethodName()}-1.0-SNAPSHOT.war").exists() ) + } catch (Exception e) { + throw new AssertionError ("Fail on task deploy.", e) + } + } + + @Test + public void test_spring_boot_war_classifier_apps_30() { + try { + runTasks(buildDir, 'deploy', 'libertyStart') + + String webPage = new URL("http://localhost:9080").getText() + Assert.assertEquals("Did not get expected http response.","Hello!", webPage) + Assert.assertTrue('defaultServer/dropins has app deployed', + new File(buildDir, 'build/wlp/usr/servers/defaultServer/dropins').list().size() == 0) + Assert.assertTrue('no app in apps folder', + new File(buildDir, "build/wlp/usr/servers/defaultServer/apps/thin-${testName.getMethodName()}-1.0-SNAPSHOT-test.war").exists() ) + } catch (Exception e) { + throw new AssertionError ("Fail on task deploy.", e) + } + } + + @Test + public void test_spring_boot_dropins_30() { + try { + runTasks(buildDir, 'deploy', 'libertyStart') + String webPage = new URL("http://localhost:9080").getText() + Assert.assertEquals("Did not get expected http response.","Hello!", webPage) + Assert.assertTrue('defaultServer/dropins/spring has no app', + new File(buildDir, "build/wlp/usr/servers/defaultServer/dropins/spring/thin-${testName.getMethodName()}-1.0-SNAPSHOT.jar").exists()) + Assert.assertTrue('apps folder should be empty', + new File(buildDir, "build/wlp/usr/servers/defaultServer/apps").list().size() == 0 ) + } catch (Exception e) { + throw new AssertionError ("Fail on task deploy.", e) + } + } +} diff --git a/src/test/resources/sample.springboot3/settings.gradle b/src/test/resources/sample.springboot3/settings.gradle new file mode 100644 index 000000000..c2d3edc19 --- /dev/null +++ b/src/test/resources/sample.springboot3/settings.gradle @@ -0,0 +1 @@ +//Empty \ No newline at end of file diff --git a/src/test/resources/sample.springboot3/src/main/java/com/ibm/test/springboot/App.java b/src/test/resources/sample.springboot3/src/main/java/com/ibm/test/springboot/App.java new file mode 100644 index 000000000..e7688517a --- /dev/null +++ b/src/test/resources/sample.springboot3/src/main/java/com/ibm/test/springboot/App.java @@ -0,0 +1,18 @@ +package com.ibm.test.springboot; + +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 App { + public static void main(String[] args) { + SpringApplication.run(App.class, args); + } + @RequestMapping("/") + public String index() { + return "Hello!"; + } +} diff --git a/src/test/resources/sample.springboot3/src/main/liberty/config/server30.xml b/src/test/resources/sample.springboot3/src/main/liberty/config/server30.xml new file mode 100644 index 000000000..a9f10f6b5 --- /dev/null +++ b/src/test/resources/sample.springboot3/src/main/liberty/config/server30.xml @@ -0,0 +1,14 @@ + + + + springBoot-3.0 + servlet-6.0 + + + + + + + diff --git a/src/test/resources/sample.springboot3/src/main/resources/application.properties b/src/test/resources/sample.springboot3/src/main/resources/application.properties new file mode 100644 index 000000000..e69de29bb diff --git a/src/test/resources/sample.springboot3/test_spring_boot_apps_30.gradle b/src/test/resources/sample.springboot3/test_spring_boot_apps_30.gradle new file mode 100644 index 000000000..3cb20f397 --- /dev/null +++ b/src/test/resources/sample.springboot3/test_spring_boot_apps_30.gradle @@ -0,0 +1,39 @@ +buildscript { + ext { + springBootVersion = '3.1.3' + } + repositories { + mavenLocal() + mavenCentral() + maven { + url "https://plugins.gradle.org/m2/" + } + } + dependencies { + classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}" + classpath "io.openliberty.tools:liberty-gradle-plugin:$lgpVersion" + } +} + +apply plugin: 'java' +apply plugin: 'org.springframework.boot' +apply plugin: 'liberty' + +group = 'liberty.gradle' +version = '1.0-SNAPSHOT' +sourceCompatibility = 17 + +repositories { + mavenCentral() +} +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") + testImplementation('org.springframework.boot:spring-boot-starter-test') + libertyRuntime group: runtimeGroup, name: runtimeArtifactId, version: runtimeVersion +} + +liberty { + server { + serverXmlFile = file("src/main/liberty/config/server30.xml") + } +} \ No newline at end of file diff --git a/src/test/resources/sample.springboot3/test_spring_boot_classifier_apps_30.gradle b/src/test/resources/sample.springboot3/test_spring_boot_classifier_apps_30.gradle new file mode 100644 index 000000000..db31d7330 --- /dev/null +++ b/src/test/resources/sample.springboot3/test_spring_boot_classifier_apps_30.gradle @@ -0,0 +1,43 @@ +buildscript { + ext { + springBootVersion = '3.1.3' + } + repositories { + mavenLocal() + mavenCentral() + maven { + url "https://plugins.gradle.org/m2/" + } + } + dependencies { + classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}" + classpath "io.openliberty.tools:liberty-gradle-plugin:$lgpVersion" + } +} + +apply plugin: 'java' +apply plugin: 'org.springframework.boot' +apply plugin: 'liberty' + +group = 'liberty.gradle' +version = '1.0-SNAPSHOT' +sourceCompatibility = 17 + +repositories { + mavenCentral() +} +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") + testImplementation('org.springframework.boot:spring-boot-starter-test') + libertyRuntime group: runtimeGroup, name: runtimeArtifactId, version: runtimeVersion +} + +bootJar { + archiveClassifier = 'test' +} + +liberty { + server { + serverXmlFile = file("src/main/liberty/config/server30.xml") + } +} diff --git a/src/test/resources/sample.springboot3/test_spring_boot_dropins_30.gradle b/src/test/resources/sample.springboot3/test_spring_boot_dropins_30.gradle new file mode 100644 index 000000000..4cd2e1cc8 --- /dev/null +++ b/src/test/resources/sample.springboot3/test_spring_boot_dropins_30.gradle @@ -0,0 +1,48 @@ +buildscript { + ext { + springBootVersion = '3.1.3' + } + repositories { + mavenLocal() + mavenCentral() + maven { + url "https://plugins.gradle.org/m2/" + } + } + dependencies { + classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}" + classpath "io.openliberty.tools:liberty-gradle-plugin:$lgpVersion" + } +} + +apply plugin: 'java' +apply plugin: 'org.springframework.boot' +apply plugin: 'liberty' + +group = 'liberty.gradle' +version = '1.0-SNAPSHOT' +sourceCompatibility = 17 + +repositories { + mavenCentral() +} +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") + testImplementation('org.springframework.boot:spring-boot-starter-test') + libertyRuntime group: runtimeGroup, name: runtimeArtifactId, version: runtimeVersion +} + + +liberty { + server { + serverXmlFile = file("src/main/liberty/config/server30.xml") + install.useOpenLiberty = false + looseApplication = false + deploy { + dropins = [bootJar] + } + features { + acceptLicense = true + } + } +} diff --git a/src/test/resources/sample.springboot3/test_spring_boot_war_apps_30.gradle b/src/test/resources/sample.springboot3/test_spring_boot_war_apps_30.gradle new file mode 100644 index 000000000..62ddb41a2 --- /dev/null +++ b/src/test/resources/sample.springboot3/test_spring_boot_war_apps_30.gradle @@ -0,0 +1,39 @@ +buildscript { + ext { + springBootVersion = '3.1.3' + } + repositories { + mavenLocal() + mavenCentral() + maven { + url "https://plugins.gradle.org/m2/" + } + } + dependencies { + classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}" + classpath "io.openliberty.tools:liberty-gradle-plugin:$lgpVersion" + } +} + +apply plugin: 'war' +apply plugin: 'org.springframework.boot' +apply plugin: 'liberty' + +group = 'liberty.gradle' +version = '1.0-SNAPSHOT' +sourceCompatibility = 17 + +repositories { + mavenCentral() +} +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") + testImplementation('org.springframework.boot:spring-boot-starter-test') + libertyRuntime group: runtimeGroup, name: runtimeArtifactId, version: runtimeVersion +} + +liberty { + server { + serverXmlFile = file("src/main/liberty/config/server30.xml") + } +} \ No newline at end of file diff --git a/src/test/resources/sample.springboot3/test_spring_boot_war_classifier_apps_30.gradle b/src/test/resources/sample.springboot3/test_spring_boot_war_classifier_apps_30.gradle new file mode 100644 index 000000000..0f71363c0 --- /dev/null +++ b/src/test/resources/sample.springboot3/test_spring_boot_war_classifier_apps_30.gradle @@ -0,0 +1,43 @@ +buildscript { + ext { + springBootVersion = '3.1.3' + } + repositories { + mavenLocal() + mavenCentral() + maven { + url "https://plugins.gradle.org/m2/" + } + } + dependencies { + classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}" + classpath "io.openliberty.tools:liberty-gradle-plugin:$lgpVersion" + } +} + +apply plugin: 'war' +apply plugin: 'org.springframework.boot' +apply plugin: 'liberty' + +group = 'liberty.gradle' +version = '1.0-SNAPSHOT' +sourceCompatibility = 17 + +repositories { + mavenCentral() +} +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") + testImplementation('org.springframework.boot:spring-boot-starter-test') + libertyRuntime group: runtimeGroup, name: runtimeArtifactId, version: runtimeVersion +} + +bootWar { + archiveClassifier = 'test' +} + +liberty { + server { + serverXmlFile = file("src/main/liberty/config/server30.xml") + } +} \ No newline at end of file From c92a60276fecb5f6359f619aa353e4c15a1bfce1 Mon Sep 17 00:00:00 2001 From: Cheryl King Date: Thu, 21 Sep 2023 11:56:31 -0500 Subject: [PATCH 02/12] Use openliberty-runtime in test case to get past error --- .../sample.springboot3/test_spring_boot_apps_30.gradle | 2 +- .../test_spring_boot_classifier_apps_30.gradle | 2 +- .../test_spring_boot_dropins_30.gradle | 10 +++++----- .../test_spring_boot_war_apps_30.gradle | 2 +- .../test_spring_boot_war_classifier_apps_30.gradle | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/test/resources/sample.springboot3/test_spring_boot_apps_30.gradle b/src/test/resources/sample.springboot3/test_spring_boot_apps_30.gradle index 3cb20f397..2a4aec6a6 100644 --- a/src/test/resources/sample.springboot3/test_spring_boot_apps_30.gradle +++ b/src/test/resources/sample.springboot3/test_spring_boot_apps_30.gradle @@ -29,7 +29,7 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") testImplementation('org.springframework.boot:spring-boot-starter-test') - libertyRuntime group: runtimeGroup, name: runtimeArtifactId, version: runtimeVersion + libertyRuntime group: 'io.openliberty', name: 'openliberty-runtime', version: '23.0.0.9' } liberty { diff --git a/src/test/resources/sample.springboot3/test_spring_boot_classifier_apps_30.gradle b/src/test/resources/sample.springboot3/test_spring_boot_classifier_apps_30.gradle index db31d7330..099f77809 100644 --- a/src/test/resources/sample.springboot3/test_spring_boot_classifier_apps_30.gradle +++ b/src/test/resources/sample.springboot3/test_spring_boot_classifier_apps_30.gradle @@ -29,7 +29,7 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") testImplementation('org.springframework.boot:spring-boot-starter-test') - libertyRuntime group: runtimeGroup, name: runtimeArtifactId, version: runtimeVersion + libertyRuntime group: 'io.openliberty', name: 'openliberty-runtime', version: '23.0.0.9' } bootJar { diff --git a/src/test/resources/sample.springboot3/test_spring_boot_dropins_30.gradle b/src/test/resources/sample.springboot3/test_spring_boot_dropins_30.gradle index 4cd2e1cc8..ecd7b9389 100644 --- a/src/test/resources/sample.springboot3/test_spring_boot_dropins_30.gradle +++ b/src/test/resources/sample.springboot3/test_spring_boot_dropins_30.gradle @@ -29,20 +29,20 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") testImplementation('org.springframework.boot:spring-boot-starter-test') - libertyRuntime group: runtimeGroup, name: runtimeArtifactId, version: runtimeVersion + libertyRuntime group: 'io.openliberty', name: 'openliberty-runtime', version: '23.0.0.9' } liberty { server { serverXmlFile = file("src/main/liberty/config/server30.xml") - install.useOpenLiberty = false + //install.useOpenLiberty = false looseApplication = false deploy { dropins = [bootJar] } - features { - acceptLicense = true - } + // features { + // acceptLicense = true + // } } } diff --git a/src/test/resources/sample.springboot3/test_spring_boot_war_apps_30.gradle b/src/test/resources/sample.springboot3/test_spring_boot_war_apps_30.gradle index 62ddb41a2..8d2d0ffa0 100644 --- a/src/test/resources/sample.springboot3/test_spring_boot_war_apps_30.gradle +++ b/src/test/resources/sample.springboot3/test_spring_boot_war_apps_30.gradle @@ -29,7 +29,7 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") testImplementation('org.springframework.boot:spring-boot-starter-test') - libertyRuntime group: runtimeGroup, name: runtimeArtifactId, version: runtimeVersion + libertyRuntime group: 'io.openliberty', name: 'openliberty-runtime', version: '23.0.0.9' } liberty { diff --git a/src/test/resources/sample.springboot3/test_spring_boot_war_classifier_apps_30.gradle b/src/test/resources/sample.springboot3/test_spring_boot_war_classifier_apps_30.gradle index 0f71363c0..6b043b2ef 100644 --- a/src/test/resources/sample.springboot3/test_spring_boot_war_classifier_apps_30.gradle +++ b/src/test/resources/sample.springboot3/test_spring_boot_war_classifier_apps_30.gradle @@ -29,7 +29,7 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") testImplementation('org.springframework.boot:spring-boot-starter-test') - libertyRuntime group: runtimeGroup, name: runtimeArtifactId, version: runtimeVersion + libertyRuntime group: 'io.openliberty', name: 'openliberty-runtime', version: '23.0.0.9' } bootWar { From 0d76f15b8d3e214fefed334395732fafb394afcb Mon Sep 17 00:00:00 2001 From: wasdevb1 Date: Fri, 6 Oct 2023 14:46:41 +0000 Subject: [PATCH 03/12] prepare for next development iteration --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e2f3feb89..98f1f0457 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ apply plugin: "com.gradle.plugin-publish" archivesBaseName = 'liberty-gradle-plugin' group = 'io.openliberty.tools' -version = '3.7' +version = '3.7.1-SNAPSHOT' repositories { mavenLocal() From 8f3178b331ef213d5893c6b58451d08cd6c55881 Mon Sep 17 00:00:00 2001 From: Cheryl King Date: Mon, 16 Oct 2023 15:44:54 -0500 Subject: [PATCH 04/12] Enhance error handling for tasks (#851) * Enhance error handling for tasks * Update RunTask to not check for installation since it depends on CreateTask --- .../gradle/tasks/AbstractServerTask.groovy | 14 ++++++++++ .../tools/gradle/tasks/CreateTask.groovy | 12 ++++++--- .../tools/gradle/tasks/RunTask.groovy | 21 ++++++++++----- .../tools/gradle/tasks/StatusTask.groovy | 22 +++++++++++++--- .../tools/gradle/tasks/StopTask.groovy | 26 ++++++++++++++----- .../tools/gradle/LibertyTest.groovy | 23 +++++++++++++++- 6 files changed, 98 insertions(+), 20 deletions(-) diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractServerTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractServerTask.groovy index 5fbedf11d..0f5b4cdd8 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractServerTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractServerTask.groovy @@ -208,6 +208,20 @@ abstract class AbstractServerTask extends AbstractLibertyTask { } } + // Use this method to copy over the server.xml file from the defaultServer template. + // Returns true if the server.xml file does not exist and the defaultServer template server.xml file is copied over, false otherwise. + protected boolean copyDefaultServerTemplate(File installDir, File serverDir) { + File serverXmlFile = new File(serverDir, "server.xml") + if (!serverXmlFile.exists()) { + File defaultServerTemplate = new File(installDir, "templates/servers/defaultServer/server.xml") + if (defaultServerTemplate.exists()) { + Files.copy(defaultServerTemplate.toPath(), serverXmlFile.toPath(), StandardCopyOption.REPLACE_EXISTING) + return true; + } + } + return false; + } + protected void copyConfigDirectory() { //merge default server.env with one in config directory File configDirServerEnv = new File(server.configDirectory, "server.env") diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/CreateTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/CreateTask.groovy index cd792daa3..7db22dc41 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/CreateTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/CreateTask.groovy @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corporation 2014, 2022. + * (C) Copyright IBM Corporation 2014, 2023. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ class CreateTask extends AbstractServerTask { group 'Liberty' }) outputs.upToDateWhen { - getServerDir(project).exists() && new File(getServerDir(project), 'server.xml') + getServerDir(project).exists() && (new File(getServerDir(project), 'server.xml')).exists() } } @@ -76,7 +76,9 @@ class CreateTask extends AbstractServerTask { void create() { //Checking etc/server.env for outputDirs Liberty.checkEtcServerEnvProperties(project) - if(!getServerDir(project).exists()){ + File serverDir = getServerDir(project) + File serverXmlFile = new File(serverDir, "server.xml") + if(!serverDir.exists()){ def params = buildLibertyMap(project); if (server.template != null && server.template.length() != 0) { params.put('template', server.template) @@ -85,6 +87,10 @@ class CreateTask extends AbstractServerTask { params.put('noPassword', server.noPassword) } executeServerCommand(project, 'create', params) + } else if (copyDefaultServerTemplate(getInstallDir(project), serverDir)) { + // copied defaultServer template server.xml over for rare case that the server.xml disappears from an existing Liberty server (issue 850) + // if the project contains its own server.xml file, it will get copied over in copyConfigFiles() next + logger.warn("The " + serverXmlFile.getAbsolutePath() + " does not exist. Copying over the defaultServer template server.xml file.") } copyConfigFiles() writeServerPropertiesToXml(project) diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/RunTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/RunTask.groovy index 00c670f39..be34e5aef 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/RunTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/RunTask.groovy @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corporation 2014, 2019. + * (C) Copyright IBM Corporation 2014, 2023. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,10 +32,19 @@ class RunTask extends AbstractServerTask { void run() { addShutdownHook { if (isLibertyInstalledAndValid(project)) { - if (getServerDir(project).exists()) { - ServerTask serverTaskStop = createServerTask(project, "stop"); - serverTaskStop.setUseEmbeddedServer(server.embedded) - serverTaskStop.execute() + File serverDir = getServerDir(project) + if (serverDir.exists()) { + // copy default server template server.xml file over if the server.xml file does not exist so that the server can be stopped + boolean defaultServerTemplateUsed = copyDefaultServerTemplate(getInstallDir(project), serverDir) + File serverXmlFile = new File(getServerDir(project),"server.xml") + if (serverXmlFile.exists()) { + ServerTask serverTaskStop = createServerTask(project, "stop"); + serverTaskStop.setUseEmbeddedServer(server.embedded) + serverTaskStop.execute() + } + if (defaultServerTemplateUsed) { + serverXmlFile.delete() // delete the temporary copy of the server.xml file + } } } } @@ -58,6 +67,6 @@ class RunTask extends AbstractServerTask { run_process.inputStream.eachLine { println it } - } + } } } diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/StatusTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/StatusTask.groovy index d96fc7cec..5f597d0f7 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/StatusTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/StatusTask.groovy @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corporation 2014, 2019. + * (C) Copyright IBM Corporation 2014, 2023. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,9 +29,23 @@ class StatusTask extends AbstractServerTask { @TaskAction void status() { - def status_process = new ProcessBuilder(buildCommand("status")).redirectErrorStream(true).start() - status_process.inputStream.eachLine { - println it + if (isLibertyInstalledAndValid(project)) { + File serverDir = getServerDir(project) + if (serverDir.exists()) { + File serverXmlFile = new File(serverDir,"server.xml") + if (serverXmlFile.exists()) { + def status_process = new ProcessBuilder(buildCommand("status")).redirectErrorStream(true).start() + status_process.inputStream.eachLine { + println it + } + } else { + logger.error ('The server status cannot be checked. There is no server.xml file in the server.') + } + } else { + logger.error ('The server status cannot be checked. The server has not been created.') + } + } else { + logger.error ('The server status cannot be checked. The runtime has not been installed.') } } diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/StopTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/StopTask.groovy index c58de8c80..3522b38b1 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/StopTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/StopTask.groovy @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corporation 2014, 2020. + * (C) Copyright IBM Corporation 2014, 2023. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,12 +31,26 @@ class StopTask extends AbstractServerTask { @TaskAction void stop() { if (isLibertyInstalledAndValid(project)) { - if (getServerDir(project).exists()) { - ServerTask serverTaskStop = createServerTask(project, "stop"); - serverTaskStop.setUseEmbeddedServer(server.embedded) - serverTaskStop.execute() + File serverDir = getServerDir(project) + if (serverDir.exists()) { + File serverXmlFile = new File(serverDir,"server.xml") + boolean defaultServerTemplateUsed = copyDefaultServerTemplate(getInstallDir(project),serverDir) + if (serverXmlFile.exists()) { + ServerTask serverTaskStop = createServerTask(project, "stop"); + serverTaskStop.setUseEmbeddedServer(server.embedded) + serverTaskStop.execute() + } else { + logger.error ('The server cannot be stopped. There is no server.xml file in the server.') + } + + if (defaultServerTemplateUsed) { + logger.warn ('The server.xml file was missing in the server during the stop task. Copied the defaultServer template server.xml file into the server temporarily so the stop task could be completed.') + if (!serverXmlFile.delete()) { + logger.error('Could not delete the server.xml file copied from the defaultServer template after stopping the server.') + } + } } else { - logger.error ('There is no server to stop. The server has not been created.') + logger.error ('There is no server to stop. The server has not been created.') } } else { logger.error ('There is no server to stop. The runtime has not been installed.') diff --git a/src/test/groovy/io/openliberty/tools/gradle/LibertyTest.groovy b/src/test/groovy/io/openliberty/tools/gradle/LibertyTest.groovy index 333d6b89f..e521645cc 100644 --- a/src/test/groovy/io/openliberty/tools/gradle/LibertyTest.groovy +++ b/src/test/groovy/io/openliberty/tools/gradle/LibertyTest.groovy @@ -28,6 +28,7 @@ class LibertyTest extends AbstractIntegrationTest{ static File resourceDir = new File("build/resources/test/liberty-test") static File buildDir = new File(integTestDir, "/liberty-test") static String buildFilename = "build.gradle" + static File serverXmlFile = new File(buildDir, "/build/wlp/usr/servers/LibertyProjectServer/server.xml") @BeforeClass public static void setup() { @@ -180,10 +181,30 @@ class LibertyTest extends AbstractIntegrationTest{ throw new AssertionError ("Fail on task libertyStart after second clean.", e) } + // try deleting the server.xml and see if we can recover + assert serverXmlFile.exists() : 'server.xml file does not exist in LibertyProjectServer' + assert serverXmlFile.delete() : 'server.xml could not be deleted in LibertyProjectServer' + try{ runTasks(buildDir, 'libertyStop') } catch (Exception e) { - throw new AssertionError ("Fail on task libertyStop after libertyStart.", e) + throw new AssertionError ("Fail on task libertyStop after deleting server.xml.", e) + } + + assert !serverXmlFile.exists() : 'server.xml file unexpectedly exists in LibertyProjectServer after libertyStop' + + try{ + runTasks(buildDir, 'libertyStatus') + } catch (Exception e) { + throw new AssertionError ("Fail on task libertyStatus after deleting server.xml.", e) + } + + assert serverXmlFile.exists() : 'server.xml file does not exist in LibertyProjectServer after libertyStatus' + + try{ + runTasks(buildDir, 'clean') + } catch (Exception e) { + throw new AssertionError ("Fail on task clean after deleting server.xml.", e) } } From 1ee28afb6ccb7b6833057d4cd60983c7abfbc825 Mon Sep 17 00:00:00 2001 From: Cheryl King Date: Wed, 18 Oct 2023 16:46:03 -0500 Subject: [PATCH 05/12] Update tests and code to install feature if no springBootUtility found --- .github/workflows/gradle.yml | 10 +++++ .../tools/gradle/tasks/DeployTask.groovy | 16 ++++--- .../gradle/TestSpringBootApplication30.groovy | 14 ++++++ .../main/liberty/alternateConfig/server30.xml | 13 ++++++ .../test_spring_boot_apps_30.gradle | 2 +- ...test_spring_boot_classifier_apps_30.gradle | 2 +- ..._boot_classifier_apps_30_no_feature.gradle | 43 +++++++++++++++++++ .../test_spring_boot_dropins_30.gradle | 2 +- .../test_spring_boot_war_apps_30.gradle | 2 +- ..._spring_boot_war_classifier_apps_30.gradle | 2 +- 10 files changed, 95 insertions(+), 11 deletions(-) create mode 100644 src/test/resources/sample.springboot3/src/main/liberty/alternateConfig/server30.xml create mode 100644 src/test/resources/sample.springboot3/test_spring_boot_classifier_apps_30_no_feature.gradle diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index e92622bc8..ee7c7b374 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -67,6 +67,11 @@ jobs: run: | mvn -V clean install -f ci.ant --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false mvn -V clean install -f ci.common --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false + # Run tests that require Java 17 or later + - name: Run tests that require Java 17 or later + if: ${{ matrix.java == '17' }} + run: + ./gradlew clean install check -P"test.include"="**/TestSpringBootApplication30*" -Druntime=${{ matrix.RUNTIME }} -DruntimeVersion="${{ matrix.RUNTIME_VERSION }}" --stacktrace --info # Run tests - name: Run tests with Gradle on Ubuntu run: @@ -145,6 +150,11 @@ jobs: - name: Install ci.common working-directory: C:/ci.common run: mvn -V clean install --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false + # Run tests that require Java 17 or later + - name: Run tests that require Java 17 or later + if: ${{ matrix.java == '17' }} + run: + ./gradlew clean install check -P"test.include"="**/TestSpringBootApplication30*" -Druntime=${{ matrix.RUNTIME }} -DruntimeVersion="${{ matrix.RUNTIME_VERSION }}" --stacktrace --info --no-daemon # Run tests - name: Run tests with Gradle on Windows working-directory: C:/ci.gradle diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/DeployTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/DeployTask.groovy index 9e4e386de..e79b8b3b0 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/DeployTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/DeployTask.groovy @@ -214,25 +214,29 @@ class DeployTask extends AbstractServerTask { return targetThinAppPath; } - private isSpringBootUtilAvailable() { - new FileNameFinder().getFileNames(new File(getInstallDir(project), "bin").getAbsolutePath(), "springBootUtility*") + private boolean isUtilityAvailable(File installDirectory, String utilityName) { + String utilFileName = isWindows ? utilityName+".bat" : utilityName; + File installUtil = new File(installDirectory, "bin/"+utilFileName); + return installUtil.exists(); } private installSpringBootFeatureIfNeeded() { - if (isClosedLiberty() && !isSpringBootUtilAvailable()) { + File installDir = getInstallDir(project) + if (!isUtilityAvailable(installDir, "springBootUtility") && isUtilityAvailable(installDir, "featureUtility")) { String fileSuffix = isWindows ? ".bat" : "" - File installUtil = new File(getInstallDir(project), "bin/installUtility"+fileSuffix) + File installUtil = new File(installDir, "bin/featureUtility"+fileSuffix) // only install springBoot feature that matches required version String sbFeature = getLibertySpringBootFeature(springBootVersion) if (sbFeature != null) { - def installCommand = installUtil.toString() + " install " + sbFeature + " --acceptLicense" + logger.info("Required springBootUtility not found in Liberty installation. Installing feature "+sbFeature+" to enable it."); + def installCommand = installUtil.toString() + " installFeature " + sbFeature + " --acceptLicense" def sbuff = new StringBuffer() def proc = installCommand.execute() proc.consumeProcessOutput(sbuff, sbuff) proc.waitFor() - logger.info(sbuff.toString()) if (proc.exitValue()!=0) { + logger.error(sbuff.toString()) throw new GradleException("Error installing required spring boot support feature: "+sbFeature) } } diff --git a/src/test/groovy/io/openliberty/tools/gradle/TestSpringBootApplication30.groovy b/src/test/groovy/io/openliberty/tools/gradle/TestSpringBootApplication30.groovy index 3572f9ace..4006d68df 100644 --- a/src/test/groovy/io/openliberty/tools/gradle/TestSpringBootApplication30.groovy +++ b/src/test/groovy/io/openliberty/tools/gradle/TestSpringBootApplication30.groovy @@ -73,6 +73,20 @@ public class TestSpringBootApplication30 extends AbstractIntegrationTest{ } } + @Test + public void test_spring_boot_classifier_apps_30_no_feature() { + try { + runTasks(buildDir, 'deploy') + + Assert.assertTrue('defaultServer/dropins has app deployed', + new File(buildDir, 'build/wlp/usr/servers/defaultServer/dropins').list().size() == 0) + Assert.assertTrue('no app in apps folder', + new File(buildDir, "build/wlp/usr/servers/defaultServer/apps/thin-${testName.getMethodName()}-1.0-SNAPSHOT-test.jar").exists() ) + } catch (Exception e) { + throw new AssertionError ("Fail on task deploy.", e) + } + } + @Test public void test_spring_boot_war_apps_30() { try { diff --git a/src/test/resources/sample.springboot3/src/main/liberty/alternateConfig/server30.xml b/src/test/resources/sample.springboot3/src/main/liberty/alternateConfig/server30.xml new file mode 100644 index 000000000..9c1fd6140 --- /dev/null +++ b/src/test/resources/sample.springboot3/src/main/liberty/alternateConfig/server30.xml @@ -0,0 +1,13 @@ + + + + servlet-6.0 + + + + + + + diff --git a/src/test/resources/sample.springboot3/test_spring_boot_apps_30.gradle b/src/test/resources/sample.springboot3/test_spring_boot_apps_30.gradle index 2a4aec6a6..c2c1b537f 100644 --- a/src/test/resources/sample.springboot3/test_spring_boot_apps_30.gradle +++ b/src/test/resources/sample.springboot3/test_spring_boot_apps_30.gradle @@ -29,7 +29,7 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") testImplementation('org.springframework.boot:spring-boot-starter-test') - libertyRuntime group: 'io.openliberty', name: 'openliberty-runtime', version: '23.0.0.9' + libertyRuntime group: 'io.openliberty', name: 'openliberty-runtime', version: '23.0.0.10' } liberty { diff --git a/src/test/resources/sample.springboot3/test_spring_boot_classifier_apps_30.gradle b/src/test/resources/sample.springboot3/test_spring_boot_classifier_apps_30.gradle index 099f77809..569db154b 100644 --- a/src/test/resources/sample.springboot3/test_spring_boot_classifier_apps_30.gradle +++ b/src/test/resources/sample.springboot3/test_spring_boot_classifier_apps_30.gradle @@ -29,7 +29,7 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") testImplementation('org.springframework.boot:spring-boot-starter-test') - libertyRuntime group: 'io.openliberty', name: 'openliberty-runtime', version: '23.0.0.9' + libertyRuntime group: 'com.ibm.websphere.appserver.runtime', name: 'wlp-jakartaee10', version: '23.0.0.10' } bootJar { diff --git a/src/test/resources/sample.springboot3/test_spring_boot_classifier_apps_30_no_feature.gradle b/src/test/resources/sample.springboot3/test_spring_boot_classifier_apps_30_no_feature.gradle new file mode 100644 index 000000000..40801aba5 --- /dev/null +++ b/src/test/resources/sample.springboot3/test_spring_boot_classifier_apps_30_no_feature.gradle @@ -0,0 +1,43 @@ +buildscript { + ext { + springBootVersion = '3.1.3' + } + repositories { + mavenLocal() + mavenCentral() + maven { + url "https://plugins.gradle.org/m2/" + } + } + dependencies { + classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}" + classpath "io.openliberty.tools:liberty-gradle-plugin:$lgpVersion" + } +} + +apply plugin: 'java' +apply plugin: 'org.springframework.boot' +apply plugin: 'liberty' + +group = 'liberty.gradle' +version = '1.0-SNAPSHOT' +sourceCompatibility = 17 + +repositories { + mavenCentral() +} +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") + testImplementation('org.springframework.boot:spring-boot-starter-test') + libertyRuntime group: 'com.ibm.websphere.appserver.runtime', name: 'wlp-jakartaee10', version: '23.0.0.10' +} + +bootJar { + archiveClassifier = 'test' +} + +liberty { + server { + serverXmlFile = file("src/main/liberty/alternateConfig/server30.xml") + } +} diff --git a/src/test/resources/sample.springboot3/test_spring_boot_dropins_30.gradle b/src/test/resources/sample.springboot3/test_spring_boot_dropins_30.gradle index ecd7b9389..bac019e86 100644 --- a/src/test/resources/sample.springboot3/test_spring_boot_dropins_30.gradle +++ b/src/test/resources/sample.springboot3/test_spring_boot_dropins_30.gradle @@ -29,7 +29,7 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") testImplementation('org.springframework.boot:spring-boot-starter-test') - libertyRuntime group: 'io.openliberty', name: 'openliberty-runtime', version: '23.0.0.9' + libertyRuntime group: 'com.ibm.websphere.appserver.runtime', name: 'wlp-jakartaee10', version: '23.0.0.10' } diff --git a/src/test/resources/sample.springboot3/test_spring_boot_war_apps_30.gradle b/src/test/resources/sample.springboot3/test_spring_boot_war_apps_30.gradle index 8d2d0ffa0..2b0150509 100644 --- a/src/test/resources/sample.springboot3/test_spring_boot_war_apps_30.gradle +++ b/src/test/resources/sample.springboot3/test_spring_boot_war_apps_30.gradle @@ -29,7 +29,7 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") testImplementation('org.springframework.boot:spring-boot-starter-test') - libertyRuntime group: 'io.openliberty', name: 'openliberty-runtime', version: '23.0.0.9' + libertyRuntime group: 'io.openliberty', name: 'openliberty-kernel', version: '23.0.0.10' } liberty { diff --git a/src/test/resources/sample.springboot3/test_spring_boot_war_classifier_apps_30.gradle b/src/test/resources/sample.springboot3/test_spring_boot_war_classifier_apps_30.gradle index 6b043b2ef..be3382a2f 100644 --- a/src/test/resources/sample.springboot3/test_spring_boot_war_classifier_apps_30.gradle +++ b/src/test/resources/sample.springboot3/test_spring_boot_war_classifier_apps_30.gradle @@ -29,7 +29,7 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") testImplementation('org.springframework.boot:spring-boot-starter-test') - libertyRuntime group: 'io.openliberty', name: 'openliberty-runtime', version: '23.0.0.9' + libertyRuntime group: 'io.openliberty', name: 'openliberty-kernel', version: '23.0.0.10' } bootWar { From fd7ef36591b272d1a70ea0a7954e3706e280b712 Mon Sep 17 00:00:00 2001 From: Matt Bowersox Date: Thu, 19 Oct 2023 11:33:18 -0500 Subject: [PATCH 06/12] Test with Java 21 --- .github/workflows/gradle.yml | 28 +++++++++---------- build.gradle | 2 +- .../gradle/tasks/AbstractFeatureTask.groovy | 14 ++++++++++ .../tools/gradle/tasks/DevTask.groovy | 14 ++++++++-- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 259db1671..a8cd0049c 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -18,13 +18,13 @@ jobs: matrix: # test against latest update of each major Java version, as well as specific updates of LTS versions: RUNTIME: [ol, wlp] - RUNTIME_VERSION: [23.0.0.6, 23.0.0.9] - java: [17, 11, 8] + RUNTIME_VERSION: [23.0.0.10] + java: [21, 17, 11, 8] exclude: - java: 8 - RUNTIME_VERSION: 23.0.0.6 - - java: 17 - RUNTIME_VERSION: 23.0.0.6 + RUNTIME: wlp + - java: 11 + RUNTIME: ol name: ${{ matrix.RUNTIME }} ${{ matrix.RUNTIME_VERSION }}, Java ${{ matrix.java }}, Linux steps: # Checkout repos @@ -65,8 +65,8 @@ jobs: # Install dependencies - name: Install ci.ant and ci.common run: | - mvn -V clean install -f ci.ant --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false - mvn -V clean install -f ci.common --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false + mvn -V clean install -f ci.ant --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false -DskipTests + mvn -V clean install -f ci.common --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false -DskipTests # Run tests - name: Run tests with Gradle on Ubuntu run: @@ -95,15 +95,13 @@ jobs: matrix: # test against latest update of each major Java version, as well as specific updates of LTS versions: RUNTIME: [ol, wlp] - RUNTIME_VERSION: [23.0.0.6, 23.0.0.9] - java: [17, 11, 8] + RUNTIME_VERSION: [23.0.0.10] + java: [21, 17, 11, 8] exclude: - java: 8 - RUNTIME_VERSION: 23.0.0.6 - - java: 8 + RUNTIME: ol + - java: 11 RUNTIME: wlp - - java: 17 - RUNTIME_VERSION: 23.0.0.6 name: ${{ matrix.RUNTIME }} ${{ matrix.RUNTIME_VERSION }}, Java ${{ matrix.java }}, Windows steps: # Checkout repos @@ -140,11 +138,11 @@ jobs: # Install ci.ant - name: Install ci.ant working-directory: C:/ci.ant - run: mvn -V clean install --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false + run: mvn -V clean install --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false -DskipTests # Install ci.common - name: Install ci.common working-directory: C:/ci.common - run: mvn -V clean install --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false + run: mvn -V clean install --batch-mode --no-transfer-progress --errors -DtrimStackTrace=false -DskipTests # Run tests - name: Run tests with Gradle on Windows working-directory: C:/ci.gradle diff --git a/build.gradle b/build.gradle index 98f1f0457..da18176e1 100644 --- a/build.gradle +++ b/build.gradle @@ -60,7 +60,7 @@ compileTestGroovy { } def libertyAntVersion = "1.9.13" -def libertyCommonVersion = "1.8.29" +def libertyCommonVersion = "1.8.30-SNAPSHOT" dependencies { implementation gradleApi() diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractFeatureTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractFeatureTask.groovy index 237419b06..7f5e7d71e 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractFeatureTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractFeatureTask.groovy @@ -16,6 +16,7 @@ package io.openliberty.tools.gradle.tasks +import io.openliberty.tools.common.plugins.util.AbstractContainerSupportUtil import io.openliberty.tools.common.plugins.util.InstallFeatureUtil import io.openliberty.tools.common.plugins.util.InstallFeatureUtil.ProductProperties import io.openliberty.tools.common.plugins.util.PluginExecutionException @@ -109,6 +110,7 @@ public class AbstractFeatureTask extends AbstractServerTask { private class InstallFeatureTaskUtil extends InstallFeatureUtil { public InstallFeatureTaskUtil(File installDir, File buildDir, String from, String to, Set pluginListedEsas, List propertiesList, String openLibertyVerion, String containerName, List additionalJsons) throws PluginScenarioException, PluginExecutionException { super(installDir, buildDir, from, to, pluginListedEsas, propertiesList, openLibertyVerion, containerName, additionalJsons) + setContainerEngine(this); } @Override @@ -291,5 +293,17 @@ public class AbstractFeatureTask extends AbstractServerTask { return util } + protected void setContainerEngine(AbstractContainerSupportUtil util) throws PluginExecutionException { + String LIBERTY_DEV_PODMAN = "liberty.dev.podman"; + Map projectProperties = project.getProperties(); + if (!projectProperties.isEmpty()) { + Object isPodman = projectProperties.get(LIBERTY_DEV_PODMAN); + isPodman = projectProperties.get(LIBERTY_DEV_PODMAN); + if (isPodman != null) { + util.setIsDocker(!(Boolean.parseBoolean(isPodman.toString()))); + logger.debug("liberty.dev.podman was set to: " + (Boolean.parseBoolean(isPodman.toString()))); + } + } + } } \ No newline at end of file diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy index 263bb3c95..15d3f4957 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy @@ -15,6 +15,7 @@ */ package io.openliberty.tools.gradle.tasks +import org.gradle.api.GradleException import org.gradle.api.Project import org.gradle.api.artifacts.Configuration import org.gradle.api.internal.file.DefaultFilePropertyFactory @@ -51,6 +52,7 @@ import java.nio.file.Path; class DevTask extends AbstractFeatureTask { + private static final String LIBERTY_DEV_PODMAN = "liberty.dev.podman"; private static final String LIBERTY_HOSTNAME = "liberty.hostname"; private static final String LIBERTY_HTTP_PORT = "liberty.http.port"; private static final String LIBERTY_HTTPS_PORT = "liberty.https.port"; @@ -360,7 +362,7 @@ class DevTask extends AbstractFeatureTask { boolean libertyDebug, boolean pollingTest, boolean container, File containerfile, File containerBuildContext, String containerRunOpts, int containerBuildTimeout, boolean skipDefaultPorts, boolean keepTempContainerfile, String mavenCacheLocation, String packagingType, File buildFile, boolean generateFeatures - ) throws IOException { + ) throws IOException, PluginExecutionException { super(buildDir, serverDirectory, sourceDirectory, testSourceDirectory, configDirectory, projectDirectory, /* multi module project directory */ projectDirectory, resourceDirs, hotTests, skipTests, false /* skipUTs */, false /* skipITs */, skipInstallFeature, artifactId, serverStartTimeout, verifyAppStartTimeout, appUpdateTimeout, ((long) (compileWait * 1000L)), libertyDebug, @@ -378,6 +380,8 @@ class DevTask extends AbstractFeatureTask { project.configurations.getByName('libertyFeature').dependencies.each { dep -> this.existingLibertyFeatureDependencies.add(dep.name) } + + setContainerEngine(this) } @Override @@ -1171,14 +1175,18 @@ class DevTask extends AbstractFeatureTask { File buildFile = project.getBuildFile(); // Instantiate util before any child gradle tasks launched so it can help find available port if needed - this.util = new DevTaskUtil(project.buildDir, serverInstallDir, getUserDir(project, serverInstallDir), + try { + this.util = new DevTaskUtil(project.buildDir, serverInstallDir, getUserDir(project, serverInstallDir), serverDirectory, sourceDirectory, testSourceDirectory, configDirectory, project.getRootDir(), resourceDirs, hotTests.booleanValue(), skipTests.booleanValue(), skipInstallFeature.booleanValue(), artifactId, serverStartTimeout.intValue(), verifyAppStartTimeout.intValue(), verifyAppStartTimeout.intValue(), compileWait.doubleValue(), libertyDebug.booleanValue(), pollingTest.booleanValue(), container.booleanValue(), containerfile, containerBuildContext, containerRunOpts, containerBuildTimeout, skipDefaultPorts.booleanValue(), keepTempContainerfile.booleanValue(), localMavenRepoForFeatureUtility, getPackagingType(), buildFile, generateFeatures.booleanValue() - ); + ); + } catch (IOException | PluginExecutionException e) { + throw new GradleException("Error initializing dev mode.", e) + } ProjectConnection gradleConnection = initGradleProjectConnection(); BuildLauncher gradleBuildLauncher = gradleConnection.newBuild(); From 3ee65c48aa0d661d9c37fa1b00faea73b12abaa9 Mon Sep 17 00:00:00 2001 From: Matt Bowersox Date: Thu, 19 Oct 2023 13:15:49 -0500 Subject: [PATCH 07/12] Check for property key in project properties and update compiler version --- build.gradle | 18 +++++++++--------- .../gradle/tasks/AbstractFeatureTask.groovy | 3 +-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/build.gradle b/build.gradle index da18176e1..7e38bbe75 100644 --- a/build.gradle +++ b/build.gradle @@ -40,26 +40,26 @@ configurations { } compileJava { - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 } compileTestJava { - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 } compileGroovy { - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 } compileTestGroovy { - sourceCompatibility = JavaVersion.VERSION_1_7 - targetCompatibility = JavaVersion.VERSION_1_7 + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 } -def libertyAntVersion = "1.9.13" +def libertyAntVersion = "1.9.14-SNAPSHOT" def libertyCommonVersion = "1.8.30-SNAPSHOT" dependencies { diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractFeatureTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractFeatureTask.groovy index 7f5e7d71e..b29d9ab5e 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractFeatureTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractFeatureTask.groovy @@ -296,9 +296,8 @@ public class AbstractFeatureTask extends AbstractServerTask { protected void setContainerEngine(AbstractContainerSupportUtil util) throws PluginExecutionException { String LIBERTY_DEV_PODMAN = "liberty.dev.podman"; Map projectProperties = project.getProperties(); - if (!projectProperties.isEmpty()) { + if (!projectProperties.isEmpty() && projectProperties.containsKey(LIBERTY_DEV_PODMAN)) { Object isPodman = projectProperties.get(LIBERTY_DEV_PODMAN); - isPodman = projectProperties.get(LIBERTY_DEV_PODMAN); if (isPodman != null) { util.setIsDocker(!(Boolean.parseBoolean(isPodman.toString()))); logger.debug("liberty.dev.podman was set to: " + (Boolean.parseBoolean(isPodman.toString()))); From 15bd86f40f0a40b4d50f41679bbf1c45d956205b Mon Sep 17 00:00:00 2001 From: Matt Bowersox Date: Thu, 19 Oct 2023 13:19:45 -0500 Subject: [PATCH 08/12] Remove unused property variable --- src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy index 15d3f4957..fa4bd519a 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/DevTask.groovy @@ -52,7 +52,6 @@ import java.nio.file.Path; class DevTask extends AbstractFeatureTask { - private static final String LIBERTY_DEV_PODMAN = "liberty.dev.podman"; private static final String LIBERTY_HOSTNAME = "liberty.hostname"; private static final String LIBERTY_HTTP_PORT = "liberty.http.port"; private static final String LIBERTY_HTTPS_PORT = "liberty.https.port"; From aa052d6f4bb2a57ae3010008bfc138adc3e9f43f Mon Sep 17 00:00:00 2001 From: Cheryl King Date: Thu, 19 Oct 2023 14:48:20 -0500 Subject: [PATCH 09/12] Update gradle wrapper to 8.4 --- gradle/wrapper/gradle-wrapper.jar | Bin 59821 -> 62076 bytes gradle/wrapper/gradle-wrapper.properties | 3 ++- gradlew | 25 ++++++++++++++++------- gradlew.bat | 15 ++++++++------ 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 41d9927a4d4fb3f96a785543079b8df6723c946b..c1962a79e29d3e0ab67b14947c167a862655af9b 100644 GIT binary patch delta 40199 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 delta 37942 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/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index ac1b06f93..6689b85be 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal From df3e61d22e57d8a490d522c0f79701acd0966874 Mon Sep 17 00:00:00 2001 From: Cheryl King Date: Thu, 19 Oct 2023 16:21:05 -0500 Subject: [PATCH 10/12] Update to Java 1.8 in test case build gradle files --- .../getAppNamesFromConfigTest.gradle | 4 ++-- .../testAppListsWithObjects.gradle | 4 ++-- .../testWarTasksWithDifferentDependencies.gradle | 4 ++-- .../verifyTimeoutSuccessListsOfAppsTest.gradle | 4 ++-- src/test/resources/sample.servlet/TestStripVersion.gradle | 4 ++-- src/test/resources/sample.servlet/testAppConfig.gradle | 4 ++-- src/test/resources/sample.servlet/testAppConfigFail.gradle | 4 ++-- .../testAppendServerEnvWithConfigServerEnv.gradle | 4 ++-- .../sample.servlet/testAppendServerEnvWithEnvProps.gradle | 4 ++-- .../sample.servlet/testAppendServerEnvWithNoEnvProps.gradle | 4 ++-- .../sample.servlet/testAppendServerEnvWithOnlyEnvProps.gradle | 4 ++-- src/test/resources/sample.servlet/testConfigDropinsApp.gradle | 4 ++-- src/test/resources/sample.servlet/testEtcOutputDir.gradle | 4 ++-- src/test/resources/sample.servlet/testLooseApplication.gradle | 4 ++-- .../sample.servlet/testLooseApplicationWithWarTask.gradle | 4 ++-- src/test/resources/sample.servlet/testOutputDirs.gradle | 4 ++-- src/test/resources/sample.servlet/testPluginConfigFile.gradle | 4 ++-- .../sample.servlet/verifyLooseAppTestTimeoutSuccess.gradle | 4 ++-- .../sample.servlet/verifyTimeoutSuccessAppsTest.gradle | 4 ++-- .../sample.servlet/verifyTimeoutSuccessDropinsTest.gradle | 4 ++-- src/test/resources/sampleJSP.servlet/testCompileJSP.gradle | 4 ++-- .../server-config-files/testCreateLibertyFiles.gradle | 4 ++-- .../testCreateLibertyInlineProperties.gradle | 4 ++-- .../server-config/testCreateLibertyDefaultConfigDir.gradle | 4 ++-- 24 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/test/resources/sample.servlet-noWebAppConfig/getAppNamesFromConfigTest.gradle b/src/test/resources/sample.servlet-noWebAppConfig/getAppNamesFromConfigTest.gradle index 6e4d32e5b..03f094e93 100644 --- a/src/test/resources/sample.servlet-noWebAppConfig/getAppNamesFromConfigTest.gradle +++ b/src/test/resources/sample.servlet-noWebAppConfig/getAppNamesFromConfigTest.gradle @@ -18,8 +18,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet-noWebAppConfig/testAppListsWithObjects.gradle b/src/test/resources/sample.servlet-noWebAppConfig/testAppListsWithObjects.gradle index 714b72842..f1d8fb3b3 100644 --- a/src/test/resources/sample.servlet-noWebAppConfig/testAppListsWithObjects.gradle +++ b/src/test/resources/sample.servlet-noWebAppConfig/testAppListsWithObjects.gradle @@ -18,8 +18,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet-noWebAppConfig/testWarTasksWithDifferentDependencies.gradle b/src/test/resources/sample.servlet-noWebAppConfig/testWarTasksWithDifferentDependencies.gradle index 05504a5f6..b91d75dd9 100644 --- a/src/test/resources/sample.servlet-noWebAppConfig/testWarTasksWithDifferentDependencies.gradle +++ b/src/test/resources/sample.servlet-noWebAppConfig/testWarTasksWithDifferentDependencies.gradle @@ -18,8 +18,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet-noWebAppConfig/verifyTimeoutSuccessListsOfAppsTest.gradle b/src/test/resources/sample.servlet-noWebAppConfig/verifyTimeoutSuccessListsOfAppsTest.gradle index 8621fe83e..4c1b49595 100644 --- a/src/test/resources/sample.servlet-noWebAppConfig/verifyTimeoutSuccessListsOfAppsTest.gradle +++ b/src/test/resources/sample.servlet-noWebAppConfig/verifyTimeoutSuccessListsOfAppsTest.gradle @@ -18,8 +18,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet/TestStripVersion.gradle b/src/test/resources/sample.servlet/TestStripVersion.gradle index 289e66696..c2e5e0852 100644 --- a/src/test/resources/sample.servlet/TestStripVersion.gradle +++ b/src/test/resources/sample.servlet/TestStripVersion.gradle @@ -22,8 +22,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet/testAppConfig.gradle b/src/test/resources/sample.servlet/testAppConfig.gradle index 92e6d6065..7e551fcf2 100644 --- a/src/test/resources/sample.servlet/testAppConfig.gradle +++ b/src/test/resources/sample.servlet/testAppConfig.gradle @@ -18,8 +18,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet/testAppConfigFail.gradle b/src/test/resources/sample.servlet/testAppConfigFail.gradle index 8dbf7cab1..f8f40b2d7 100644 --- a/src/test/resources/sample.servlet/testAppConfigFail.gradle +++ b/src/test/resources/sample.servlet/testAppConfigFail.gradle @@ -18,8 +18,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet/testAppendServerEnvWithConfigServerEnv.gradle b/src/test/resources/sample.servlet/testAppendServerEnvWithConfigServerEnv.gradle index 2e351e225..32ddbd553 100644 --- a/src/test/resources/sample.servlet/testAppendServerEnvWithConfigServerEnv.gradle +++ b/src/test/resources/sample.servlet/testAppendServerEnvWithConfigServerEnv.gradle @@ -22,8 +22,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet/testAppendServerEnvWithEnvProps.gradle b/src/test/resources/sample.servlet/testAppendServerEnvWithEnvProps.gradle index 128196d9e..d5635c143 100644 --- a/src/test/resources/sample.servlet/testAppendServerEnvWithEnvProps.gradle +++ b/src/test/resources/sample.servlet/testAppendServerEnvWithEnvProps.gradle @@ -22,8 +22,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet/testAppendServerEnvWithNoEnvProps.gradle b/src/test/resources/sample.servlet/testAppendServerEnvWithNoEnvProps.gradle index c9e40e1dd..e7d014514 100644 --- a/src/test/resources/sample.servlet/testAppendServerEnvWithNoEnvProps.gradle +++ b/src/test/resources/sample.servlet/testAppendServerEnvWithNoEnvProps.gradle @@ -22,8 +22,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet/testAppendServerEnvWithOnlyEnvProps.gradle b/src/test/resources/sample.servlet/testAppendServerEnvWithOnlyEnvProps.gradle index 5987ae0a7..8302475e9 100644 --- a/src/test/resources/sample.servlet/testAppendServerEnvWithOnlyEnvProps.gradle +++ b/src/test/resources/sample.servlet/testAppendServerEnvWithOnlyEnvProps.gradle @@ -22,8 +22,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet/testConfigDropinsApp.gradle b/src/test/resources/sample.servlet/testConfigDropinsApp.gradle index d2fadd23e..2923349fe 100644 --- a/src/test/resources/sample.servlet/testConfigDropinsApp.gradle +++ b/src/test/resources/sample.servlet/testConfigDropinsApp.gradle @@ -18,8 +18,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet/testEtcOutputDir.gradle b/src/test/resources/sample.servlet/testEtcOutputDir.gradle index 29f3c8075..1a739e806 100644 --- a/src/test/resources/sample.servlet/testEtcOutputDir.gradle +++ b/src/test/resources/sample.servlet/testEtcOutputDir.gradle @@ -18,8 +18,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet/testLooseApplication.gradle b/src/test/resources/sample.servlet/testLooseApplication.gradle index d98637a0d..730e87874 100644 --- a/src/test/resources/sample.servlet/testLooseApplication.gradle +++ b/src/test/resources/sample.servlet/testLooseApplication.gradle @@ -22,8 +22,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet/testLooseApplicationWithWarTask.gradle b/src/test/resources/sample.servlet/testLooseApplicationWithWarTask.gradle index 025f1ab01..c064ffdc2 100644 --- a/src/test/resources/sample.servlet/testLooseApplicationWithWarTask.gradle +++ b/src/test/resources/sample.servlet/testLooseApplicationWithWarTask.gradle @@ -23,8 +23,8 @@ apply plugin: 'java' apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet/testOutputDirs.gradle b/src/test/resources/sample.servlet/testOutputDirs.gradle index 4f4743723..1adc20cfb 100644 --- a/src/test/resources/sample.servlet/testOutputDirs.gradle +++ b/src/test/resources/sample.servlet/testOutputDirs.gradle @@ -18,8 +18,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet/testPluginConfigFile.gradle b/src/test/resources/sample.servlet/testPluginConfigFile.gradle index e21b17e60..f2d4195d2 100644 --- a/src/test/resources/sample.servlet/testPluginConfigFile.gradle +++ b/src/test/resources/sample.servlet/testPluginConfigFile.gradle @@ -21,8 +21,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet/verifyLooseAppTestTimeoutSuccess.gradle b/src/test/resources/sample.servlet/verifyLooseAppTestTimeoutSuccess.gradle index 0c53a7ca7..d041aaccc 100644 --- a/src/test/resources/sample.servlet/verifyLooseAppTestTimeoutSuccess.gradle +++ b/src/test/resources/sample.servlet/verifyLooseAppTestTimeoutSuccess.gradle @@ -18,8 +18,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet/verifyTimeoutSuccessAppsTest.gradle b/src/test/resources/sample.servlet/verifyTimeoutSuccessAppsTest.gradle index 96338e76b..68df5281d 100644 --- a/src/test/resources/sample.servlet/verifyTimeoutSuccessAppsTest.gradle +++ b/src/test/resources/sample.servlet/verifyTimeoutSuccessAppsTest.gradle @@ -18,8 +18,8 @@ buildscript { apply plugin: 'liberty' apply plugin: 'war' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sample.servlet/verifyTimeoutSuccessDropinsTest.gradle b/src/test/resources/sample.servlet/verifyTimeoutSuccessDropinsTest.gradle index 9d72ebb45..e11b56a73 100644 --- a/src/test/resources/sample.servlet/verifyTimeoutSuccessDropinsTest.gradle +++ b/src/test/resources/sample.servlet/verifyTimeoutSuccessDropinsTest.gradle @@ -18,8 +18,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/sampleJSP.servlet/testCompileJSP.gradle b/src/test/resources/sampleJSP.servlet/testCompileJSP.gradle index bbaf305b6..5ea1ce95d 100644 --- a/src/test/resources/sampleJSP.servlet/testCompileJSP.gradle +++ b/src/test/resources/sampleJSP.servlet/testCompileJSP.gradle @@ -21,8 +21,8 @@ buildscript { apply plugin: 'war' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/server-config-files/testCreateLibertyFiles.gradle b/src/test/resources/server-config-files/testCreateLibertyFiles.gradle index 72e179e17..c00bf6c72 100644 --- a/src/test/resources/server-config-files/testCreateLibertyFiles.gradle +++ b/src/test/resources/server-config-files/testCreateLibertyFiles.gradle @@ -18,8 +18,8 @@ buildscript { apply plugin: 'java' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/server-config-files/testCreateLibertyInlineProperties.gradle b/src/test/resources/server-config-files/testCreateLibertyInlineProperties.gradle index d414d7ef5..0b158f689 100644 --- a/src/test/resources/server-config-files/testCreateLibertyInlineProperties.gradle +++ b/src/test/resources/server-config-files/testCreateLibertyInlineProperties.gradle @@ -18,8 +18,8 @@ buildscript { apply plugin: 'java' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' diff --git a/src/test/resources/server-config/testCreateLibertyDefaultConfigDir.gradle b/src/test/resources/server-config/testCreateLibertyDefaultConfigDir.gradle index 2e4e42c0d..5a29e7398 100644 --- a/src/test/resources/server-config/testCreateLibertyDefaultConfigDir.gradle +++ b/src/test/resources/server-config/testCreateLibertyDefaultConfigDir.gradle @@ -18,8 +18,8 @@ buildscript { apply plugin: 'java' apply plugin: 'liberty' -sourceCompatibility = 1.7 -targetCompatibility = 1.7 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 compileJava.options.encoding = 'UTF-8' From 4617f9b33620465ac49781bcf371b516800d3c95 Mon Sep 17 00:00:00 2001 From: Cheryl King Date: Thu, 19 Oct 2023 16:48:20 -0500 Subject: [PATCH 11/12] Fix GenerateFeaturesTest by suppressing Gradle deprecation warnings --- src/test/groovy/io/openliberty/tools/gradle/BaseDevTest.groovy | 2 +- .../io/openliberty/tools/gradle/BaseGenerateFeaturesTest.groovy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/groovy/io/openliberty/tools/gradle/BaseDevTest.groovy b/src/test/groovy/io/openliberty/tools/gradle/BaseDevTest.groovy index 0183f849a..c3ad287b4 100644 --- a/src/test/groovy/io/openliberty/tools/gradle/BaseDevTest.groovy +++ b/src/test/groovy/io/openliberty/tools/gradle/BaseDevTest.groovy @@ -83,7 +83,7 @@ class BaseDevTest extends AbstractIntegrationTest { gradlew = new File("gradlew") } - StringBuilder command = new StringBuilder(gradlew.getAbsolutePath() + " libertyDev"); + StringBuilder command = new StringBuilder(gradlew.getAbsolutePath() + " --warning-mode none libertyDev"); if (params != null) { command.append(" " + params); } diff --git a/src/test/groovy/io/openliberty/tools/gradle/BaseGenerateFeaturesTest.groovy b/src/test/groovy/io/openliberty/tools/gradle/BaseGenerateFeaturesTest.groovy index 6bb5611db..38b512a71 100644 --- a/src/test/groovy/io/openliberty/tools/gradle/BaseGenerateFeaturesTest.groovy +++ b/src/test/groovy/io/openliberty/tools/gradle/BaseGenerateFeaturesTest.groovy @@ -125,7 +125,7 @@ class BaseGenerateFeaturesTest extends AbstractIntegrationTest { gradlew = new File("gradlew"); } - StringBuilder command = new StringBuilder(gradlew.getAbsolutePath() + " " + processCommand); + StringBuilder command = new StringBuilder(gradlew.getAbsolutePath() + " --warning-mode none " + processCommand); System.out.println("Running command: " + command.toString()); ProcessBuilder builder = buildProcess(command.toString()); From 7351a9d5fb81b6ac69682685b386ba22d1b385b1 Mon Sep 17 00:00:00 2001 From: Cheryl King Date: Thu, 19 Oct 2023 21:41:16 -0500 Subject: [PATCH 12/12] Fix eclipse facet test java version --- .../io/openliberty/tools/gradle/TestEclipseFacetsWar.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/groovy/io/openliberty/tools/gradle/TestEclipseFacetsWar.groovy b/src/test/groovy/io/openliberty/tools/gradle/TestEclipseFacetsWar.groovy index edcf15cbb..f7f504944 100644 --- a/src/test/groovy/io/openliberty/tools/gradle/TestEclipseFacetsWar.groovy +++ b/src/test/groovy/io/openliberty/tools/gradle/TestEclipseFacetsWar.groovy @@ -57,7 +57,7 @@ public class TestEclipseFacetsWar extends AbstractIntegrationTest{ if (attributes.getAt('facet').equals('jst.web') && attributes.getAt('version').equals('3.0')) { hasJstWebFacet = true } - if (attributes.getAt('facet').equals('jst.java') && attributes.getAt('version').equals('1.7')) { + if (attributes.getAt('facet').equals('jst.java') && attributes.getAt('version').equals('1.8')) { hasJavaFacet = true } }