From 1dc5c484f0969ae9d6a6d6a03e97525c20a53770 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 28 Mar 2017 14:41:12 +0100 Subject: [PATCH] Use application plugin properties by convention when it is applied bootRun's main and jvmArgs properties use mainClassName and applicationDefaultJvmArgs respectively by convention. bootJar and bootWar's mainClass property uses mainClassName by convention. --- .../bundling/BundlingPluginFeatures.java | 21 +++++++++++++------ .../boot/gradle/run/RunPluginFeatures.java | 21 +++++++++---------- .../AbstractBootArchiveIntegrationTests.java | 15 +++++++++++++ .../gradle/run/BootRunIntegrationTests.java | 18 ++++++++++++++++ ...pplicationPluginMainClassNameIsUsed.gradle | 11 ++++++++++ ...pplicationPluginMainClassNameIsUsed.gradle | 11 ++++++++++ ...pplicationPluginJvmArgumentsAreUsed.gradle | 14 +++++++++++++ ...pplicationPluginMainClassNameIsUsed.gradle | 14 +++++++++++++ 8 files changed, 108 insertions(+), 17 deletions(-) create mode 100644 spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/bundling/BootJarIntegrationTests-applicationPluginMainClassNameIsUsed.gradle create mode 100644 spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/bundling/BootWarIntegrationTests-applicationPluginMainClassNameIsUsed.gradle create mode 100644 spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/run/BootRunIntegrationTests-applicationPluginJvmArgumentsAreUsed.gradle create mode 100644 spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/run/BootRunIntegrationTests-applicationPluginMainClassNameIsUsed.gradle diff --git a/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BundlingPluginFeatures.java b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BundlingPluginFeatures.java index 5baa4a9cbcf..b1a262e61f6 100644 --- a/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BundlingPluginFeatures.java +++ b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/bundling/BundlingPluginFeatures.java @@ -19,6 +19,7 @@ package org.springframework.boot.gradle.bundling; import java.util.Collections; import java.util.Set; import java.util.concurrent.Callable; +import java.util.function.Supplier; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; @@ -66,9 +67,8 @@ public class BundlingPluginFeatures implements PluginFeatures { ArchivePublishArtifact artifact = new ArchivePublishArtifact(bootWar); this.singlePublishedArtifact.addCandidate(artifact); project.getComponents().add(new BootSoftwareComponent(artifact, "bootWeb")); - bootWar.conventionMapping("mainClass", () -> { - return new MainClassResolver(bootWar.getClasspath()).resolveMainClass(); - }); + bootWar.conventionMapping("mainClass", + mainClassConvention(project, bootWar::getClasspath)); } private void configureBootJarTask(Project project) { @@ -83,9 +83,18 @@ public class BundlingPluginFeatures implements PluginFeatures { ArchivePublishArtifact artifact = new ArchivePublishArtifact(bootJar); this.singlePublishedArtifact.addCandidate(artifact); project.getComponents().add(new BootSoftwareComponent(artifact, "bootJava")); - bootJar.conventionMapping("mainClass", () -> { - return new MainClassResolver(bootJar.getClasspath()).resolveMainClass(); - }); + bootJar.conventionMapping("mainClass", + mainClassConvention(project, bootJar::getClasspath)); + } + + private Callable mainClassConvention(Project project, + Supplier classpathSupplier) { + return () -> { + if (project.hasProperty("mainClassName")) { + return project.property("mainClassName"); + } + return new MainClassResolver(classpathSupplier.get()).resolveMainClass(); + }; } private void configureBootArchivesUpload(Project project) { diff --git a/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/run/RunPluginFeatures.java b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/run/RunPluginFeatures.java index 0ad7034b4f7..c7838b22a45 100644 --- a/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/run/RunPluginFeatures.java +++ b/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/run/RunPluginFeatures.java @@ -44,26 +44,25 @@ public class RunPluginFeatures implements PluginFeatures { }); } - private void addBootRunTask(final Project project) { - final JavaPluginConvention javaConvention = project.getConvention() + private void addBootRunTask(Project project) { + JavaPluginConvention javaConvention = project.getConvention() .getPlugin(JavaPluginConvention.class); - BootRun run = project.getTasks().create(RUN_APP_TASK_NAME, BootRun.class); run.setDescription("Run the project with support for " + "auto-detecting main class and reloading static resources"); run.setGroup("application"); run.classpath(javaConvention.getSourceSets() .findByName(SourceSet.MAIN_SOURCE_SET_NAME).getRuntimeClasspath()); - run.getConventionMapping().map("jvmArgs", new Callable() { - @Override - public Object call() throws Exception { - if (project.hasProperty("applicationDefaultJvmArgs")) { - return project.property("applicationDefaultJvmArgs"); - } - return Collections.emptyList(); + run.getConventionMapping().map("jvmArgs", ((Callable) () -> { + if (project.hasProperty("applicationDefaultJvmArgs")) { + return project.property("applicationDefaultJvmArgs"); } - }); + return Collections.emptyList(); + })); run.conventionMapping("main", () -> { + if (project.hasProperty("mainClassName")) { + return project.property("mainClassName"); + } return new MainClassResolver(run.getClasspath()).resolveMainClass(); }); } diff --git a/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/bundling/AbstractBootArchiveIntegrationTests.java b/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/bundling/AbstractBootArchiveIntegrationTests.java index 9ab3e301c93..11ad775d9d2 100644 --- a/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/bundling/AbstractBootArchiveIntegrationTests.java +++ b/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/bundling/AbstractBootArchiveIntegrationTests.java @@ -16,7 +16,9 @@ package org.springframework.boot.gradle.bundling; +import java.io.File; import java.io.IOException; +import java.util.jar.JarFile; import org.gradle.testkit.runner.InvalidRunnerConfigurationException; import org.gradle.testkit.runner.TaskOutcome; @@ -97,4 +99,17 @@ public abstract class AbstractBootArchiveIntegrationTests { .getOutcome()).isEqualTo(TaskOutcome.SUCCESS); } + @Test + public void applicationPluginMainClassNameIsUsed() throws IOException { + assertThat(this.gradleBuild.build(this.taskName).task(":" + this.taskName) + .getOutcome()).isEqualTo(TaskOutcome.SUCCESS); + try (JarFile jarFile = new JarFile( + new File(this.gradleBuild.getProjectDir(), "build/libs") + .listFiles()[0])) { + assertThat(jarFile.getManifest().getMainAttributes().getValue("Start-Class")) + .isEqualTo("com.example.CustomMain"); + } + + } + } diff --git a/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/run/BootRunIntegrationTests.java b/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/run/BootRunIntegrationTests.java index 5945b21551f..120a211be7c 100644 --- a/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/run/BootRunIntegrationTests.java +++ b/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/run/BootRunIntegrationTests.java @@ -66,6 +66,24 @@ public class BootRunIntegrationTests { assertThat(result.getOutput()).doesNotContain(urlOf("build/resources/main")); } + @Test + public void applicationPluginMainClassNameIsUsed() throws IOException { + BuildResult result = this.gradleBuild.build("echoMainClassName"); + assertThat(result.task(":echoMainClassName").getOutcome()) + .isEqualTo(TaskOutcome.UP_TO_DATE); + assertThat(result.getOutput()) + .contains("Main class name = com.example.CustomMainClass"); + } + + @Test + public void applicationPluginJvmArgumentsAreUsed() throws IOException { + BuildResult result = this.gradleBuild.build("echoJvmArguments"); + assertThat(result.task(":echoJvmArguments").getOutcome()) + .isEqualTo(TaskOutcome.UP_TO_DATE); + assertThat(result.getOutput()) + .contains("JVM arguments = [-Dcom.foo=bar, -Dcom.bar=baz]"); + } + private String urlOf(String path) throws IOException { return new File(this.gradleBuild.getProjectDir().getCanonicalFile(), path).toURI() .toURL().toString(); diff --git a/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/bundling/BootJarIntegrationTests-applicationPluginMainClassNameIsUsed.gradle b/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/bundling/BootJarIntegrationTests-applicationPluginMainClassNameIsUsed.gradle new file mode 100644 index 00000000000..684171c1403 --- /dev/null +++ b/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/bundling/BootJarIntegrationTests-applicationPluginMainClassNameIsUsed.gradle @@ -0,0 +1,11 @@ +buildscript { + dependencies { + classpath files(pluginClasspath.split(',')) + } +} + +apply plugin: 'java' +apply plugin: 'org.springframework.boot' +apply plugin: 'application' + +mainClassName = 'com.example.CustomMain' diff --git a/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/bundling/BootWarIntegrationTests-applicationPluginMainClassNameIsUsed.gradle b/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/bundling/BootWarIntegrationTests-applicationPluginMainClassNameIsUsed.gradle new file mode 100644 index 00000000000..8da00e317bf --- /dev/null +++ b/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/bundling/BootWarIntegrationTests-applicationPluginMainClassNameIsUsed.gradle @@ -0,0 +1,11 @@ +buildscript { + dependencies { + classpath files(pluginClasspath.split(',')) + } +} + +apply plugin: 'war' +apply plugin: 'org.springframework.boot' +apply plugin: 'application' + +mainClassName = 'com.example.CustomMain' diff --git a/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/run/BootRunIntegrationTests-applicationPluginJvmArgumentsAreUsed.gradle b/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/run/BootRunIntegrationTests-applicationPluginJvmArgumentsAreUsed.gradle new file mode 100644 index 00000000000..96047897b24 --- /dev/null +++ b/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/run/BootRunIntegrationTests-applicationPluginJvmArgumentsAreUsed.gradle @@ -0,0 +1,14 @@ +buildscript { + dependencies { + classpath files(pluginClasspath.split(',')) + } +} + +apply plugin: 'application' +apply plugin: 'org.springframework.boot' + +applicationDefaultJvmArgs = ['-Dcom.foo=bar', '-Dcom.bar=baz'] + +task echoJvmArguments { + println 'JVM arguments = ' + bootRun.jvmArgs +} diff --git a/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/run/BootRunIntegrationTests-applicationPluginMainClassNameIsUsed.gradle b/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/run/BootRunIntegrationTests-applicationPluginMainClassNameIsUsed.gradle new file mode 100644 index 00000000000..a9163cd7d3e --- /dev/null +++ b/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/run/BootRunIntegrationTests-applicationPluginMainClassNameIsUsed.gradle @@ -0,0 +1,14 @@ +buildscript { + dependencies { + classpath files(pluginClasspath.split(',')) + } +} + +apply plugin: 'application' +apply plugin: 'org.springframework.boot' + +mainClassName = 'com.example.CustomMainClass' + +task echoMainClassName { + println 'Main class name = ' + bootRun.main +}