Simplify resolution of the application's main class name
Closes gh-30467
This commit is contained in:
parent
98cac100c6
commit
42ae55895d
|
|
@ -88,7 +88,7 @@ A number of configuration options that are specific to executable jars and wars
|
|||
|
||||
[[packaging-executable.configuring.main-class]]
|
||||
=== Configuring the Main Class
|
||||
By default, the executable archive's main class will be configured automatically by looking for a class with a `public static void main(String[])` method in directories on the task's classpath.
|
||||
By default, the executable archive's main class will be configured automatically by looking for a class with a `public static void main(String[])` method in the main source set's output.
|
||||
|
||||
The main class can also be configured explicitly using the task's `mainClass` property:
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ The `bootRun` task is an instance of {boot-run-javadoc}[`BootRun`] which is a `J
|
|||
As such, all of the {gradle-dsl}/org.gradle.api.tasks.JavaExec.html[usual configuration options] for executing a Java process in Gradle are available to you.
|
||||
The task is automatically configured to use the runtime classpath of the main source set.
|
||||
|
||||
By default, the main class will be configured automatically by looking for a class with a `public static void main(String[])` method in directories on the task's classpath.
|
||||
By default, the main class will be configured automatically by looking for a class with a `public static void main(String[])` method in the main source set's output.
|
||||
|
||||
The main class can also be configured explicitly using the task's `main` property:
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ import org.gradle.api.file.FileCollection;
|
|||
import org.gradle.api.model.ObjectFactory;
|
||||
import org.gradle.api.plugins.ApplicationPlugin;
|
||||
import org.gradle.api.plugins.BasePlugin;
|
||||
import org.gradle.api.plugins.ExtensionContainer;
|
||||
import org.gradle.api.plugins.JavaApplication;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.plugins.JavaPluginExtension;
|
||||
import org.gradle.api.provider.Provider;
|
||||
|
|
@ -46,6 +48,7 @@ import org.gradle.api.tasks.compile.JavaCompile;
|
|||
import org.gradle.jvm.toolchain.JavaToolchainService;
|
||||
import org.gradle.jvm.toolchain.JavaToolchainSpec;
|
||||
|
||||
import org.springframework.boot.gradle.dsl.SpringBootExtension;
|
||||
import org.springframework.boot.gradle.tasks.bundling.BootBuildImage;
|
||||
import org.springframework.boot.gradle.tasks.bundling.BootJar;
|
||||
import org.springframework.boot.gradle.tasks.run.BootRun;
|
||||
|
|
@ -77,10 +80,11 @@ final class JavaPluginAction implements PluginApplicationAction {
|
|||
classifyJarTask(project);
|
||||
configureBuildTask(project);
|
||||
configureDevelopmentOnlyConfiguration(project);
|
||||
TaskProvider<BootJar> bootJar = configureBootJarTask(project);
|
||||
TaskProvider<ResolveMainClassName> resolveMainClassName = configureResolveMainClassNameTask(project);
|
||||
TaskProvider<BootJar> bootJar = configureBootJarTask(project, resolveMainClassName);
|
||||
configureBootBuildImageTask(project, bootJar);
|
||||
configureArtifactPublication(bootJar);
|
||||
configureBootRunTask(project);
|
||||
configureBootRunTask(project, resolveMainClassName);
|
||||
project.afterEvaluate(this::configureUtf8Encoding);
|
||||
configureParametersCompilerArg(project);
|
||||
configureAdditionalMetadataLocations(project);
|
||||
|
|
@ -96,7 +100,39 @@ final class JavaPluginAction implements PluginApplicationAction {
|
|||
.configure((task) -> task.dependsOn(this.singlePublishedArtifact));
|
||||
}
|
||||
|
||||
private TaskProvider<BootJar> configureBootJarTask(Project project) {
|
||||
private TaskProvider<ResolveMainClassName> configureResolveMainClassNameTask(Project project) {
|
||||
return project.getTasks().register(SpringBootPlugin.RESOLVE_MAIN_CLASS_NAME_TASK_NAME,
|
||||
ResolveMainClassName.class, (resolveMainClassName) -> {
|
||||
ExtensionContainer extensions = project.getExtensions();
|
||||
resolveMainClassName.setDescription("Resolves the name of the application's main class.");
|
||||
resolveMainClassName.setGroup(BasePlugin.BUILD_GROUP);
|
||||
Callable<FileCollection> classpath = () -> project.getExtensions()
|
||||
.getByType(SourceSetContainer.class).getByName(SourceSet.MAIN_SOURCE_SET_NAME).getOutput();
|
||||
resolveMainClassName.setClasspath(classpath);
|
||||
resolveMainClassName.getConfiguredMainClassName().convention(project.provider(() -> {
|
||||
String javaApplicationMainClass = getJavaApplicationMainClass(extensions);
|
||||
if (javaApplicationMainClass != null) {
|
||||
return javaApplicationMainClass;
|
||||
}
|
||||
SpringBootExtension springBootExtension = project.getExtensions()
|
||||
.findByType(SpringBootExtension.class);
|
||||
return springBootExtension.getMainClass().getOrNull();
|
||||
}));
|
||||
resolveMainClassName.getOutputFile()
|
||||
.set(project.getLayout().getBuildDirectory().file("resolvedMainClassName"));
|
||||
});
|
||||
}
|
||||
|
||||
private static String getJavaApplicationMainClass(ExtensionContainer extensions) {
|
||||
JavaApplication javaApplication = extensions.findByType(JavaApplication.class);
|
||||
if (javaApplication == null) {
|
||||
return null;
|
||||
}
|
||||
return javaApplication.getMainClass().getOrNull();
|
||||
}
|
||||
|
||||
private TaskProvider<BootJar> configureBootJarTask(Project project,
|
||||
TaskProvider<ResolveMainClassName> resolveMainClassName) {
|
||||
SourceSet mainSourceSet = javaPluginExtension(project).getSourceSets()
|
||||
.getByName(SourceSet.MAIN_SOURCE_SET_NAME);
|
||||
Configuration developmentOnly = project.getConfigurations()
|
||||
|
|
@ -105,8 +141,6 @@ final class JavaPluginAction implements PluginApplicationAction {
|
|||
.getByName(SpringBootPlugin.PRODUCTION_RUNTIME_CLASSPATH_CONFIGURATION_NAME);
|
||||
Callable<FileCollection> classpath = () -> mainSourceSet.getRuntimeClasspath()
|
||||
.minus((developmentOnly.minus(productionRuntimeClasspath))).filter(new JarTypeFileSpec());
|
||||
TaskProvider<ResolveMainClassName> resolveMainClassName = ResolveMainClassName
|
||||
.registerForTask(SpringBootPlugin.BOOT_JAR_TASK_NAME, project, classpath);
|
||||
return project.getTasks().register(SpringBootPlugin.BOOT_JAR_TASK_NAME, BootJar.class, (bootJar) -> {
|
||||
bootJar.setDescription(
|
||||
"Assembles an executable jar archive containing the main classes and their dependencies.");
|
||||
|
|
@ -134,11 +168,9 @@ final class JavaPluginAction implements PluginApplicationAction {
|
|||
this.singlePublishedArtifact.addJarCandidate(bootJar);
|
||||
}
|
||||
|
||||
private void configureBootRunTask(Project project) {
|
||||
private void configureBootRunTask(Project project, TaskProvider<ResolveMainClassName> resolveMainClassName) {
|
||||
Callable<FileCollection> classpath = () -> javaPluginExtension(project).getSourceSets()
|
||||
.findByName(SourceSet.MAIN_SOURCE_SET_NAME).getRuntimeClasspath().filter(new JarTypeFileSpec());
|
||||
TaskProvider<ResolveMainClassName> resolveProvider = ResolveMainClassName.registerForTask("bootRun", project,
|
||||
classpath);
|
||||
project.getTasks().register("bootRun", BootRun.class, (run) -> {
|
||||
run.setDescription("Runs this project as a Spring Boot application.");
|
||||
run.setGroup(ApplicationPlugin.APPLICATION_GROUP);
|
||||
|
|
@ -149,7 +181,7 @@ final class JavaPluginAction implements PluginApplicationAction {
|
|||
}
|
||||
return Collections.emptyList();
|
||||
});
|
||||
run.getMainClass().convention(resolveProvider.flatMap(ResolveMainClassName::readMainClassName));
|
||||
run.getMainClass().convention(resolveMainClassName.flatMap(ResolveMainClassName::readMainClassName));
|
||||
configureToolchainConvention(project, run);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ import java.nio.file.Files;
|
|||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.InvalidUserDataException;
|
||||
|
|
@ -33,9 +32,6 @@ import org.gradle.api.Transformer;
|
|||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.file.RegularFile;
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.plugins.BasePlugin;
|
||||
import org.gradle.api.plugins.ExtensionContainer;
|
||||
import org.gradle.api.plugins.JavaApplication;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.tasks.Classpath;
|
||||
|
|
@ -43,10 +39,8 @@ import org.gradle.api.tasks.Input;
|
|||
import org.gradle.api.tasks.Optional;
|
||||
import org.gradle.api.tasks.OutputFile;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.api.tasks.TaskProvider;
|
||||
import org.gradle.work.DisableCachingByDefault;
|
||||
|
||||
import org.springframework.boot.gradle.dsl.SpringBootExtension;
|
||||
import org.springframework.boot.loader.tools.MainClassFinder;
|
||||
|
||||
/**
|
||||
|
|
@ -154,38 +148,6 @@ public class ResolveMainClassName extends DefaultTask {
|
|||
return this.outputFile.map(new ClassNameReader());
|
||||
}
|
||||
|
||||
static TaskProvider<ResolveMainClassName> registerForTask(String taskName, Project project,
|
||||
Callable<FileCollection> classpath) {
|
||||
TaskProvider<ResolveMainClassName> resolveMainClassNameProvider = project.getTasks()
|
||||
.register(taskName + "MainClassName", ResolveMainClassName.class, (resolveMainClassName) -> {
|
||||
ExtensionContainer extensions = project.getExtensions();
|
||||
resolveMainClassName.setDescription(
|
||||
"Resolves the name of the application's main class for the " + taskName + " task.");
|
||||
resolveMainClassName.setGroup(BasePlugin.BUILD_GROUP);
|
||||
resolveMainClassName.setClasspath(classpath);
|
||||
resolveMainClassName.getConfiguredMainClassName().convention(project.provider(() -> {
|
||||
String javaApplicationMainClass = getJavaApplicationMainClass(extensions);
|
||||
if (javaApplicationMainClass != null) {
|
||||
return javaApplicationMainClass;
|
||||
}
|
||||
SpringBootExtension springBootExtension = project.getExtensions()
|
||||
.findByType(SpringBootExtension.class);
|
||||
return springBootExtension.getMainClass().getOrNull();
|
||||
}));
|
||||
resolveMainClassName.getOutputFile()
|
||||
.set(project.getLayout().getBuildDirectory().file(taskName + "MainClassName"));
|
||||
});
|
||||
return resolveMainClassNameProvider;
|
||||
}
|
||||
|
||||
private static String getJavaApplicationMainClass(ExtensionContainer extensions) {
|
||||
JavaApplication javaApplication = extensions.findByType(JavaApplication.class);
|
||||
if (javaApplication == null) {
|
||||
return null;
|
||||
}
|
||||
return javaApplication.getMainClass().getOrNull();
|
||||
}
|
||||
|
||||
private static final class ClassNameReader implements Transformer<String, RegularFile> {
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -81,6 +81,12 @@ public class SpringBootPlugin implements Plugin<Project> {
|
|||
*/
|
||||
public static final String PRODUCTION_RUNTIME_CLASSPATH_CONFIGURATION_NAME = "productionRuntimeClasspath";
|
||||
|
||||
/**
|
||||
* The name of the {@link ResolveMainClassName} task.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static final String RESOLVE_MAIN_CLASS_NAME_TASK_NAME = "resolveMainClassName";
|
||||
|
||||
/**
|
||||
* The coordinates {@code (group:name:version)} of the
|
||||
* {@code spring-boot-dependencies} bom.
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ class WarPluginAction implements PluginApplicationAction {
|
|||
.getByName(SourceSet.MAIN_SOURCE_SET_NAME).getRuntimeClasspath()
|
||||
.minus(providedRuntimeConfiguration(project)).minus((developmentOnly.minus(productionRuntimeClasspath)))
|
||||
.filter(new JarTypeFileSpec());
|
||||
TaskProvider<ResolveMainClassName> resolveMainClassName = ResolveMainClassName
|
||||
.registerForTask(SpringBootPlugin.BOOT_WAR_TASK_NAME, project, classpath);
|
||||
TaskProvider<ResolveMainClassName> resolveMainClassName = project.getTasks()
|
||||
.named(SpringBootPlugin.RESOLVE_MAIN_CLASS_NAME_TASK_NAME, ResolveMainClassName.class);
|
||||
TaskProvider<BootWar> bootWarProvider = project.getTasks().register(SpringBootPlugin.BOOT_WAR_TASK_NAME,
|
||||
BootWar.class, (bootWar) -> {
|
||||
bootWar.setGroup(BasePlugin.BUILD_GROUP);
|
||||
|
|
|
|||
Loading…
Reference in New Issue