Add Spring Integration to shutdown

This commit is contained in:
Dave Syer
2014-06-27 08:33:55 +01:00
parent c3c2f0b43f
commit 21e9fc2961
4 changed files with 90 additions and 12 deletions

View File

@@ -41,6 +41,11 @@
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jmx</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>

View File

@@ -26,6 +26,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationBeanFactoryMetaData;
@@ -35,6 +36,7 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.integration.monitor.IntegrationMBeanExporter;
import org.springframework.platform.bootstrap.config.ConfigServiceBootstrapConfiguration;
import org.springframework.platform.config.client.RefreshEndpoint;
import org.springframework.platform.context.environment.EnvironmentManager;
@@ -83,10 +85,31 @@ public class RefreshAutoConfiguration {
@ConditionalOnClass(Endpoint.class)
protected static class RefreshEndpointsConfiguration {
@Bean
@ConditionalOnMissingBean
public RestartEndpoint restartEndpoint() {
return new RestartEndpoint();
@ConditionalOnClass(IntegrationMBeanExporter.class)
protected static class RefreshEndpointWithIntegration {
@Autowired
private IntegrationMBeanExporter exporter;
@Bean
@ConditionalOnMissingBean
public RestartEndpoint restartEndpoint() {
RestartEndpoint endpoint = new RestartEndpoint();
if (exporter!=null) {
endpoint.setIntegrationMBeanExporter(exporter);
}
return endpoint;
}
}
@ConditionalOnMissingClass(name="org.springframework.integration.monitor.IntegrationMBeanExporter")
protected static class RefreshEndpointWithoutIntegration {
@Bean
@ConditionalOnMissingBean
public RestartEndpoint restartEndpoint() {
return new RestartEndpoint();
}
}
@Bean
@@ -94,13 +117,13 @@ public class RefreshAutoConfiguration {
public Endpoint<Boolean> pauseEndpoint(RestartEndpoint restartEndpoint) {
return restartEndpoint.getPauseEndpoint();
}
@Bean
@ConfigurationProperties("endpoints.resume")
public Endpoint<Boolean> resumeEndpoint(RestartEndpoint restartEndpoint) {
return restartEndpoint.getResumeEndpoint();
}
@Configuration
@ConditionalOnExpression("${endpoints.refresh.enabled:true}")
@ConditionalOnBean(ConfigServiceBootstrapConfiguration.class)

View File

@@ -24,6 +24,8 @@ import java.util.Map;
import java.util.Set;
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
import org.springframework.boot.context.config.ConfigFileApplicationListener;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.CompositePropertySource;
@@ -58,6 +60,7 @@ public class RefreshEndpoint extends AbstractEndpoint<Collection<String>> {
public synchronized String[] refresh() {
Map<String, Object> before = extract(context.getEnvironment().getPropertySources());
bootstrap.initialize(context);
new ConfigFileApplicationListener().onApplicationEvent(new ApplicationEnvironmentPreparedEvent(null, null, context.getEnvironment()));
Set<String> keys = changes(before,
extract(context.getEnvironment().getPropertySources())).keySet();
if (keys.isEmpty()) {

View File

@@ -26,6 +26,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.integration.monitor.IntegrationMBeanExporter;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
@@ -59,6 +60,36 @@ public class RestartEndpoint extends AbstractEndpoint<Boolean> implements
private ApplicationPreparedEvent event;
private IntegrationShutdown integrationShutdown;
private boolean forceShutdown;
private long timeout;
@ManagedAttribute
public boolean isForceShutdown() {
return forceShutdown;
}
public void setForceShutdown(boolean forceShutdown) {
this.forceShutdown = forceShutdown;
}
@ManagedAttribute
public long getTimeout() {
return timeout;
}
public void setTimeout(long timeout) {
this.timeout = timeout;
}
public void setIntegrationMBeanExporter(IntegrationMBeanExporter exporter) {
if (exporter != null) {
this.integrationShutdown = new IntegrationShutdown(exporter);
}
}
@Override
public void onApplicationEvent(ApplicationPreparedEvent input) {
event = (ApplicationPreparedEvent) input;
@@ -84,17 +115,17 @@ public class RestartEndpoint extends AbstractEndpoint<Boolean> implements
return false;
}
}
public Endpoint<Boolean> getPauseEndpoint() {
return new PauseEndpoint();
}
public Endpoint<Boolean> getResumeEndpoint() {
return new ResumeEndpoint();
}
private class PauseEndpoint extends AbstractEndpoint<Boolean> {
public PauseEndpoint() {
super("pause", true, true);
}
@@ -110,7 +141,7 @@ public class RestartEndpoint extends AbstractEndpoint<Boolean> implements
}
private class ResumeEndpoint extends AbstractEndpoint<Boolean> {
public ResumeEndpoint() {
super("resume", true, true);
}
@@ -128,6 +159,9 @@ public class RestartEndpoint extends AbstractEndpoint<Boolean> implements
@ManagedOperation
public synchronized ConfigurableApplicationContext restart() {
if (context != null) {
if (integrationShutdown != null) {
integrationShutdown.stop(forceShutdown, timeout);
}
context.close();
// If running in a webapp then the context classloader is probably going to
// die so we need to revert to a safe place before starting again
@@ -136,7 +170,7 @@ public class RestartEndpoint extends AbstractEndpoint<Boolean> implements
}
return context;
}
@ManagedAttribute
public boolean isRunning() {
if (context != null) {
@@ -163,4 +197,17 @@ public class RestartEndpoint extends AbstractEndpoint<Boolean> implements
ClassUtils.overrideThreadContextClassLoader(application.getClass().getClassLoader());
}
private class IntegrationShutdown {
private IntegrationMBeanExporter exporter;
public IntegrationShutdown(IntegrationMBeanExporter exporter) {
this.exporter = exporter;
}
public void stop(boolean force, long timeout) {
exporter.stopActiveComponents(force, timeout);
}
}
}