diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java index b04951e203..03f1bf75cd 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java @@ -37,11 +37,9 @@ import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts; -import org.apache.maven.toolchain.Toolchain; import org.apache.maven.toolchain.ToolchainManager; import org.springframework.boot.loader.tools.FileUtils; -import org.springframework.boot.loader.tools.JavaExecutable; /** * Base class to run a Spring Boot application. @@ -215,20 +213,24 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { addClasspath(args); args.add(startClassName); addArgs(args); - run((this.workingDirectory != null) ? this.workingDirectory : this.project.getBasedir(), args, - determineEnvironmentVariables()); + JavaProcessExecutor processExecutor = new JavaProcessExecutor(this.session, this.toolchainManager); + File workingDirectoryToUse = (this.workingDirectory != null) ? this.workingDirectory + : this.project.getBasedir(); + run(processExecutor, workingDirectoryToUse, args, determineEnvironmentVariables()); } /** - * Run with a forked VM, using the specified command line arguments. + * Run the application. + * @param processExecutor the {@link JavaProcessExecutor} to use * @param workingDirectory the working directory of the forked JVM * @param args the arguments (JVM arguments and application arguments) * @param environmentVariables the environment variables * @throws MojoExecutionException in case of MOJO execution errors * @throws MojoFailureException in case of MOJO failures + * @since 3.0.0 */ - protected abstract void run(File workingDirectory, List args, Map environmentVariables) - throws MojoExecutionException, MojoFailureException; + protected abstract void run(JavaProcessExecutor processExecutor, File workingDirectory, List args, + Map environmentVariables) throws MojoExecutionException, MojoFailureException; /** * Resolve the application arguments to use. @@ -241,16 +243,6 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { return runArguments; } - /** - * Provides access to the java binary executable, regardless of OS. - * @return the java executable - */ - protected String getJavaExecutable() { - Toolchain toolchain = this.toolchainManager.getToolchainFromBuildContext("jdk", this.session); - String javaExecutable = (toolchain != null) ? toolchain.findTool("java") : null; - return (javaExecutable != null) ? javaExecutable : new JavaExecutable().toString(); - } - /** * Resolve the environment variables to use. * @return an {@link EnvVariables} defining the environment variables diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JavaProcessExecutor.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JavaProcessExecutor.java index 94941b6a1f..e1cc925259 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JavaProcessExecutor.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/JavaProcessExecutor.java @@ -20,6 +20,7 @@ import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; +import java.util.function.Consumer; import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.MojoExecutionException; @@ -42,9 +43,23 @@ class JavaProcessExecutor { private final ToolchainManager toolchainManager; + private final Consumer runProcessCustomizer; + JavaProcessExecutor(MavenSession mavenSession, ToolchainManager toolchainManager) { + this(mavenSession, toolchainManager, null); + } + + private JavaProcessExecutor(MavenSession mavenSession, ToolchainManager toolchainManager, + Consumer runProcessCustomizer) { this.mavenSession = mavenSession; this.toolchainManager = toolchainManager; + this.runProcessCustomizer = runProcessCustomizer; + } + + JavaProcessExecutor withRunProcessCustomizer(Consumer customizer) { + Consumer combinedCustomizer = (this.runProcessCustomizer != null) + ? this.runProcessCustomizer.andThen(customizer) : customizer; + return new JavaProcessExecutor(this.mavenSession, this.toolchainManager, combinedCustomizer); } int run(File workingDirectory, List args, Map environmentVariables) @@ -62,6 +77,18 @@ class JavaProcessExecutor { } } + RunProcess runAsync(File workingDirectory, List args, Map environmentVariables) + throws MojoExecutionException { + try { + RunProcess runProcess = new RunProcess(workingDirectory, getJavaExecutable()); + runProcess.run(false, args, environmentVariables); + return runProcess; + } + catch (IOException ex) { + throw new MojoExecutionException("Process execution failed", ex); + } + } + private boolean hasTerminatedSuccessfully(int exitCode) { return (exitCode == 0 || exitCode == EXIT_CODE_SIGINT); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunMojo.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunMojo.java index 6cc51b7706..7645fa338c 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunMojo.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunMojo.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.Map; import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Execute; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; @@ -43,8 +44,6 @@ import org.springframework.boot.loader.tools.RunProcess; @Execute(phase = LifecyclePhase.TEST_COMPILE) public class RunMojo extends AbstractRunMojo { - private static final int EXIT_CODE_SIGINT = 130; - /** * Whether the JVM's launch should be optimized. * @since 2.2.0 @@ -62,25 +61,11 @@ public class RunMojo extends AbstractRunMojo { } @Override - protected void run(File workingDirectory, List args, Map environmentVariables) - throws MojoExecutionException { - int exitCode = forkJvm(workingDirectory, args, environmentVariables); - if (exitCode == 0 || exitCode == EXIT_CODE_SIGINT) { - return; - } - throw new MojoExecutionException("Application finished with exit code: " + exitCode); - } - - private int forkJvm(File workingDirectory, List args, Map environmentVariables) - throws MojoExecutionException { - try { - RunProcess runProcess = new RunProcess(workingDirectory, getJavaExecutable()); - Runtime.getRuntime().addShutdownHook(new Thread(new RunProcessKiller(runProcess))); - return runProcess.run(true, args, environmentVariables); - } - catch (Exception ex) { - throw new MojoExecutionException("Could not exec java", ex); - } + protected void run(JavaProcessExecutor processExecutor, File workingDirectory, List args, + Map environmentVariables) throws MojoExecutionException, MojoFailureException { + processExecutor.withRunProcessCustomizer( + (runProcess) -> Runtime.getRuntime().addShutdownHook(new Thread(new RunProcessKiller(runProcess)))) + .run(workingDirectory, args, environmentVariables); } private static final class RunProcessKiller implements Runnable { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java index afedb82554..a28de2d032 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java @@ -86,9 +86,9 @@ public class StartMojo extends AbstractRunMojo { private final Object lock = new Object(); @Override - protected void run(File workingDirectory, List args, Map environmentVariables) - throws MojoExecutionException, MojoFailureException { - RunProcess runProcess = runProcess(workingDirectory, args, environmentVariables); + protected void run(JavaProcessExecutor processExecutor, File workingDirectory, List args, + Map environmentVariables) throws MojoExecutionException, MojoFailureException { + RunProcess runProcess = processExecutor.runAsync(workingDirectory, args, environmentVariables); try { waitForSpringApplication(); } @@ -98,18 +98,6 @@ public class StartMojo extends AbstractRunMojo { } } - private RunProcess runProcess(File workingDirectory, List args, Map environmentVariables) - throws MojoExecutionException { - try { - RunProcess runProcess = new RunProcess(workingDirectory, getJavaExecutable()); - runProcess.run(false, args, environmentVariables); - return runProcess; - } - catch (Exception ex) { - throw new MojoExecutionException("Could not exec java", ex); - } - } - @Override protected RunArguments resolveApplicationArguments() { RunArguments applicationArguments = super.resolveApplicationArguments();