Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
bce4bb88
Commit
bce4bb88
authored
Jun 04, 2015
by
Phillip Webb
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Polish start stop support
parent
09a29a72
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
274 additions
and
232 deletions
+274
-232
SpringApplicationLifecycleAutoConfiguration.java
.../context/SpringApplicationLifecycleAutoConfiguration.java
+6
-5
SpringApplicationLifecycleAutoConfigurationTests.java
...ext/SpringApplicationLifecycleAutoConfigurationTests.java
+12
-14
RunProcess.java
...ava/org/springframework/boot/loader/tools/RunProcess.java
+8
-9
SampleApplication.java
...t-stop-fork/src/main/java/org/test/SampleApplication.java
+8
-6
SampleApplication.java
.../start-stop/src/main/java/org/test/SampleApplication.java
+8
-6
AbstractRunMojo.java
.../java/org/springframework/boot/maven/AbstractRunMojo.java
+13
-13
RunArguments.java
...ain/java/org/springframework/boot/maven/RunArguments.java
+1
-1
RunMojo.java
...src/main/java/org/springframework/boot/maven/RunMojo.java
+5
-4
SpringApplicationLifecycleClient.java
...ramework/boot/maven/SpringApplicationLifecycleClient.java
+29
-26
StartMojo.java
...c/main/java/org/springframework/boot/maven/StartMojo.java
+134
-103
StopMojo.java
...rc/main/java/org/springframework/boot/maven/StopMojo.java
+27
-24
SpringApplicationLifecycleRegistrar.java
...ork/boot/context/SpringApplicationLifecycleRegistrar.java
+13
-12
SpringApplicationLifecycleRegistrarTests.java
...oot/context/SpringApplicationLifecycleRegistrarTests.java
+10
-9
No files found.
spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/SpringApplicationLifecycleAutoConfiguration.java
View file @
bce4bb88
...
...
@@ -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
);
}
...
...
spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/SpringApplicationLifecycleAutoConfigurationTests.java
View file @
bce4bb88
...
...
@@ -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
e
x
)
{
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
e
x
)
{
throw
new
IllegalStateException
(
"Invalid jmx name "
+
jmxName
,
e
x
);
}
}
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
;
}
}
spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/RunProcess.java
View file @
bce4bb88
...
...
@@ -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
e
x
)
{
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
;
}
...
...
spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-fork/src/main/java/org/test/SampleApplication.java
View file @
bce4bb88
...
...
@@ -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"
);
}
}
}
spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop/src/main/java/org/test/SampleApplication.java
View file @
bce4bb88
...
...
@@ -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"
);
}
}
}
spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java
View file @
bce4bb88
...
...
@@ -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
e
x
)
{
throw
new
MojoExecutionException
(
"Could not build classpath"
,
e
x
);
}
}
...
...
@@ -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
(
...
...
spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunArguments.java
View file @
bce4bb88
...
...
@@ -42,7 +42,7 @@ class RunArguments {
}
public
LinkedList
<
String
>
getArgs
()
{
return
args
;
return
this
.
args
;
}
public
String
[]
asArray
()
{
...
...
spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunMojo.java
View file @
bce4bb88
...
...
@@ -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()"
);
...
...
spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/SpringApplicationLifecycleClient.java
View file @
bce4bb88
...
...
@@ -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
mBeanServerC
onnection
;
private
final
MBeanServerConnection
c
onnection
;
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
.
mBeanServerC
onnection
.
getAttribute
(
this
.
objectName
,
"Ready"
);
return
(
Boolean
)
this
.
c
onnection
.
getAttribute
(
this
.
objectName
,
"Ready"
);
}
catch
(
InstanceNotFoundException
e
)
{
catch
(
InstanceNotFoundException
e
x
)
{
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
e
x
)
{
throw
new
MojoExecutionException
(
e
x
.
getMessage
(),
ex
);
}
catch
(
IOException
e
)
{
throw
new
MojoExecutionException
(
e
.
getMessage
(),
e
);
catch
(
IOException
e
x
)
{
throw
new
MojoExecutionException
(
e
x
.
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
.
mBeanServerC
onnection
.
invoke
(
this
.
objectName
,
"shutdown"
,
null
,
null
);
this
.
c
onnection
.
invoke
(
this
.
objectName
,
"shutdown"
,
null
,
null
);
}
catch
(
ReflectionException
e
)
{
throw
new
MojoExecutionException
(
"Shutdown failed"
,
e
.
getCause
());
catch
(
ReflectionException
e
x
)
{
throw
new
MojoExecutionException
(
"Shutdown failed"
,
e
x
.
getCause
());
}
catch
(
MBeanException
e
)
{
throw
new
MojoExecutionException
(
"Could not invoke shutdown operation"
,
e
);
catch
(
MBeanException
e
x
)
{
throw
new
MojoExecutionException
(
"Could not invoke shutdown operation"
,
e
x
);
}
}
...
...
spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java
View file @
bce4bb88
...
...
@@ -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
* s
uite and s
topped 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
e
x
)
{
runProcess
.
kill
();
throw
e
;
throw
e
x
;
}
catch
(
MojoFailureException
e
)
{
catch
(
MojoFailureException
e
x
)
{
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
=
jmxC
onnector
.
getMBeanServerConnection
();
doWaitForSpringApplication
(
mBeanServerC
onnection
);
MBeanServerConnection
connection
=
c
onnector
.
getMBeanServerConnection
();
doWaitForSpringApplication
(
c
onnection
);
}
finally
{
jmxC
onnector
.
close
();
c
onnector
.
close
();
}
}
catch
(
IOException
e
)
{
throw
e
;
catch
(
IOException
e
x
)
{
throw
e
x
;
}
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
e
x
)
{
throw
new
MojoFailureException
(
"Could not invoke shutdown operation"
,
e
x
);
}
}
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
;
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
;
}
}
interface
RetryCallback
<
T
>
{
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
;
}
}
spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StopMojo.java
View file @
bce4bb88
...
...
@@ -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,36 +73,38 @@ public class StopMojo extends AbstractMojo {
stop
();
}
}
catch
(
IOException
e
)
{
catch
(
IOException
e
x
)
{
// 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
stop
()
throws
IOException
,
MojoFailureException
,
MojoExecutionException
{
doStop
(
ManagementFactory
.
getPlatformMBeanServer
());
}
private
void
stopForkedProcess
()
throws
IOException
,
MojoFailureException
,
MojoExecutionException
{
JMXConnector
jmxConnector
=
SpringApplicationLifecycleClient
.
createLocalJmxConnector
(
this
.
jmxPort
);
private
void
stopForkedProcess
()
throws
IOException
,
MojoFailureException
,
MojoExecutionException
{
JMXConnector
connector
=
SpringApplicationLifecycleClient
.
createLocalJmxConnector
(
this
.
jmxPort
);
try
{
MBeanServerConnection
mBeanServerConnection
=
jmxC
onnector
.
getMBeanServerConnection
();
doStop
(
mBeanServerC
onnection
);
MBeanServerConnection
connection
=
c
onnector
.
getMBeanServerConnection
();
doStop
(
c
onnection
);
}
finally
{
jmxC
onnector
.
close
();
c
onnector
.
close
();
}
}
private
void
doStop
(
MBeanServerConnection
connection
)
throws
IOException
,
MojoExecutionException
{
SpringApplicationLifecycleClient
helper
=
new
SpringApplicationLifecycleClient
(
connection
,
this
.
jmxName
);
private
void
stop
()
throws
IOException
,
MojoFailureException
,
MojoExecutionException
{
doStop
(
ManagementFactory
.
getPlatformMBeanServer
());
}
private
void
doStop
(
MBeanServerConnection
connection
)
throws
IOException
,
MojoExecutionException
{
try
{
helper
.
stop
();
new
SpringApplicationLifecycleClient
(
connection
,
this
.
jmxName
)
.
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
);
}
}
...
...
spring-boot/src/main/java/org/springframework/boot/context/SpringApplicationLifecycleRegistrar.java
View file @
bce4bb88
...
...
@@ -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
();
}
}
}
spring-boot/src/test/java/org/springframework/boot/context/SpringApplicationLifecycleRegistrarTests.java
View file @
bce4bb88
...
...
@@ -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
);
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment