Polish start stop support
This commit is contained in:
parent
09a29a7207
commit
bce4bb8860
|
|
@ -43,7 +43,8 @@ import org.springframework.jmx.export.MBeanExporter;
|
|||
class SpringApplicationLifecycleAutoConfiguration {
|
||||
|
||||
/**
|
||||
* The property to use to customize the {@code ObjectName} of the application lifecycle mbean.
|
||||
* The property to use to customize the {@code ObjectName} of the application
|
||||
* lifecycle mbean.
|
||||
*/
|
||||
static final String JMX_NAME_PROPERTY = "spring.context.lifecycle.jmx-name";
|
||||
|
||||
|
|
@ -61,10 +62,10 @@ class SpringApplicationLifecycleAutoConfiguration {
|
|||
@Bean
|
||||
public SpringApplicationLifecycleRegistrar springApplicationLifecycleRegistrar()
|
||||
throws MalformedObjectNameException {
|
||||
|
||||
String jmxName = this.environment.getProperty(JMX_NAME_PROPERTY, DEFAULT_JMX_NAME);
|
||||
if (mbeanExporter != null) { // Make sure to not register that MBean twice
|
||||
mbeanExporter.addExcludedBean(jmxName);
|
||||
String jmxName = this.environment
|
||||
.getProperty(JMX_NAME_PROPERTY, DEFAULT_JMX_NAME);
|
||||
if (this.mbeanExporter != null) { // Make sure to not register that MBean twice
|
||||
this.mbeanExporter.addExcludedBean(jmxName);
|
||||
}
|
||||
return new SpringApplicationLifecycleRegistrar(jmxName);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.boot.autoconfigure.context;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
|
|
@ -28,7 +29,6 @@ import org.junit.Before;
|
|||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
|
||||
import org.springframework.boot.test.EnvironmentTestUtils;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
|
|
@ -65,17 +65,16 @@ public class SpringApplicationLifecycleAutoConfigurationTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void notRegisteredByDefault() throws MalformedObjectNameException, InstanceNotFoundException {
|
||||
public void notRegisteredByDefault() throws MalformedObjectNameException,
|
||||
InstanceNotFoundException {
|
||||
load();
|
||||
|
||||
thrown.expect(InstanceNotFoundException.class);
|
||||
this.thrown.expect(InstanceNotFoundException.class);
|
||||
this.mBeanServer.getObjectInstance(createDefaultObjectName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registeredWithProperty() throws Exception {
|
||||
load(ENABLE_LIFECYCLE_PROP);
|
||||
|
||||
ObjectName objectName = createDefaultObjectName();
|
||||
ObjectInstance objectInstance = this.mBeanServer.getObjectInstance(objectName);
|
||||
assertNotNull("Lifecycle bean should have been registered", objectInstance);
|
||||
|
|
@ -84,18 +83,17 @@ public class SpringApplicationLifecycleAutoConfigurationTests {
|
|||
@Test
|
||||
public void registerWithCustomJmxName() throws InstanceNotFoundException {
|
||||
String customJmxName = "org.acme:name=FooBar";
|
||||
System.setProperty(SpringApplicationLifecycleAutoConfiguration.JMX_NAME_PROPERTY, customJmxName);
|
||||
System.setProperty(SpringApplicationLifecycleAutoConfiguration.JMX_NAME_PROPERTY,
|
||||
customJmxName);
|
||||
try {
|
||||
load(ENABLE_LIFECYCLE_PROP);
|
||||
|
||||
try {
|
||||
this.mBeanServer.getObjectInstance(createObjectName(customJmxName));
|
||||
}
|
||||
catch (InstanceNotFoundException e) {
|
||||
catch (InstanceNotFoundException ex) {
|
||||
fail("lifecycle MBean should have been exposed with custom name");
|
||||
}
|
||||
|
||||
thrown.expect(InstanceNotFoundException.class); // Should not be exposed
|
||||
this.thrown.expect(InstanceNotFoundException.class); // Should not be exposed
|
||||
this.mBeanServer.getObjectInstance(createDefaultObjectName());
|
||||
}
|
||||
finally {
|
||||
|
|
@ -111,18 +109,18 @@ public class SpringApplicationLifecycleAutoConfigurationTests {
|
|||
try {
|
||||
return new ObjectName(jmxName);
|
||||
}
|
||||
catch (MalformedObjectNameException e) {
|
||||
throw new IllegalStateException("Invalid jmx name " + jmxName, e);
|
||||
catch (MalformedObjectNameException ex) {
|
||||
throw new IllegalStateException("Invalid jmx name " + jmxName, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void load(String... environment) {
|
||||
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
|
||||
EnvironmentTestUtils.addEnvironment(applicationContext, environment);
|
||||
applicationContext.register(JmxAutoConfiguration.class, SpringApplicationLifecycleAutoConfiguration.class);
|
||||
applicationContext.register(JmxAutoConfiguration.class,
|
||||
SpringApplicationLifecycleAutoConfiguration.class);
|
||||
applicationContext.refresh();
|
||||
this.context = applicationContext;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,13 +55,6 @@ public class RunProcess {
|
|||
return run(waitForProcess, Arrays.asList(args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Kill this process.
|
||||
*/
|
||||
public void kill() {
|
||||
doKill();
|
||||
}
|
||||
|
||||
protected int run(boolean waitForProcess, Collection<String> args) throws IOException {
|
||||
ProcessBuilder builder = new ProcessBuilder(this.command);
|
||||
builder.command().addAll(args);
|
||||
|
|
@ -131,7 +124,7 @@ public class RunProcess {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
catch (Exception ex) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -180,6 +173,13 @@ public class RunProcess {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Kill this process.
|
||||
*/
|
||||
public void kill() {
|
||||
doKill();
|
||||
}
|
||||
|
||||
private boolean doKill() {
|
||||
// destroy the running process
|
||||
Process process = this.process;
|
||||
|
|
@ -194,7 +194,6 @@ public class RunProcess {
|
|||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,8 +22,7 @@ import javax.management.MBeanServer;
|
|||
import javax.management.ObjectName;
|
||||
|
||||
/**
|
||||
* This sample app simulates the JMX Mbean that is exposed by the Spring
|
||||
* Boot application.
|
||||
* This sample app simulates the JMX Mbean that is exposed by the Spring Boot application.
|
||||
*/
|
||||
public class SampleApplication {
|
||||
|
||||
|
|
@ -31,7 +30,8 @@ public class SampleApplication {
|
|||
|
||||
public static void main(String[] args) throws Exception {
|
||||
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||
ObjectName name = new ObjectName("org.springframework.boot:type=Lifecycle,name=springApplicationLifecycle");
|
||||
ObjectName name = new ObjectName(
|
||||
"org.springframework.boot:type=Lifecycle,name=springApplicationLifecycle");
|
||||
SpringApplicationLifecycle mbean = new SpringApplicationLifecycle();
|
||||
mbs.registerMBean(mbean, name);
|
||||
|
||||
|
|
@ -41,7 +41,8 @@ public class SampleApplication {
|
|||
int waitAttempts = 0;
|
||||
while (!mbean.shutdownInvoked) {
|
||||
if (waitAttempts > 10) {
|
||||
throw new IllegalStateException("Shutdown should have been invoked by now");
|
||||
throw new IllegalStateException(
|
||||
"Shutdown should have been invoked by now");
|
||||
}
|
||||
synchronized (lock) {
|
||||
lock.wait(250);
|
||||
|
|
@ -50,7 +51,6 @@ public class SampleApplication {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public interface SpringApplicationLifecycleMXBean {
|
||||
|
||||
boolean isReady();
|
||||
|
|
@ -76,5 +76,7 @@ public class SampleApplication {
|
|||
this.shutdownInvoked = true;
|
||||
System.out.println("Shutdown requested");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,7 @@ import javax.management.MBeanServer;
|
|||
import javax.management.ObjectName;
|
||||
|
||||
/**
|
||||
* This sample app simulates the JMX Mbean that is exposed by the Spring
|
||||
* Boot application.
|
||||
* This sample app simulates the JMX Mbean that is exposed by the Spring Boot application.
|
||||
*/
|
||||
public class SampleApplication {
|
||||
|
||||
|
|
@ -30,7 +29,8 @@ public class SampleApplication {
|
|||
|
||||
public static void main(String[] args) throws Exception {
|
||||
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||
ObjectName name = new ObjectName("org.springframework.boot:type=Lifecycle,name=springApplicationLifecycle");
|
||||
ObjectName name = new ObjectName(
|
||||
"org.springframework.boot:type=Lifecycle,name=springApplicationLifecycle");
|
||||
SpringApplicationLifecycle mbean = new SpringApplicationLifecycle();
|
||||
mbs.registerMBean(mbean, name);
|
||||
|
||||
|
|
@ -40,7 +40,8 @@ public class SampleApplication {
|
|||
int waitAttempts = 0;
|
||||
while (!mbean.shutdownInvoked) {
|
||||
if (waitAttempts > 10) {
|
||||
throw new IllegalStateException("Shutdown should have been invoked by now");
|
||||
throw new IllegalStateException(
|
||||
"Shutdown should have been invoked by now");
|
||||
}
|
||||
synchronized (lock) {
|
||||
lock.wait(250);
|
||||
|
|
@ -49,7 +50,6 @@ public class SampleApplication {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public interface SpringApplicationLifecycleMXBean {
|
||||
|
||||
boolean isReady();
|
||||
|
|
@ -75,5 +75,7 @@ public class SampleApplication {
|
|||
this.shutdownInvoked = true;
|
||||
System.out.println("Shutdown requested");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ import org.apache.maven.plugins.annotations.Parameter;
|
|||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.shared.artifact.filter.collection.AbstractArtifactFeatureFilter;
|
||||
import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts;
|
||||
|
||||
import org.springframework.boot.loader.tools.FileUtils;
|
||||
import org.springframework.boot.loader.tools.MainClassFinder;
|
||||
|
||||
|
|
@ -137,8 +136,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
|||
* @return {@code true} if the application process should be forked
|
||||
*/
|
||||
protected boolean isFork() {
|
||||
return (Boolean.TRUE.equals(this.fork)
|
||||
|| (this.fork == null && (hasAgent() || hasJvmArgs())));
|
||||
return (Boolean.TRUE.equals(this.fork) || (this.fork == null && (hasAgent() || hasJvmArgs())));
|
||||
}
|
||||
|
||||
private boolean hasAgent() {
|
||||
|
|
@ -165,7 +163,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
|||
}
|
||||
CodeSource source = loaded.getProtectionDomain().getCodeSource();
|
||||
if (source != null) {
|
||||
this.agent = new File[] {new File(source.getLocation().getFile())};
|
||||
this.agent = new File[] { new File(source.getLocation().getFile()) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -178,7 +176,8 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
|||
}
|
||||
}
|
||||
|
||||
private void run(String startClassName) throws MojoExecutionException, MojoFailureException {
|
||||
private void run(String startClassName) throws MojoExecutionException,
|
||||
MojoFailureException {
|
||||
findAgent();
|
||||
if (isFork()) {
|
||||
doRunWithForkedJvm(startClassName);
|
||||
|
|
@ -196,8 +195,8 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
|||
}
|
||||
}
|
||||
|
||||
private void doRunWithForkedJvm(String startClassName)
|
||||
throws MojoExecutionException, MojoFailureException {
|
||||
private void doRunWithForkedJvm(String startClassName) throws MojoExecutionException,
|
||||
MojoFailureException {
|
||||
List<String> args = new ArrayList<String>();
|
||||
addAgents(args);
|
||||
addJvmArgs(args);
|
||||
|
|
@ -213,8 +212,8 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
|||
* @throws MojoExecutionException
|
||||
* @throws MojoFailureException
|
||||
*/
|
||||
protected abstract void runWithForkedJvm(List<String> args) throws MojoExecutionException, MojoFailureException;
|
||||
|
||||
protected abstract void runWithForkedJvm(List<String> args)
|
||||
throws MojoExecutionException, MojoFailureException;
|
||||
|
||||
/**
|
||||
* Run with the current VM, using the specified arguments.
|
||||
|
|
@ -277,8 +276,8 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
|||
args.add("-cp");
|
||||
args.add(classpath.toString());
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new MojoExecutionException("Could not build classpath", e);
|
||||
catch (Exception ex) {
|
||||
throw new MojoExecutionException("Could not build classpath", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -358,8 +357,8 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
|||
getLog().debug(sb.toString().trim());
|
||||
}
|
||||
|
||||
|
||||
private static class TestArtifactFilter extends AbstractArtifactFeatureFilter {
|
||||
|
||||
public TestArtifactFilter() {
|
||||
super("", Artifact.SCOPE_TEST);
|
||||
}
|
||||
|
|
@ -368,6 +367,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
|||
protected String getArtifactFeature(Artifact artifact) {
|
||||
return artifact.getScope();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -423,7 +423,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
|||
if (!mainMethod.isAccessible()) {
|
||||
mainMethod.setAccessible(true);
|
||||
}
|
||||
mainMethod.invoke(null, new Object[] {this.args});
|
||||
mainMethod.invoke(null, new Object[] { this.args });
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
Exception wrappedEx = new Exception(
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class RunArguments {
|
|||
}
|
||||
|
||||
public LinkedList<String> getArgs() {
|
||||
return args;
|
||||
return this.args;
|
||||
}
|
||||
|
||||
public String[] asArray() {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import org.apache.maven.plugins.annotations.Execute;
|
|||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||
|
||||
import org.springframework.boot.loader.tools.JavaExecutable;
|
||||
import org.springframework.boot.loader.tools.RunProcess;
|
||||
|
||||
|
|
@ -41,15 +40,17 @@ public class RunMojo extends AbstractRunMojo {
|
|||
@Override
|
||||
protected void runWithForkedJvm(List<String> args) throws MojoExecutionException {
|
||||
try {
|
||||
new RunProcess(new JavaExecutable().toString()).run(true, args
|
||||
.toArray(new String[args.size()]));
|
||||
new RunProcess(new JavaExecutable().toString()).run(true,
|
||||
args.toArray(new String[args.size()]));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new MojoExecutionException("Could not exec java", ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected void runWithMavenJvm(String startClassName, String... arguments) throws MojoExecutionException {
|
||||
@Override
|
||||
protected void runWithMavenJvm(String startClassName, String... arguments)
|
||||
throws MojoExecutionException {
|
||||
IsolatedThreadGroup threadGroup = new IsolatedThreadGroup(startClassName);
|
||||
Thread launchThread = new Thread(threadGroup, new LaunchRunner(startClassName,
|
||||
arguments), startClassName + ".main()");
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.boot.maven;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.management.AttributeNotFoundException;
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.MBeanException;
|
||||
|
|
@ -35,20 +36,19 @@ import org.apache.maven.plugin.MojoExecutionException;
|
|||
* information about the lifecycle of a given Spring application.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.3.0
|
||||
*/
|
||||
class SpringApplicationLifecycleClient {
|
||||
|
||||
//Note: see org.springframework.boot.autoconfigure.test.SpringApplicationLifecycleAutoConfiguration
|
||||
static final String DEFAULT_OBJECT_NAME =
|
||||
"org.springframework.boot:type=Lifecycle,name=springApplicationLifecycle";
|
||||
// Note: see SpringApplicationLifecycleAutoConfiguration
|
||||
static final String DEFAULT_OBJECT_NAME = "org.springframework.boot:type=Lifecycle,name=springApplicationLifecycle";
|
||||
|
||||
private final MBeanServerConnection mBeanServerConnection;
|
||||
private final MBeanServerConnection connection;
|
||||
|
||||
private final ObjectName objectName;
|
||||
|
||||
public SpringApplicationLifecycleClient(MBeanServerConnection mBeanServerConnection, String jmxName) {
|
||||
this.mBeanServerConnection = mBeanServerConnection;
|
||||
public SpringApplicationLifecycleClient(MBeanServerConnection connection,
|
||||
String jmxName) {
|
||||
this.connection = connection;
|
||||
this.objectName = toObjectName(jmxName);
|
||||
}
|
||||
|
||||
|
|
@ -66,30 +66,32 @@ class SpringApplicationLifecycleClient {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if the spring application managed by this instance is ready.
|
||||
* <p>Returns {@code false} if the mbean is not yet deployed so this method
|
||||
* should be repeatedly called until a timeout is reached.
|
||||
* Check if the spring application managed by this instance is ready. Returns
|
||||
* {@code false} if the mbean is not yet deployed so this method should be repeatedly
|
||||
* called until a timeout is reached.
|
||||
* @return {@code true} if the application is ready to service requests
|
||||
* @throws MojoExecutionException if the JMX service could not be contacted
|
||||
*/
|
||||
public boolean isReady() throws MojoExecutionException {
|
||||
try {
|
||||
return (Boolean) this.mBeanServerConnection.getAttribute(this.objectName, "Ready");
|
||||
return (Boolean) this.connection.getAttribute(this.objectName, "Ready");
|
||||
}
|
||||
catch (InstanceNotFoundException e) {
|
||||
catch (InstanceNotFoundException ex) {
|
||||
return false; // Instance not available yet
|
||||
}
|
||||
catch (AttributeNotFoundException e) {
|
||||
throw new IllegalStateException("Unexpected: attribute 'Ready' not available", e);
|
||||
catch (AttributeNotFoundException ex) {
|
||||
throw new IllegalStateException(
|
||||
"Unexpected: attribute 'Ready' not available", ex);
|
||||
}
|
||||
catch (ReflectionException e) {
|
||||
throw new MojoExecutionException("Failed to retrieve Ready attribute", e.getCause());
|
||||
catch (ReflectionException ex) {
|
||||
throw new MojoExecutionException("Failed to retrieve Ready attribute",
|
||||
ex.getCause());
|
||||
}
|
||||
catch (MBeanException e) {
|
||||
throw new MojoExecutionException(e.getMessage(), e);
|
||||
catch (MBeanException ex) {
|
||||
throw new MojoExecutionException(ex.getMessage(), ex);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new MojoExecutionException(e.getMessage(), e);
|
||||
catch (IOException ex) {
|
||||
throw new MojoExecutionException(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -99,15 +101,16 @@ class SpringApplicationLifecycleClient {
|
|||
* @throws IOException if an I/O error occurs
|
||||
* @throws InstanceNotFoundException if the lifecycle mbean cannot be found
|
||||
*/
|
||||
public void stop() throws MojoExecutionException, IOException, InstanceNotFoundException {
|
||||
public void stop() throws MojoExecutionException, IOException,
|
||||
InstanceNotFoundException {
|
||||
try {
|
||||
this.mBeanServerConnection.invoke(this.objectName, "shutdown", null, null);
|
||||
this.connection.invoke(this.objectName, "shutdown", null, null);
|
||||
}
|
||||
catch (ReflectionException e) {
|
||||
throw new MojoExecutionException("Shutdown failed", e.getCause());
|
||||
catch (ReflectionException ex) {
|
||||
throw new MojoExecutionException("Shutdown failed", ex.getCause());
|
||||
}
|
||||
catch (MBeanException e) {
|
||||
throw new MojoExecutionException("Could not invoke shutdown operation", e);
|
||||
catch (MBeanException ex) {
|
||||
throw new MojoExecutionException("Could not invoke shutdown operation", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ import java.net.ConnectException;
|
|||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.management.MBeanServerConnection;
|
||||
import javax.management.ReflectionException;
|
||||
import javax.management.remote.JMXConnector;
|
||||
|
|
@ -32,15 +34,14 @@ 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.plugins.annotations.ResolutionScope;
|
||||
|
||||
import org.springframework.boot.loader.tools.JavaExecutable;
|
||||
import org.springframework.boot.loader.tools.RunProcess;
|
||||
|
||||
/**
|
||||
* Start a spring application. Contrary to the {@code run} goal, this does not
|
||||
* block and allows other goal to operate on the application. This goal is typically
|
||||
* used in integration test scenario where the application is started before a test
|
||||
* suite and stopped after.
|
||||
* Start a spring application. Contrary to the {@code run} goal, this does not block and
|
||||
* allows other goal to operate on the application. This goal is typically used in
|
||||
* integration test scenario where the application is started before a test suite and
|
||||
* stopped after.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.3.0
|
||||
|
|
@ -54,30 +55,30 @@ public class StartMojo extends AbstractRunMojo {
|
|||
private static final String JMX_NAME_PROPERTY_PREFIX = "--spring.context.lifecycle.jmx-name=";
|
||||
|
||||
/**
|
||||
* The JMX name of the automatically deployed MBean managing the lifecycle
|
||||
* of the spring application.
|
||||
* The JMX name of the automatically deployed MBean managing the lifecycle of the
|
||||
* spring application.
|
||||
*/
|
||||
@Parameter
|
||||
private String jmxName = SpringApplicationLifecycleClient.DEFAULT_OBJECT_NAME;
|
||||
|
||||
/**
|
||||
* The port to use to expose the platform MBeanServer if the application
|
||||
* needs to be forked.
|
||||
* The port to use to expose the platform MBeanServer if the application needs to be
|
||||
* forked.
|
||||
*/
|
||||
@Parameter
|
||||
private int jmxPort = 9001;
|
||||
|
||||
/**
|
||||
* The number of milli-seconds to wait between each attempt to check if the
|
||||
* spring application is ready.
|
||||
* The number of milli-seconds to wait between each attempt to check if the spring
|
||||
* application is ready.
|
||||
*/
|
||||
@Parameter
|
||||
private long wait = 500;
|
||||
|
||||
/**
|
||||
* The maximum number of attempts to check if the spring application is
|
||||
* ready. Combined with the "wait" argument, this gives a global timeout
|
||||
* value (30 sec by default)
|
||||
* The maximum number of attempts to check if the spring application is ready.
|
||||
* Combined with the "wait" argument, this gives a global timeout value (30 sec by
|
||||
* default)
|
||||
*/
|
||||
@Parameter
|
||||
private int maxAttempts = 60;
|
||||
|
|
@ -85,26 +86,30 @@ public class StartMojo extends AbstractRunMojo {
|
|||
private final Object lock = new Object();
|
||||
|
||||
@Override
|
||||
protected void runWithForkedJvm(List<String> args) throws MojoExecutionException, MojoFailureException {
|
||||
RunProcess runProcess;
|
||||
try {
|
||||
runProcess = new RunProcess(new JavaExecutable().toString());
|
||||
runProcess.run(false, args.toArray(new String[args.size()]));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new MojoExecutionException("Could not exec java", ex);
|
||||
}
|
||||
|
||||
protected void runWithForkedJvm(List<String> args) throws MojoExecutionException,
|
||||
MojoFailureException {
|
||||
RunProcess runProcess = runProcess(args);
|
||||
try {
|
||||
waitForSpringApplication();
|
||||
}
|
||||
catch (MojoExecutionException e) {
|
||||
catch (MojoExecutionException ex) {
|
||||
runProcess.kill();
|
||||
throw e;
|
||||
throw ex;
|
||||
}
|
||||
catch (MojoFailureException e) {
|
||||
catch (MojoFailureException ex) {
|
||||
runProcess.kill();
|
||||
throw e;
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
private RunProcess runProcess(List<String> args) throws MojoExecutionException {
|
||||
try {
|
||||
RunProcess runProcess = new RunProcess(new JavaExecutable().toString());
|
||||
runProcess.run(false, args.toArray(new String[args.size()]));
|
||||
return runProcess;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new MojoExecutionException("Could not exec java", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -113,7 +118,8 @@ public class StartMojo extends AbstractRunMojo {
|
|||
RunArguments applicationArguments = super.resolveApplicationArguments();
|
||||
applicationArguments.getArgs().addLast(ENABLE_MBEAN_PROPERTY);
|
||||
if (isFork()) {
|
||||
applicationArguments.getArgs().addLast(JMX_NAME_PROPERTY_PREFIX + this.jmxName);
|
||||
applicationArguments.getArgs().addLast(
|
||||
JMX_NAME_PROPERTY_PREFIX + this.jmxName);
|
||||
}
|
||||
return applicationArguments;
|
||||
}
|
||||
|
|
@ -124,7 +130,7 @@ public class StartMojo extends AbstractRunMojo {
|
|||
if (isFork()) {
|
||||
List<String> remoteJmxArguments = new ArrayList<String>();
|
||||
remoteJmxArguments.add("-Dcom.sun.management.jmxremote");
|
||||
remoteJmxArguments.add("-Dcom.sun.management.jmxremote.port=" + jmxPort);
|
||||
remoteJmxArguments.add("-Dcom.sun.management.jmxremote.port=" + this.jmxPort);
|
||||
remoteJmxArguments.add("-Dcom.sun.management.jmxremote.authenticate=false");
|
||||
remoteJmxArguments.add("-Dcom.sun.management.jmxremote.ssl=false");
|
||||
jvmArguments.getArgs().addAll(remoteJmxArguments);
|
||||
|
|
@ -132,18 +138,19 @@ public class StartMojo extends AbstractRunMojo {
|
|||
return jvmArguments;
|
||||
}
|
||||
|
||||
|
||||
protected void runWithMavenJvm(String startClassName, String... arguments) throws MojoExecutionException {
|
||||
@Override
|
||||
protected void runWithMavenJvm(String startClassName, String... arguments)
|
||||
throws MojoExecutionException {
|
||||
IsolatedThreadGroup threadGroup = new IsolatedThreadGroup(startClassName);
|
||||
Thread launchThread = new Thread(threadGroup, new LaunchRunner(startClassName,
|
||||
arguments), startClassName + ".main()");
|
||||
launchThread.setContextClassLoader(new URLClassLoader(getClassPathUrls()));
|
||||
launchThread.start();
|
||||
|
||||
waitForSpringApplication(this.wait, this.maxAttempts);
|
||||
}
|
||||
|
||||
private void waitForSpringApplication(long wait, int maxAttempts) throws MojoExecutionException {
|
||||
private void waitForSpringApplication(long wait, int maxAttempts)
|
||||
throws MojoExecutionException {
|
||||
SpringApplicationLifecycleClient helper = new SpringApplicationLifecycleClient(
|
||||
ManagementFactory.getPlatformMBeanServer(), this.jmxName);
|
||||
getLog().debug("Waiting for spring application to start...");
|
||||
|
|
@ -151,21 +158,26 @@ public class StartMojo extends AbstractRunMojo {
|
|||
if (helper.isReady()) {
|
||||
return;
|
||||
}
|
||||
getLog().debug("Spring application is not ready yet, waiting " + wait + "ms (attempt " + (i + 1) + ")");
|
||||
String message = "Spring application is not ready yet, waiting " + wait
|
||||
+ "ms (attempt " + (i + 1) + ")";
|
||||
getLog().debug(message);
|
||||
synchronized (this.lock) {
|
||||
try {
|
||||
this.lock.wait(wait);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
throw new IllegalStateException("Interrupted while waiting for Spring Boot app to start.");
|
||||
catch (InterruptedException ex) {
|
||||
throw new IllegalStateException(
|
||||
"Interrupted while waiting for Spring Boot app to start.");
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new MojoExecutionException("Spring application did not start before the configured " +
|
||||
"timeout (" + (wait * maxAttempts) + "ms");
|
||||
throw new MojoExecutionException(
|
||||
"Spring application did not start before the configured timeout ("
|
||||
+ (wait * maxAttempts) + "ms");
|
||||
}
|
||||
|
||||
private void waitForSpringApplication() throws MojoFailureException, MojoExecutionException {
|
||||
private void waitForSpringApplication() throws MojoFailureException,
|
||||
MojoExecutionException {
|
||||
try {
|
||||
if (Boolean.TRUE.equals(isFork())) {
|
||||
waitForForkedSpringApplication();
|
||||
|
|
@ -174,114 +186,133 @@ public class StartMojo extends AbstractRunMojo {
|
|||
doWaitForSpringApplication(ManagementFactory.getPlatformMBeanServer());
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new MojoFailureException("Could not contact Spring Boot application", e);
|
||||
catch (IOException ex) {
|
||||
throw new MojoFailureException("Could not contact Spring Boot application",
|
||||
ex);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new MojoExecutionException("Could not figure out if the application has started", e);
|
||||
catch (Exception ex) {
|
||||
throw new MojoExecutionException(
|
||||
"Could not figure out if the application has started", ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void waitForForkedSpringApplication() throws IOException, MojoFailureException, MojoExecutionException {
|
||||
final JMXConnector jmxConnector;
|
||||
private void waitForForkedSpringApplication() throws IOException,
|
||||
MojoFailureException, MojoExecutionException {
|
||||
try {
|
||||
getLog().debug("Connecting to local MBeanServer at port " + this.jmxPort);
|
||||
jmxConnector = execute(wait, maxAttempts, new RetryCallback<JMXConnector>() {
|
||||
@Override
|
||||
public JMXConnector retry() throws Exception {
|
||||
try {
|
||||
return SpringApplicationLifecycleClient.createLocalJmxConnector(jmxPort);
|
||||
}
|
||||
catch (IOException e) {
|
||||
if (hasCauseWithType(e, ConnectException.class)) { // Not there yet
|
||||
getLog().debug("MBean server at port " + jmxPort + " is not up yet...");
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (jmxConnector == null) {
|
||||
throw new MojoExecutionException("JMX MBean server was not reachable before the configured " +
|
||||
"timeout (" + (this.wait * this.maxAttempts) + "ms");
|
||||
JMXConnector connector = execute(this.wait, this.maxAttempts,
|
||||
new CreateJmxConnector(this.jmxPort));
|
||||
if (connector == null) {
|
||||
throw new MojoExecutionException(
|
||||
"JMX MBean server was not reachable before the configured "
|
||||
+ "timeout (" + (this.wait * this.maxAttempts) + "ms");
|
||||
}
|
||||
getLog().debug("Connected to local MBeanServer at port " + this.jmxPort);
|
||||
try {
|
||||
MBeanServerConnection mBeanServerConnection = jmxConnector.getMBeanServerConnection();
|
||||
doWaitForSpringApplication(mBeanServerConnection);
|
||||
MBeanServerConnection connection = connector.getMBeanServerConnection();
|
||||
doWaitForSpringApplication(connection);
|
||||
}
|
||||
finally {
|
||||
jmxConnector.close();
|
||||
connector.close();
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw e;
|
||||
catch (IOException ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new MojoExecutionException("Failed to connect to MBean server at port " + this.jmxPort, e);
|
||||
catch (Exception ex) {
|
||||
throw new MojoExecutionException("Failed to connect to MBean server at port "
|
||||
+ this.jmxPort, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void doWaitForSpringApplication(MBeanServerConnection connection)
|
||||
throws IOException, MojoExecutionException, MojoFailureException {
|
||||
|
||||
final SpringApplicationLifecycleClient client =
|
||||
new SpringApplicationLifecycleClient(connection, this.jmxName);
|
||||
final SpringApplicationLifecycleClient client = new SpringApplicationLifecycleClient(
|
||||
connection, this.jmxName);
|
||||
try {
|
||||
execute(this.wait, this.maxAttempts, new RetryCallback<Boolean>() {
|
||||
execute(this.wait, this.maxAttempts, new Callable<Boolean>() {
|
||||
|
||||
@Override
|
||||
public Boolean retry() throws Exception {
|
||||
boolean ready = client.isReady();
|
||||
// Wait until the app is ready
|
||||
return (ready ? true : null);
|
||||
public Boolean call() throws Exception {
|
||||
return (client.isReady() ? true : null);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
catch (ReflectionException e) {
|
||||
throw new MojoExecutionException("Unable to retrieve Ready attribute", e.getCause());
|
||||
catch (ReflectionException ex) {
|
||||
throw new MojoExecutionException("Unable to retrieve 'ready' attribute",
|
||||
ex.getCause());
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new MojoFailureException("Could not invoke shutdown operation", e);
|
||||
catch (Exception ex) {
|
||||
throw new MojoFailureException("Could not invoke shutdown operation", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T execute(long wait, int maxAttempts, RetryCallback<T> callback) throws Exception {
|
||||
/**
|
||||
* Execute a task, retrying it on failure.
|
||||
* @param wait the wait time
|
||||
* @param maxAttempts the maximum number of attempts
|
||||
* @param callback the task to execute (possibly multiple times). The callback should
|
||||
* return {@code null} to indicate that another attempt should be made
|
||||
* @return the result
|
||||
* @throws Exception
|
||||
*/
|
||||
public <T> T execute(long wait, int maxAttempts, Callable<T> callback)
|
||||
throws Exception {
|
||||
getLog().debug("Waiting for spring application to start...");
|
||||
for (int i = 0; i < maxAttempts; i++) {
|
||||
T result = callback.retry();
|
||||
T result = callback.call();
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
getLog().debug("Spring application is not ready yet, waiting " + wait + "ms (attempt " + (i + 1) + ")");
|
||||
String message = "Spring application is not ready yet, waiting " + wait
|
||||
+ "ms (attempt " + (i + 1) + ")";
|
||||
getLog().debug(message);
|
||||
synchronized (this.lock) {
|
||||
try {
|
||||
this.lock.wait(wait);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
throw new IllegalStateException("Interrupted while waiting for Spring Boot app to start.");
|
||||
catch (InterruptedException ex) {
|
||||
throw new IllegalStateException(
|
||||
"Interrupted while waiting for Spring Boot app to start.");
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new MojoExecutionException("Spring application did not start before the configured " +
|
||||
"timeout (" + (wait * maxAttempts) + "ms");
|
||||
throw new MojoExecutionException(
|
||||
"Spring application did not start before the configured " + "timeout ("
|
||||
+ (wait * maxAttempts) + "ms");
|
||||
}
|
||||
|
||||
private static boolean hasCauseWithType(Throwable t, Class<? extends Exception> type) {
|
||||
return type.isAssignableFrom(t.getClass()) || t.getCause() != null && hasCauseWithType(t.getCause(), type);
|
||||
}
|
||||
private class CreateJmxConnector implements Callable<JMXConnector> {
|
||||
|
||||
private final int port;
|
||||
|
||||
interface RetryCallback<T> {
|
||||
public CreateJmxConnector(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JMXConnector call() throws Exception {
|
||||
try {
|
||||
return SpringApplicationLifecycleClient
|
||||
.createLocalJmxConnector(this.port);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
if (hasCauseWithType(ex, ConnectException.class)) {
|
||||
String message = "MBean server at port " + this.port
|
||||
+ " is not up yet...";
|
||||
getLog().debug(message);
|
||||
return null;
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasCauseWithType(Throwable t, Class<? extends Exception> type) {
|
||||
return type.isAssignableFrom(t.getClass()) || t.getCause() != null
|
||||
&& hasCauseWithType(t.getCause(), type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to execute an operation. Throws an exception in case of fatal
|
||||
* exception, returns {@code null} to indicate another attempt should be
|
||||
* made if possible.
|
||||
*/
|
||||
T retry() throws Exception;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package org.springframework.boot.maven;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.lang.management.ManagementFactory;
|
||||
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.MBeanServerConnection;
|
||||
import javax.management.remote.JMXConnector;
|
||||
|
|
@ -40,23 +41,23 @@ 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
|
||||
* 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
|
||||
*/
|
||||
@Parameter(property = "fork")
|
||||
private Boolean fork;
|
||||
|
||||
/**
|
||||
* The JMX name of the automatically deployed MBean managing the lifecycle
|
||||
* of the application.
|
||||
* The JMX name of the automatically deployed MBean managing the lifecycle of the
|
||||
* application.
|
||||
*/
|
||||
@Parameter
|
||||
private String jmxName = SpringApplicationLifecycleClient.DEFAULT_OBJECT_NAME;
|
||||
|
||||
/**
|
||||
* The port to use to lookup the platform MBeanServer if the application
|
||||
* has been forked.
|
||||
* The port to use to lookup the platform MBeanServer if the application has been
|
||||
* forked.
|
||||
*/
|
||||
@Parameter
|
||||
private int jmxPort = 9001;
|
||||
|
|
@ -72,9 +73,22 @@ public class StopMojo extends AbstractMojo {
|
|||
stop();
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
catch (IOException ex) {
|
||||
// The response won't be received as the server has died - ignoring
|
||||
getLog().debug("Service is not reachable anymore (" + e.getMessage() + ")");
|
||||
getLog().debug("Service is not reachable anymore (" + ex.getMessage() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
private void stopForkedProcess() throws IOException, MojoFailureException,
|
||||
MojoExecutionException {
|
||||
JMXConnector connector = SpringApplicationLifecycleClient
|
||||
.createLocalJmxConnector(this.jmxPort);
|
||||
try {
|
||||
MBeanServerConnection connection = connector.getMBeanServerConnection();
|
||||
doStop(connection);
|
||||
}
|
||||
finally {
|
||||
connector.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -82,26 +96,15 @@ public class StopMojo extends AbstractMojo {
|
|||
doStop(ManagementFactory.getPlatformMBeanServer());
|
||||
}
|
||||
|
||||
private void stopForkedProcess() throws IOException, MojoFailureException, MojoExecutionException {
|
||||
JMXConnector jmxConnector = SpringApplicationLifecycleClient.createLocalJmxConnector(this.jmxPort);
|
||||
private void doStop(MBeanServerConnection connection) throws IOException,
|
||||
MojoExecutionException {
|
||||
try {
|
||||
MBeanServerConnection mBeanServerConnection = jmxConnector.getMBeanServerConnection();
|
||||
doStop(mBeanServerConnection);
|
||||
new SpringApplicationLifecycleClient(connection, this.jmxName).stop();
|
||||
}
|
||||
finally {
|
||||
jmxConnector.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void doStop(MBeanServerConnection connection)
|
||||
throws IOException, MojoExecutionException {
|
||||
SpringApplicationLifecycleClient helper = new SpringApplicationLifecycleClient(connection, this.jmxName);
|
||||
try {
|
||||
helper.stop();
|
||||
}
|
||||
catch (InstanceNotFoundException e) {
|
||||
throw new MojoExecutionException("Spring application lifecycle JMX bean not found (fork is " +
|
||||
"" + this.fork + "). Could not stop application gracefully", e);
|
||||
catch (InstanceNotFoundException ex) {
|
||||
throw new MojoExecutionException(
|
||||
"Spring application lifecycle JMX bean not found (fork is " + ""
|
||||
+ this.fork + "). Could not stop application gracefully", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,13 +17,13 @@
|
|||
package org.springframework.boot.context;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
|
@ -52,50 +52,51 @@ public class SpringApplicationLifecycleRegistrar implements ApplicationContextAw
|
|||
|
||||
private boolean ready = false;
|
||||
|
||||
public SpringApplicationLifecycleRegistrar(String name) throws MalformedObjectNameException {
|
||||
public SpringApplicationLifecycleRegistrar(String name)
|
||||
throws MalformedObjectNameException {
|
||||
this.objectName = new ObjectName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
Assert.isTrue(applicationContext instanceof ConfigurableApplicationContext,
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
Assert.state(applicationContext instanceof ConfigurableApplicationContext,
|
||||
"ApplicationContext does not implement ConfigurableApplicationContext");
|
||||
this.applicationContext = (ConfigurableApplicationContext) applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationReadyEvent event) {
|
||||
ready = true;
|
||||
this.ready = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
|
||||
server.registerMBean(new SpringApplicationLifecycle(), objectName);
|
||||
server.registerMBean(new SpringApplicationLifecycle(), this.objectName);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Application lifecycle MBean registered with name '" + objectName + "'");
|
||||
logger.debug("Application lifecycle MBean registered with name '"
|
||||
+ this.objectName + "'");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
ManagementFactory.getPlatformMBeanServer().unregisterMBean(objectName);
|
||||
ManagementFactory.getPlatformMBeanServer().unregisterMBean(this.objectName);
|
||||
}
|
||||
|
||||
|
||||
private class SpringApplicationLifecycle implements SpringApplicationLifecycleMXBean {
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return ready;
|
||||
return SpringApplicationLifecycleRegistrar.this.ready;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
logger.info("Application shutdown requested.");
|
||||
applicationContext.close();
|
||||
SpringApplicationLifecycleRegistrar.this.applicationContext.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.boot.context;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
|
|
@ -27,7 +28,6 @@ import org.junit.Before;
|
|||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
|
@ -75,15 +75,18 @@ public class SpringApplicationLifecycleRegistrarTests {
|
|||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
try {
|
||||
assertFalse("Application should not be ready yet", isCurrentApplicationReady(objectName));
|
||||
assertFalse("Application should not be ready yet",
|
||||
isCurrentApplicationReady(objectName));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException("Could not contact spring application lifecycle bean", e);
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException(
|
||||
"Could not contact spring application lifecycle bean", ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.context = application.run();
|
||||
assertTrue("application should be ready now", isCurrentApplicationReady(objectName));
|
||||
assertTrue("application should be ready now",
|
||||
isCurrentApplicationReady(objectName));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -95,8 +98,7 @@ public class SpringApplicationLifecycleRegistrarTests {
|
|||
assertTrue("application should be running", this.context.isRunning());
|
||||
invokeShutdown(objectName);
|
||||
assertFalse("application should not be running", this.context.isRunning());
|
||||
|
||||
thrown.expect(InstanceNotFoundException.class); // JMX cleanup
|
||||
this.thrown.expect(InstanceNotFoundException.class); // JMX cleanup
|
||||
this.mBeanServer.getObjectInstance(objectName);
|
||||
}
|
||||
|
||||
|
|
@ -127,16 +129,15 @@ public class SpringApplicationLifecycleRegistrarTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
public SpringApplicationLifecycleRegistrar springApplicationLifecycle()
|
||||
throws MalformedObjectNameException {
|
||||
|
||||
return new SpringApplicationLifecycleRegistrar(OBJECT_NAME);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue