@ -18,7 +18,6 @@ package org.springframework.boot.maven;
import java.io.File ;
import java.io.IOException ;
import java.lang.reflect.Method ;
import java.net.MalformedURLException ;
import java.net.URL ;
import java.util.ArrayList ;
@ -95,7 +94,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
private boolean addResources = false ;
/ * *
* Path to agent jars . NOTE : a forked process is required to use this feature .
* Path to agent jars .
* @since 2.2 .0
* /
@Parameter ( property = "spring-boot.run.agents" )
@ -110,7 +109,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
/ * *
* Current working directory to use for the application . If not specified , basedir
* will be used . NOTE : a forked process is required to use this feature .
* will be used .
* @since 1.5 .0
* /
@Parameter ( property = "spring-boot.run.workingDirectory" )
@ -119,15 +118,13 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
/ * *
* JVM arguments that should be associated with the forked process used to run the
* application . On command line , make sure to wrap multiple values between quotes .
* NOTE : a forked process is required to use this feature .
* @since 1.1 .0
* /
@Parameter ( property = "spring-boot.run.jvmArguments" )
private String jvmArguments ;
/ * *
* List of JVM system properties to pass to the process . NOTE : a forked process is
* required to use this feature .
* List of JVM system properties to pass to the process .
* @since 2.1 .0
* /
@Parameter
@ -135,8 +132,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
/ * *
* List of Environment variables that should be associated with the forked process
* used to run the application . NOTE : a forked process is required to use this
* feature .
* used to run the application .
* @since 2.1 .0
* /
@Parameter
@ -191,17 +187,6 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
@Parameter ( defaultValue = "${project.build.outputDirectory}" , required = true )
private File classesDirectory ;
/ * *
* Deprecated . Flag to indicate if the run processes should be forked . Disabling
* forking will disable some features such as an agent , custom JVM arguments , devtools
* or specifying the working directory to use .
* @since 1.2 .0
* @deprecated since 2.7 .0 for removal in 3.0 .0 with no replacement
* /
@Parameter ( property = "spring-boot.run.fork" , defaultValue = "true" )
@Deprecated
private boolean fork ;
/ * *
* Flag to include the test classpath when running .
* @since 1.3 .0
@ -225,71 +210,14 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
run ( getStartClass ( ) ) ;
}
/ * *
* Specify if the application process should be forked .
* @return { @code true } if the application process should be forked
* @deprecated since 2.7 .0 for removal in 3.0 .0 with no replacement
* /
@Deprecated
protected boolean isFork ( ) {
return this . fork ;
}
private boolean hasAgent ( ) {
return ( this . agents ! = null & & this . agents . length > 0 ) ;
}
private boolean hasJvmArgs ( ) {
return ( this . jvmArguments ! = null & & ! this . jvmArguments . isEmpty ( ) )
| | ( this . systemPropertyVariables ! = null & & ! this . systemPropertyVariables . isEmpty ( ) ) ;
}
private boolean hasWorkingDirectorySet ( ) {
return this . workingDirectory ! = null ;
}
@SuppressWarnings ( "deprecation" )
private void run ( String startClassName ) throws MojoExecutionException , MojoFailureException {
boolean fork = isFork ( ) ;
this . project . getProperties ( ) . setProperty ( "_spring.boot.fork.enabled" , Boolean . toString ( fork ) ) ;
if ( fork ) {
doRunWithForkedJvm ( startClassName ) ;
}
else {
logDisabledFork ( ) ;
runWithMavenJvm ( startClassName , resolveApplicationArguments ( ) . asArray ( ) ) ;
}
}
/ * *
* Log a warning indicating that fork mode has been explicitly disabled while some
* conditions are present that require to enable it .
* /
@Deprecated
protected void logDisabledFork ( ) {
if ( getLog ( ) . isWarnEnabled ( ) ) {
if ( hasAgent ( ) ) {
getLog ( ) . warn ( "Fork mode disabled, ignoring agent" ) ;
}
if ( hasJvmArgs ( ) ) {
RunArguments runArguments = resolveJvmArguments ( ) ;
getLog ( ) . warn ( "Fork mode disabled, ignoring JVM argument(s) ["
+ String . join ( " " , runArguments . asArray ( ) ) + "]" ) ;
}
if ( hasWorkingDirectorySet ( ) ) {
getLog ( ) . warn ( "Fork mode disabled, ignoring working directory configuration" ) ;
}
}
}
private void doRunWithForkedJvm ( String startClassName ) throws MojoExecutionException , MojoFailureException {
List < String > args = new ArrayList < > ( ) ;
addAgents ( args ) ;
addJvmArgs ( args ) ;
addClasspath ( args ) ;
args . add ( startClassName ) ;
addArgs ( args ) ;
run WithForkedJvm ( ( this . workingDirectory ! = null ) ? this . workingDirectory : this . project . getBasedir ( ) , args ,
run ( ( this . workingDirectory ! = null ) ? this . workingDirectory : this . project . getBasedir ( ) , args ,
determineEnvironmentVariables ( ) ) ;
}
@ -301,19 +229,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @throws MojoExecutionException in case of MOJO execution errors
* @throws MojoFailureException in case of MOJO failures
* /
protected abstract void runWithForkedJvm ( File workingDirectory , List < String > args ,
Map < String , String > environmentVariables ) throws MojoExecutionException , MojoFailureException ;
/ * *
* Run with the current VM , using the specified arguments .
* @param startClassName the class to run
* @param arguments the class arguments
* @throws MojoExecutionException in case of MOJO execution errors
* @throws MojoFailureException in case of MOJO failures
* @deprecated since 2.7 .0 for removal in 3.0 .0 with no replacement
* /
@Deprecated
protected abstract void runWithMavenJvm ( String startClassName , String . . . arguments )
protected abstract void run ( File workingDirectory , List < String > args , Map < String , String > environmentVariables )
throws MojoExecutionException , MojoFailureException ;
/ * *
@ -510,78 +426,6 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
}
/ * *
* Isolated { @link ThreadGroup } to capture uncaught exceptions .
* /
class IsolatedThreadGroup extends ThreadGroup {
private final Object monitor = new Object ( ) ;
private Throwable exception ;
IsolatedThreadGroup ( String name ) {
super ( name ) ;
}
@Override
public void uncaughtException ( Thread thread , Throwable ex ) {
if ( ! ( ex instanceof ThreadDeath ) ) {
synchronized ( this . monitor ) {
this . exception = ( this . exception ! = null ) ? this . exception : ex ;
}
getLog ( ) . warn ( ex ) ;
}
}
void rethrowUncaughtException ( ) throws MojoExecutionException {
synchronized ( this . monitor ) {
if ( this . exception ! = null ) {
throw new MojoExecutionException (
"An exception occurred while running. " + this . exception . getMessage ( ) , this . exception ) ;
}
}
}
}
/ * *
* Runner used to launch the application .
* /
class LaunchRunner implements Runnable {
private final String startClassName ;
private final String [ ] args ;
LaunchRunner ( String startClassName , String . . . args ) {
this . startClassName = startClassName ;
this . args = ( args ! = null ) ? args : new String [ ] { } ;
}
@Override
public void run ( ) {
Thread thread = Thread . currentThread ( ) ;
ClassLoader classLoader = thread . getContextClassLoader ( ) ;
try {
Class < ? > startClass = Class . forName ( this . startClassName , false , classLoader ) ;
Method mainMethod = startClass . getMethod ( "main" , String [ ] . class ) ;
if ( ! mainMethod . canAccess ( null ) ) {
mainMethod . setAccessible ( true ) ;
}
mainMethod . invoke ( null , new Object [ ] { this . args } ) ;
}
catch ( NoSuchMethodException ex ) {
Exception wrappedEx = new Exception (
"The specified mainClass doesn't contain a main method with appropriate signature." , ex ) ;
thread . getThreadGroup ( ) . uncaughtException ( thread , wrappedEx ) ;
}
catch ( Exception ex ) {
thread . getThreadGroup ( ) . uncaughtException ( thread , ex ) ;
}
}
}
/ * *
* Format System properties .
* /