From 97f15d606d9e1f05695c2b223ef8742b350ad8d5 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Sat, 27 Aug 2016 12:33:44 +0200 Subject: [PATCH] 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 --- .../invoker.properties | 1 + .../src/it/start-stop-automatic-fork/pom.xml | 58 +++++++++++++ .../main/java/org/test/SampleApplication.java | 82 +++++++++++++++++++ .../start-stop-automatic-fork/verify.groovy | 5 ++ .../boot/maven/AbstractRunMojo.java | 11 ++- .../springframework/boot/maven/StartMojo.java | 2 +- .../springframework/boot/maven/StopMojo.java | 25 +++++- 7 files changed, 176 insertions(+), 8 deletions(-) create mode 100644 spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-automatic-fork/invoker.properties create mode 100644 spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-automatic-fork/pom.xml create mode 100644 spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-automatic-fork/src/main/java/org/test/SampleApplication.java create mode 100644 spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-automatic-fork/verify.groovy diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-automatic-fork/invoker.properties b/spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-automatic-fork/invoker.properties new file mode 100644 index 00000000000..793d89fcd37 --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-automatic-fork/invoker.properties @@ -0,0 +1 @@ +invoker.goals=clean verify \ No newline at end of file diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-automatic-fork/pom.xml b/spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-automatic-fork/pom.xml new file mode 100644 index 00000000000..577fd23131e --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-automatic-fork/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + org.springframework.boot.maven.it + start-stop-automatic-fork + 0.0.1.BUILD-SNAPSHOT + + UTF-8 + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + reserve-jmx-port + + reserve-network-port + + process-resources + + + jmx.port + + + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + pre-integration-test + + start + + + -Dfoo=bar + + + + post-integration-test + + stop + + + + + ${jmx.port} + + + + + diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-automatic-fork/src/main/java/org/test/SampleApplication.java b/spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-automatic-fork/src/main/java/org/test/SampleApplication.java new file mode 100644 index 00000000000..b9c69d69c4b --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-automatic-fork/src/main/java/org/test/SampleApplication.java @@ -0,0 +1,82 @@ +/* + * 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"); + } + + } + +} diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-automatic-fork/verify.groovy b/spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-automatic-fork/verify.groovy new file mode 100644 index 00000000000..5aa87af6830 --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-automatic-fork/verify.groovy @@ -0,0 +1,5 @@ +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") diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java index bc4721cce45..2031162b934 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java +++ b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java @@ -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 { diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java index 0e45d747042..74fe47655c4 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java +++ b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java @@ -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 { diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StopMojo.java b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StopMojo.java index 5e04ad96873..aee5532e0c6 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StopMojo.java +++ b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StopMojo.java @@ -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);