diff --git a/spring-platform-config-client/src/main/java/org/springframework/platform/autoconfigure/RefreshAutoConfiguration.java b/spring-platform-config-client/src/main/java/org/springframework/platform/autoconfigure/RefreshAutoConfiguration.java index f05e4354..e582d63c 100644 --- a/spring-platform-config-client/src/main/java/org/springframework/platform/autoconfigure/RefreshAutoConfiguration.java +++ b/spring-platform-config-client/src/main/java/org/springframework/platform/autoconfigure/RefreshAutoConfiguration.java @@ -45,6 +45,7 @@ import org.springframework.platform.context.properties.ConfigurationPropertiesRe import org.springframework.platform.context.restart.RestartEndpoint; import org.springframework.platform.context.restart.RestartMvcEndpoint; import org.springframework.platform.context.scope.refresh.RefreshScope; +import org.springframework.platform.endpoint.GenericPostableMvcEndpoint; @Configuration @ConditionalOnClass(RefreshScope.class) @@ -88,21 +89,22 @@ public class RefreshAutoConfiguration { @ConditionalOnClass(IntegrationMBeanExporter.class) protected static class RefreshEndpointWithIntegration { - @Autowired + @Autowired(required=false) private IntegrationMBeanExporter exporter; @Bean @ConditionalOnMissingBean public RestartEndpoint restartEndpoint() { RestartEndpoint endpoint = new RestartEndpoint(); - if (exporter!=null) { + if (exporter != null) { endpoint.setIntegrationMBeanExporter(exporter); } return endpoint; } + } - @ConditionalOnMissingClass(name="org.springframework.integration.monitor.IntegrationMBeanExporter") + @ConditionalOnMissingClass(name = "org.springframework.integration.monitor.IntegrationMBeanExporter") protected static class RefreshEndpointWithoutIntegration { @Bean @@ -131,13 +133,16 @@ public class RefreshAutoConfiguration { @Bean @ConditionalOnMissingBean - public RefreshEndpoint refreshEndpoint( - ConfigurableApplicationContext context, - ConfigServiceBootstrapConfiguration bootstrap) { - RefreshEndpoint endpoint = new RefreshEndpoint(context, bootstrap); + public RefreshEndpoint refreshEndpoint(ConfigurableApplicationContext context) { + RefreshEndpoint endpoint = new RefreshEndpoint(context); return endpoint; } + @Bean + public MvcEndpoint refreshMvcEndpoint(RefreshEndpoint endpoint) { + return new GenericPostableMvcEndpoint(endpoint); + } + } @Configuration diff --git a/spring-platform-config-client/src/main/java/org/springframework/platform/config/client/RefreshEndpoint.java b/spring-platform-config-client/src/main/java/org/springframework/platform/config/client/RefreshEndpoint.java index b3ce853b..3b7fe167 100644 --- a/spring-platform-config-client/src/main/java/org/springframework/platform/config/client/RefreshEndpoint.java +++ b/spring-platform-config-client/src/main/java/org/springframework/platform/config/client/RefreshEndpoint.java @@ -20,23 +20,25 @@ import java.lang.reflect.Field; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; 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.builder.SpringApplicationBuilder; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Configuration; 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.core.env.StandardEnvironment; 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; +import org.springframework.web.context.support.StandardServletEnvironment; /** * @author Dave Syer @@ -46,28 +48,51 @@ import org.springframework.util.ReflectionUtils; @ManagedResource public class RefreshEndpoint extends AbstractEndpoint> { + private Set standardSources = new HashSet(Arrays.asList( + StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, + StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, + StandardServletEnvironment.JNDI_PROPERTY_SOURCE_NAME, + StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME, + StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME)); + private ConfigurableApplicationContext context; - private ConfigServiceBootstrapConfiguration bootstrap = new ConfigServiceBootstrapConfiguration(); - - public RefreshEndpoint(ConfigurableApplicationContext context, ConfigServiceBootstrapConfiguration bootstrap) { + public RefreshEndpoint(ConfigurableApplicationContext context) { super("refresh"); this.context = context; - this.bootstrap = bootstrap; } - + @ManagedOperation public synchronized String[] refresh() { Map before = extract(context.getEnvironment().getPropertySources()); - bootstrap.initialize(context); - new ConfigFileApplicationListener().onApplicationEvent(new ApplicationEnvironmentPreparedEvent(null, null, context.getEnvironment())); + addConfigFilesToEnvironment(); Set keys = changes(before, extract(context.getEnvironment().getPropertySources())).keySet(); if (keys.isEmpty()) { return new String[0]; } context.publishEvent(new EnvironmentChangeEvent(keys)); - return keys.toArray(new String[keys.size()]); + return keys.toArray(new String[keys.size()]); + } + + private void addConfigFilesToEnvironment() { + ConfigurableApplicationContext capture = new SpringApplicationBuilder(Empty.class).showBanner( + false).web(false).environment(context.getEnvironment()).run(); + MutablePropertySources target = context.getEnvironment().getPropertySources(); + for (PropertySource source : capture.getEnvironment().getPropertySources()) { + String name = source.getName(); + if (!standardSources.contains(name)) { + if (target.contains(name)) { + target.replace(name, source); + } else { + if (target.contains("defaultProperties")) { + target.addBefore("defaultProperties", source); + } else { + target.addLast(source); + } + } + } + } } @Override @@ -105,8 +130,11 @@ public class RefreshEndpoint extends AbstractEndpoint> { private Map extract(MutablePropertySources propertySources) { Map result = new HashMap(); - PropertySource parent = propertySources.get("bootstrap"); - extract(parent, result); + for (PropertySource parent : propertySources) { + if (!standardSources.contains(parent.getName())) { + extract(parent, result); + } + } return result; } @@ -131,4 +159,9 @@ public class RefreshEndpoint extends AbstractEndpoint> { } } + @Configuration + protected static class Empty { + + } + } diff --git a/spring-platform-config-client/src/main/java/org/springframework/platform/context/restart/RestartMvcEndpoint.java b/spring-platform-config-client/src/main/java/org/springframework/platform/context/restart/RestartMvcEndpoint.java index c3e06ef3..0cb9bdd2 100644 --- a/spring-platform-config-client/src/main/java/org/springframework/platform/context/restart/RestartMvcEndpoint.java +++ b/spring-platform-config-client/src/main/java/org/springframework/platform/context/restart/RestartMvcEndpoint.java @@ -18,11 +18,11 @@ 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.platform.endpoint.GenericPostableMvcEndpoint; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; @@ -66,25 +66,5 @@ public class RestartMvcEndpoint extends EndpointMvcAdapter { 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>(Collections.singletonMap( - "message", "This endpoint is disabled"), HttpStatus.NOT_FOUND); - } - return super.invoke(); - } - - } - } diff --git a/spring-platform-config-client/src/main/java/org/springframework/platform/endpoint/GenericPostableMvcEndpoint.java b/spring-platform-config-client/src/main/java/org/springframework/platform/endpoint/GenericPostableMvcEndpoint.java new file mode 100644 index 00000000..7f422b2f --- /dev/null +++ b/spring-platform-config-client/src/main/java/org/springframework/platform/endpoint/GenericPostableMvcEndpoint.java @@ -0,0 +1,46 @@ +/* + * Copyright 2013-2014 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.platform.endpoint; + +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.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +public 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>(Collections.singletonMap( + "message", "This endpoint is disabled"), HttpStatus.NOT_FOUND); + } + return super.invoke(); + } + +} \ No newline at end of file diff --git a/spring-platform-config-client/src/test/java/org/springframework/platform/context/scope/refresh/RefreshScopeConcurrencyTests.java b/spring-platform-config-client/src/test/java/org/springframework/platform/context/scope/refresh/RefreshScopeConcurrencyTests.java index 18b7a981..765e4f35 100644 --- a/spring-platform-config-client/src/test/java/org/springframework/platform/context/scope/refresh/RefreshScopeConcurrencyTests.java +++ b/spring-platform-config-client/src/test/java/org/springframework/platform/context/scope/refresh/RefreshScopeConcurrencyTests.java @@ -86,7 +86,7 @@ public class RefreshScopeConcurrencyTests { } } }); - assertTrue(latch.await(500, TimeUnit.MILLISECONDS)); + assertTrue(latch.await(1500, TimeUnit.MILLISECONDS)); logger.info("Refreshing"); scope.refreshAll(); assertEquals("Foo", service.getMessage()); diff --git a/spring-platform-config-sample/src/main/resources/application.yml b/spring-platform-config-sample/src/main/resources/application.yml index 0593a41d..53923f63 100644 --- a/spring-platform-config-sample/src/main/resources/application.yml +++ b/spring-platform-config-sample/src/main/resources/application.yml @@ -1,5 +1,5 @@ info: - component: Config Sample + component: Config Samples endpoints: restart: enabled: true \ No newline at end of file