Commit 97f15d60 authored by Stephane Nicoll's avatar Stephane Nicoll

Auto-detect fork value in stop goal

So far, one has to set the "fork" value to both the start and stop
goals. Since they have the same name, sharing them in a global
configuration element does the trick. However, the plugin also supports
auto-detection of the fork value according to other parameters:
typically if an agent or jvm arguments are set, forking will be
automatically enabled. This is a problem since the stop goal is not aware
of that.

This commit transmits the value in a property attached to the
`MavenProject`. That way, the stop goal can retrieve that value and
apply the same defaults. This has the side effect that specifying the
fork value isn't necessary anymore.

Closes gh-6747
parent a5c6b095
<?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 http://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>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<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>
/*
* Copyright 2012-2016 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
*
* http://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");
}
}
}
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")
......@@ -90,6 +90,8 @@ 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: the use of JVM arguments means that processes will be started by forking
* a new JVM.
* @since 1.1
*/
@Parameter(property = "run.jvmArguments")
......@@ -137,8 +139,8 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
private File classesDirectory;
/**
* Flag to indicate if the run processes should be forked. By default process forking
* is only used if an agent or jvmArguments are specified.
* Flag to indicate if the run processes should be forked. {@code fork } is
* automatically enabled if an agent or jvmArguments are specified.
* @since 1.2
*/
@Parameter(property = "fork")
......@@ -212,7 +214,10 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
private void run(String startClassName)
throws MojoExecutionException, MojoFailureException {
findAgent();
if (isFork()) {
boolean forkEnabled = isFork();
this.project.getProperties().setProperty("_spring.boot.fork.enabled",
Boolean.toString(forkEnabled));
if (forkEnabled) {
doRunWithForkedJvm(startClassName);
}
else {
......
......@@ -181,7 +181,7 @@ public class StartMojo extends AbstractRunMojo {
private void waitForSpringApplication()
throws MojoFailureException, MojoExecutionException {
try {
if (Boolean.TRUE.equals(isFork())) {
if (isFork()) {
waitForForkedSpringApplication();
}
else {
......
......@@ -29,6 +29,7 @@ import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
/**
* Stop a spring application that has been started by the "start" goal. Typically invoked
......@@ -41,9 +42,17 @@ import org.apache.maven.plugins.annotations.Parameter;
public class StopMojo extends AbstractMojo {
/**
* Flag to indicate if the run processes should be forked. Must be aligned to the
* value used to {@link StartMojo start} the process
* @since 1.2
* The Maven project.
* @since 1.4.1
*/
@Parameter(defaultValue = "${project}", readonly = true, required = true)
private MavenProject project;
/**
* Flag to indicate if process to stop was forked. By default, the value is inherited
* from the {@link MavenProject}. If it is set, it must match the value used to
* {@link StartMojo start} the process.
* @since 1.3
*/
@Parameter(property = "fork")
private Boolean fork;
......@@ -77,7 +86,7 @@ public class StopMojo extends AbstractMojo {
}
getLog().info("Stopping application...");
try {
if (Boolean.TRUE.equals(this.fork)) {
if (isForked()) {
stopForkedProcess();
}
else {
......@@ -90,6 +99,14 @@ public class StopMojo extends AbstractMojo {
}
}
private boolean isForked() {
if (this.fork != null) {
return this.fork;
}
String property = this.project.getProperties().getProperty("_spring.boot.fork.enabled");
return Boolean.valueOf(property);
}
private void stopForkedProcess()
throws IOException, MojoFailureException, MojoExecutionException {
JMXConnector connector = SpringApplicationAdminClient.connect(this.jmxPort);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment