Fork application process with Maven by default

Closes gh-16945
pull/16972/head
Stephane Nicoll 6 years ago
parent 3432044997
commit a5537bd2e1

@ -829,8 +829,8 @@ and triggers a restart. In IntelliJ IDEA, building the project
==== ====
As long as forking is enabled, you can also start your application by using the supported As long as forking is enabled, you can also start your application by using the supported
build plugins (Maven and Gradle), since DevTools needs an isolated application build plugins (Maven and Gradle), since DevTools needs an isolated application
classloader to operate properly. By default, Gradle and Maven do that when they detect classloader to operate properly. By default, the Gradle and Maven plugins fork the
DevTools on the classpath. application process.
==== ====

@ -22,9 +22,6 @@
<goals> <goals>
<goal>run</goal> <goal>run</goal>
</goals> </goals>
<configuration>
<fork>true</fork>
</configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>

@ -23,7 +23,6 @@
<goal>run</goal> <goal>run</goal>
</goals> </goals>
<configuration> <configuration>
<fork>true</fork>
<profiles> <profiles>
<profile>foo</profile> <profile>foo</profile>
<profile>bar</profile> <profile>bar</profile>

@ -22,6 +22,9 @@
<goals> <goals>
<goal>run</goal> <goal>run</goal>
</goals> </goals>
<configuration>
<fork>false</fork>
</configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.boot.maven.it</groupId>
<artifactId>start-stop-automatic-fork</artifactId>
<version>0.0.1.BUILD-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>@java.version@</maven.compiler.source>
<maven.compiler.target>@java.version@</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>@build-helper-maven-plugin.version@</version>
<executions>
<execution>
<id>reserve-jmx-port</id>
<goals>
<goal>reserve-network-port</goal>
</goals>
<phase>process-resources</phase>
<configuration>
<portNames>
<portName>jmx.port</portName>
</portNames>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
<executions>
<execution>
<id>pre-integration-test</id>
<goals>
<goal>start</goal>
</goals>
<configuration>
<jvmArguments>-Dfoo=bar</jvmArguments>
</configuration>
</execution>
<execution>
<id>post-integration-test</id>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
<configuration>
<jmxPort>${jmx.port}</jmxPort>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -1,82 +0,0 @@
/*
* Copyright 2012-2017 the original author or authors.
*
* 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
*
* https://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 org.test;
import java.lang.management.ManagementFactory;
import javax.management.MBeanServer;
import javax.management.ObjectName;
/**
* This sample app simulates the JMX Mbean that is exposed by the Spring Boot application.
*/
public class SampleApplication {
private static final Object lock = new Object();
public static void main(String[] args) throws Exception {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName(
"org.springframework.boot:type=Admin,name=SpringApplication");
SpringApplicationAdmin mbean = new SpringApplicationAdmin();
mbs.registerMBean(mbean, name);
// Flag the app as ready
mbean.ready = true;
int waitAttempts = 0;
while (!mbean.shutdownInvoked) {
if (waitAttempts > 30) {
throw new IllegalStateException(
"Shutdown should have been invoked by now");
}
synchronized (lock) {
lock.wait(250);
}
waitAttempts++;
}
}
public interface SpringApplicationAdminMXBean {
boolean isReady();
void shutdown();
}
static class SpringApplicationAdmin implements SpringApplicationAdminMXBean {
private boolean ready;
private boolean shutdownInvoked;
@Override
public boolean isReady() {
System.out.println("isReady: " + this.ready);
return this.ready;
}
@Override
public void shutdown() {
this.shutdownInvoked = true;
System.out.println("Shutdown requested");
}
}
}

@ -1,5 +0,0 @@
import static org.junit.Assert.assertTrue
def file = new File(basedir, "build.log")
assertTrue 'Start should have waited for application to be ready', file.text.contains("isReady: true")
assertTrue 'Shutdown should have been invoked', file.text.contains("Shutdown requested")

@ -50,7 +50,6 @@
</execution> </execution>
</executions> </executions>
<configuration> <configuration>
<fork>true</fork>
<jmxPort>${jmx.port}</jmxPort> <jmxPort>${jmx.port}</jmxPort>
</configuration> </configuration>
</plugin> </plugin>

@ -30,6 +30,9 @@
</goals> </goals>
</execution> </execution>
</executions> </executions>
<configuration>
<fork>false</fork>
</configuration>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>

@ -75,8 +75,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
private boolean addResources = false; private boolean addResources = false;
/** /**
* Path to agent jar. NOTE: the use of agents means that processes will be started by * Path to agent jar. NOTE: a forked process is required to use this feature.
* forking a new JVM.
* @since 1.0 * @since 1.0
* @deprecated since 2.2.0 in favor of {@code agents} * @deprecated since 2.2.0 in favor of {@code agents}
*/ */
@ -85,8 +84,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
private File[] agent; private File[] agent;
/** /**
* Path to agent jars. NOTE: the use of agents means that processes will be started by * Path to agent jars. NOTE: a forked process is required to use this feature.
* forking a new JVM.
* @since 2.2 * @since 2.2
*/ */
@Parameter(property = "spring-boot.run.agents") @Parameter(property = "spring-boot.run.agents")
@ -101,8 +99,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
/** /**
* Current working directory to use for the application. If not specified, basedir * Current working directory to use for the application. If not specified, basedir
* will be used. NOTE: the use of working directory means that processes will be * will be used. NOTE: a forked process is required to use this feature.
* started by forking a new JVM.
* @since 1.5 * @since 1.5
*/ */
@Parameter(property = "spring-boot.run.workingDirectory") @Parameter(property = "spring-boot.run.workingDirectory")
@ -111,16 +108,15 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
/** /**
* JVM arguments that should be associated with the forked process used to run the * 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. * application. On command line, make sure to wrap multiple values between quotes.
* NOTE: the use of JVM arguments means that processes will be started by forking a * NOTE: a forked process is required to use this feature.
* new JVM.
* @since 1.1 * @since 1.1
*/ */
@Parameter(property = "spring-boot.run.jvmArguments") @Parameter(property = "spring-boot.run.jvmArguments")
private String jvmArguments; private String jvmArguments;
/** /**
* List of JVM system properties to pass to the process. NOTE: the use of system * List of JVM system properties to pass to the process. NOTE: a forked process is
* properties means that processes will be started by forking a new JVM. * required to use this feature.
* @since 2.1 * @since 2.1
*/ */
@Parameter @Parameter
@ -128,8 +124,8 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
/** /**
* List of Environment variables that should be associated with the forked process * List of Environment variables that should be associated with the forked process
* used to run the application. NOTE: the use of Environment variables means that * used to run the application. NOTE: a forked process is required to use this
* processes will be started by forking a new JVM. * feature.
* @since 2.1 * @since 2.1
*/ */
@Parameter @Parameter
@ -177,13 +173,13 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
private File classesDirectory; private File classesDirectory;
/** /**
* Flag to indicate if the run processes should be forked. {@code fork} is * Flag to indicate if the run processes should be forked. Disabling forking will
* automatically enabled if an agent, jvmArguments or working directory are specified, * disable some features such as an agent, custom JVM arguments, devtools or
* or if devtools is present. * specifying the working directory to use.
* @since 1.2 * @since 1.2
*/ */
@Parameter(property = "spring-boot.run.fork") @Parameter(property = "spring-boot.run.fork", defaultValue = "true")
private Boolean fork; private boolean fork;
/** /**
* Flag to include the test classpath when running. * Flag to include the test classpath when running.
@ -213,15 +209,16 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @return {@code true} if the application process should be forked * @return {@code true} if the application process should be forked
*/ */
protected boolean isFork() { protected boolean isFork() {
return (Boolean.TRUE.equals(this.fork) return this.fork;
|| (this.fork == null && enableForkByDefault()));
} }
/** /**
* Specify if fork should be enabled by default. * Specify if fork should be enabled by default.
* @return {@code true} if fork should be enabled by default * @return {@code true} if fork should be enabled by default
* @see #logDisabledFork() * @see #logDisabledFork()
* @deprecated as of 2.2.0 in favour of enabling forking by default.
*/ */
@Deprecated
protected boolean enableForkByDefault() { protected boolean enableForkByDefault() {
return hasAgent() || hasJvmArgs() || hasEnvVariables() return hasAgent() || hasJvmArgs() || hasEnvVariables()
|| hasWorkingDirectorySet(); || hasWorkingDirectorySet();
@ -264,7 +261,6 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
/** /**
* Log a warning indicating that fork mode has been explicitly disabled while some * Log a warning indicating that fork mode has been explicitly disabled while some
* conditions are present that require to enable it. * conditions are present that require to enable it.
* @see #enableForkByDefault()
*/ */
protected void logDisabledFork() { protected void logDisabledFork() {
if (getLog().isWarnEnabled()) { if (getLog().isWarnEnabled()) {
@ -273,9 +269,8 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
} }
if (hasJvmArgs()) { if (hasJvmArgs()) {
RunArguments runArguments = resolveJvmArguments(); RunArguments runArguments = resolveJvmArguments();
getLog().warn("Fork mode disabled, ignoring JVM argument(s) [" + Arrays getLog().warn("Fork mode disabled, ignoring JVM argument(s) ["
.stream(runArguments.asArray()).collect(Collectors.joining(" ")) + String.join(" ", runArguments.asArray()) + "]");
+ "]");
} }
if (hasWorkingDirectorySet()) { if (hasWorkingDirectorySet()) {
getLog().warn( getLog().warn(

@ -54,6 +54,7 @@ public class RunMojo extends AbstractRunMojo {
private Boolean hasDevtools; private Boolean hasDevtools;
@Override @Override
@Deprecated
protected boolean enableForkByDefault() { protected boolean enableForkByDefault() {
return super.enableForkByDefault() || hasDevtools(); return super.enableForkByDefault() || hasDevtools();
} }

@ -67,8 +67,7 @@ public class StartMojo extends AbstractRunMojo {
private String jmxName = SpringApplicationAdminClient.DEFAULT_OBJECT_NAME; private String jmxName = SpringApplicationAdminClient.DEFAULT_OBJECT_NAME;
/** /**
* The port to use to expose the platform MBeanServer if the application needs to be * The port to use to expose the platform MBeanServer if the application is forked.
* forked.
*/ */
@Parameter @Parameter
private int jmxPort = 9001; private int jmxPort = 9001;

@ -6,10 +6,8 @@
2014-05-14 2014-05-14
----- -----
By default, the <<<run>>> goal runs in the same process unless jvm arguments or an agent have been specified. You By default, the <<<run>>> goal runs your application in a forked process. If you need to
can enable or disable forking explicitly using the <<<fork>>> attribute. debug it, you should add the necessary JVM arguments to enable remote debugging. The
If you need to fork the process and debug it you can add the necessary JVM arguments to enable remote debugging. The
following configuration suspend the process until a debugger has joined on port 5005: following configuration suspend the process until a debugger has joined on port 5005:
--- ---
@ -38,8 +36,8 @@
</project> </project>
--- ---
Note that since you specified some JVM arguments, the process is forked automatically. These arguments can be These arguments can be specified on the command line as well, make sure to wrap that
specified on the command line as well, make sure to wrap that properly, that is: properly, that is:
--- ---
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005" mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"

@ -130,10 +130,11 @@ Usage
mvn spring-boot:run mvn spring-boot:run
--- ---
By default the application is executed directly from the Maven JVM. If you need to run By default the application is executed in a forked process. Although this is not
in a forked process you can use the 'fork' option. Forking will also occur if the recommended, it is possible to execute the application directly from the Maven JVM by
'jvmArguments', 'systemPropertyVariables', 'environmentVariables' or 'agent' options disabling the <<<fork>>> property. Doing so means that <<<jvmArguments>>>,
are specified, or if devtools is present. <<<systemPropertyVariables>>>, <<<environmentVariables>>> and <<<agent>>> options are
ignored.
If you need to specify some JVM arguments (i.e. for debugging purposes), you can use If you need to specify some JVM arguments (i.e. for debugging purposes), you can use
the <<<jvmArguments>>> parameter, see {{{./examples/run-debug.html}Debug the application}} the <<<jvmArguments>>> parameter, see {{{./examples/run-debug.html}Debug the application}}

Loading…
Cancel
Save