forked from spring-projects/spring-boot
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add start/stop goals to maven plugin
SpringApplicationLifecycle provides basic lifecycle operations on the current Spring Boot application (that is checking if the application has fully started and gracefully terminate the app). It can be registered as an MBean of the platform MBean server if a specific property is set. The Maven plugin uses that MBean to check that the application is ready before ending the "start" phase. It uses it to trigger a proper shutdown of the application during the "stop" phase. If the process has to be forked, the platform MBean server is exposed on a configurable port so that the maven plugin can connect to it. Such change permits the maven plugin to integrate a classical integration test scenario where the "start" goal is invoked during the pre-integration phase and the "stop" goal during the post-integration phase. Closes spring-projectsgh-2525
- Loading branch information
Showing
26 changed files
with
1,893 additions
and
382 deletions.
There are no files selected for viewing
72 changes: 72 additions & 0 deletions
72
...ringframework/boot/autoconfigure/context/SpringApplicationLifecycleAutoConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* | ||
* Copyright 2012-2015 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.springframework.boot.autoconfigure.context; | ||
|
||
import javax.management.MalformedObjectNameException; | ||
|
||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.autoconfigure.AutoConfigureAfter; | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration; | ||
import org.springframework.boot.context.SpringApplicationLifecycleMXBean; | ||
import org.springframework.boot.context.SpringApplicationLifecycleRegistrar; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.core.env.Environment; | ||
import org.springframework.jmx.export.MBeanExporter; | ||
|
||
/** | ||
* Register a JMX component that allows to manage the lifecycle of the current | ||
* application. Intended for internal use only. | ||
* | ||
* @author Stephane Nicoll | ||
* @since 1.3.0 | ||
* @see SpringApplicationLifecycleMXBean | ||
*/ | ||
@Configuration | ||
@AutoConfigureAfter(JmxAutoConfiguration.class) | ||
@ConditionalOnProperty(value = "spring.context.lifecycle.enabled", havingValue = "true", matchIfMissing = false) | ||
class SpringApplicationLifecycleAutoConfiguration { | ||
|
||
/** | ||
* 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"; | ||
|
||
/** | ||
* The default {@code ObjectName} of the application lifecycle mbean. | ||
*/ | ||
static final String DEFAULT_JMX_NAME = "org.springframework.boot:type=Lifecycle,name=springApplicationLifecycle"; | ||
|
||
@Autowired(required = false) | ||
private MBeanExporter mbeanExporter; | ||
|
||
@Autowired | ||
private Environment environment; | ||
|
||
@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); | ||
} | ||
return new SpringApplicationLifecycleRegistrar(jmxName); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
128 changes: 128 additions & 0 deletions
128
...ramework/boot/autoconfigure/context/SpringApplicationLifecycleAutoConfigurationTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
/* | ||
* Copyright 2012-2015 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.springframework.boot.autoconfigure.context; | ||
|
||
import java.lang.management.ManagementFactory; | ||
import javax.management.InstanceNotFoundException; | ||
import javax.management.MBeanServer; | ||
import javax.management.MalformedObjectNameException; | ||
import javax.management.ObjectInstance; | ||
import javax.management.ObjectName; | ||
|
||
import org.junit.After; | ||
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; | ||
|
||
import static org.junit.Assert.assertNotNull; | ||
import static org.junit.Assert.fail; | ||
|
||
/** | ||
* Tests for {@link SpringApplicationLifecycleAutoConfiguration}. | ||
* | ||
* @author Stephane Nicoll | ||
*/ | ||
public class SpringApplicationLifecycleAutoConfigurationTests { | ||
|
||
public static final String ENABLE_LIFECYCLE_PROP = "spring.context.lifecycle.enabled=true"; | ||
|
||
@Rule | ||
public final ExpectedException thrown = ExpectedException.none(); | ||
|
||
private AnnotationConfigApplicationContext context; | ||
|
||
private MBeanServer mBeanServer; | ||
|
||
@Before | ||
public void setup() throws MalformedObjectNameException { | ||
this.mBeanServer = ManagementFactory.getPlatformMBeanServer(); | ||
} | ||
|
||
@After | ||
public void tearDown() { | ||
if (this.context != null) { | ||
this.context.close(); | ||
} | ||
} | ||
|
||
@Test | ||
public void notRegisteredByDefault() throws MalformedObjectNameException, InstanceNotFoundException { | ||
load(); | ||
|
||
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); | ||
} | ||
|
||
@Test | ||
public void registerWithCustomJmxName() throws InstanceNotFoundException { | ||
String customJmxName = "org.acme:name=FooBar"; | ||
System.setProperty(SpringApplicationLifecycleAutoConfiguration.JMX_NAME_PROPERTY, customJmxName); | ||
try { | ||
load(ENABLE_LIFECYCLE_PROP); | ||
|
||
try { | ||
this.mBeanServer.getObjectInstance(createObjectName(customJmxName)); | ||
} | ||
catch (InstanceNotFoundException e) { | ||
fail("lifecycle MBean should have been exposed with custom name"); | ||
} | ||
|
||
thrown.expect(InstanceNotFoundException.class); // Should not be exposed | ||
this.mBeanServer.getObjectInstance(createDefaultObjectName()); | ||
} | ||
finally { | ||
System.clearProperty(SpringApplicationLifecycleAutoConfiguration.JMX_NAME_PROPERTY); | ||
} | ||
} | ||
|
||
private ObjectName createDefaultObjectName() { | ||
return createObjectName(SpringApplicationLifecycleAutoConfiguration.DEFAULT_JMX_NAME); | ||
} | ||
|
||
private ObjectName createObjectName(String jmxName) { | ||
try { | ||
return new ObjectName(jmxName); | ||
} | ||
catch (MalformedObjectNameException e) { | ||
throw new IllegalStateException("Invalid jmx name " + jmxName, e); | ||
} | ||
} | ||
|
||
private void load(String... environment) { | ||
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); | ||
EnvironmentTestUtils.addEnvironment(applicationContext, environment); | ||
applicationContext.register(JmxAutoConfiguration.class, SpringApplicationLifecycleAutoConfiguration.class); | ||
applicationContext.refresh(); | ||
this.context = applicationContext; | ||
} | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-fork/invoker.properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
invoker.goals=clean verify |
37 changes: 37 additions & 0 deletions
37
spring-boot-tools/spring-boot-maven-plugin/src/it/start-stop-fork/pom.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<groupId>org.springframework.boot.maven.it</groupId> | ||
<artifactId>start-stop-fork</artifactId> | ||
<version>0.0.1.BUILD-SNAPSHOT</version> | ||
<properties> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
</properties> | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>@project.groupId@</groupId> | ||
<artifactId>@project.artifactId@</artifactId> | ||
<version>@project.version@</version> | ||
<executions> | ||
<execution> | ||
<id>pre-integration-test</id> | ||
<goals> | ||
<goal>start</goal> | ||
</goals> | ||
</execution> | ||
<execution> | ||
<id>post-integration-test</id> | ||
<goals> | ||
<goal>stop</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
<configuration> | ||
<fork>true</fork> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
Oops, something went wrong.