Isolate refresh/resume/pause/restart endpoints
This commit is contained in:
@@ -20,6 +20,7 @@ package org.springframework.platform.autoconfigure;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
@@ -28,6 +29,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.ConfigurationBeanFactoryMetaData;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -83,10 +85,22 @@ public class RefreshAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public RestartEndpoint restartContextListener() {
|
||||
public RestartEndpoint restartEndpoint() {
|
||||
return new RestartEndpoint();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties("endpoints.pause")
|
||||
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)
|
||||
@@ -124,6 +138,16 @@ public class RefreshAutoConfiguration {
|
||||
return new RestartMvcEndpoint(restartEndpoint);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MvcEndpoint pauseMvcEndpoint(RestartMvcEndpoint restartEndpoint) {
|
||||
return restartEndpoint.getPauseEndpoint();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MvcEndpoint resumeMvcEndpoint(RestartMvcEndpoint restartEndpoint) {
|
||||
return restartEndpoint.getResumeEndpoint();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.platform.config.client;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -29,6 +30,8 @@ import org.springframework.core.env.CompositePropertySource;
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.jmx.export.annotation.ManagedOperation;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
import org.springframework.platform.bootstrap.config.ConfigServiceBootstrapConfiguration;
|
||||
import org.springframework.platform.context.environment.EnvironmentChangeEvent;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -38,6 +41,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "endpoints.refresh", ignoreUnknownFields = false)
|
||||
@ManagedResource
|
||||
public class RefreshEndpoint extends AbstractEndpoint<Collection<String>> {
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
@@ -49,18 +53,23 @@ public class RefreshEndpoint extends AbstractEndpoint<Collection<String>> {
|
||||
this.context = context;
|
||||
this.bootstrap = bootstrap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> invoke() {
|
||||
|
||||
@ManagedOperation
|
||||
public synchronized String[] refresh() {
|
||||
Map<String, Object> before = extract(context.getEnvironment().getPropertySources());
|
||||
bootstrap.initialize(context);
|
||||
Set<String> keys = changes(before,
|
||||
extract(context.getEnvironment().getPropertySources())).keySet();
|
||||
if (keys.isEmpty()) {
|
||||
return keys;
|
||||
return new String[0];
|
||||
}
|
||||
context.publishEvent(new EnvironmentChangeEvent(keys));
|
||||
return keys;
|
||||
return keys.toArray(new String[keys.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> invoke() {
|
||||
return Arrays.asList(refresh());
|
||||
}
|
||||
|
||||
private Map<String, Object> changes(Map<String, Object> before,
|
||||
|
||||
@@ -20,11 +20,15 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.context.event.ApplicationPreparedEvent;
|
||||
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.jmx.export.annotation.ManagedAttribute;
|
||||
import org.springframework.jmx.export.annotation.ManagedOperation;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
@@ -37,6 +41,7 @@ import org.springframework.util.ClassUtils;
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("endpoints.restart")
|
||||
@ManagedResource
|
||||
public class RestartEndpoint extends AbstractEndpoint<Boolean> implements
|
||||
ApplicationListener<ApplicationPreparedEvent> {
|
||||
|
||||
@@ -79,7 +84,48 @@ 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean invoke() {
|
||||
if (isRunning()) {
|
||||
pause();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private class ResumeEndpoint extends AbstractEndpoint<Boolean> {
|
||||
|
||||
public ResumeEndpoint() {
|
||||
super("resume", true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean invoke() {
|
||||
if (!isRunning()) {
|
||||
resume();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ManagedOperation
|
||||
public synchronized ConfigurableApplicationContext restart() {
|
||||
if (context != null) {
|
||||
context.close();
|
||||
@@ -90,6 +136,28 @@ public class RestartEndpoint extends AbstractEndpoint<Boolean> implements
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@ManagedAttribute
|
||||
public boolean isRunning() {
|
||||
if (context != null) {
|
||||
return context.isRunning();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ManagedOperation
|
||||
public synchronized void pause() {
|
||||
if (context != null) {
|
||||
context.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@ManagedOperation
|
||||
public synchronized void resume() {
|
||||
if (context != null) {
|
||||
context.start();
|
||||
}
|
||||
}
|
||||
|
||||
private void overrideClassLoaderForRestart() {
|
||||
ClassUtils.overrideThreadContextClassLoader(application.getClass().getClassLoader());
|
||||
|
||||
@@ -18,7 +18,9 @@ package org.springframework.platform.context.restart;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@@ -55,5 +57,34 @@ public class RestartMvcEndpoint extends EndpointMvcAdapter {
|
||||
return Collections.singletonMap(
|
||||
"message", "Restarting");
|
||||
}
|
||||
|
||||
public MvcEndpoint getPauseEndpoint() {
|
||||
return new GenericPostableMvcEndpoint(((RestartEndpoint)getDelegate()).getPauseEndpoint());
|
||||
}
|
||||
|
||||
public MvcEndpoint getResumeEndpoint() {
|
||||
return new GenericPostableMvcEndpoint(((RestartEndpoint)getDelegate()).getResumeEndpoint());
|
||||
}
|
||||
|
||||
|
||||
private static class GenericPostableMvcEndpoint extends EndpointMvcAdapter {
|
||||
|
||||
public GenericPostableMvcEndpoint(Endpoint<?> delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
@Override
|
||||
public Object invoke() {
|
||||
if (!getDelegate().isEnabled()) {
|
||||
return new ResponseEntity<Map<String, String>>(Collections.singletonMap(
|
||||
"message", "This endpoint is disabled"), HttpStatus.NOT_FOUND);
|
||||
}
|
||||
return super.invoke();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user