From 689d12e9c14629027ebb373840b2af3c052ce337 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 25 Nov 2014 12:23:47 +0000 Subject: [PATCH] Break Mvc endpoint configuration out from non Mvc Fixes gh-44 because it allows an extra layer to insert an @AutoConfigureAfter. Also adds some more integration tests for refresh scope Per gh-43, note that @Configuration does not play well with @RefreshScope (see @Ignored test case). --- .../EnvironmentEndpointAutoConfiguration.java | 78 +++++++ .../RefreshAutoConfiguration.java | 44 ---- .../client/ConfigServerHealthIndicator.java | 3 +- .../context/restart/RestartEndpoint.java | 17 +- .../main/resources/META-INF/spring.factories | 1 + .../ImportRefreshScopeIntegrationTests.java | 71 ++++++ .../ProxyRefreshScopeIntegrationTests.java | 212 ------------------ .../RefreshEndpointIntegrationTests.java | 103 +++++++++ ...eshScopeConfigurationIntegrationTests.java | 87 +++++++ .../src/test/resources/application.properties | 3 +- 10 files changed, 347 insertions(+), 272 deletions(-) create mode 100644 spring-cloud-config-client/src/main/java/org/springframework/cloud/autoconfigure/EnvironmentEndpointAutoConfiguration.java create mode 100644 spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/ImportRefreshScopeIntegrationTests.java delete mode 100644 spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/ProxyRefreshScopeIntegrationTests.java create mode 100644 spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/RefreshEndpointIntegrationTests.java create mode 100644 spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/RefreshScopeConfigurationIntegrationTests.java diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/autoconfigure/EnvironmentEndpointAutoConfiguration.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/autoconfigure/EnvironmentEndpointAutoConfiguration.java new file mode 100644 index 00000000..4c944f5a --- /dev/null +++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/autoconfigure/EnvironmentEndpointAutoConfiguration.java @@ -0,0 +1,78 @@ +/* + * 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.cloud.autoconfigure; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration; +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; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration; +import org.springframework.cloud.config.client.RefreshEndpoint; +import org.springframework.cloud.context.environment.EnvironmentManager; +import org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint; +import org.springframework.cloud.context.restart.RestartEndpoint; +import org.springframework.cloud.context.restart.RestartMvcEndpoint; +import org.springframework.cloud.endpoint.GenericPostableMvcEndpoint; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Dave Syer + * + */ +@Configuration +@ConditionalOnClass(EnvironmentEndpoint.class) +@ConditionalOnExpression("${endpoints.env.enabled:true}") +@ConditionalOnWebApplication +@ConditionalOnBean({ EnvironmentEndpoint.class, RefreshEndpoint.class }) +@AutoConfigureAfter({ WebMvcAutoConfiguration.class, EndpointAutoConfiguration.class }) +public class EnvironmentEndpointAutoConfiguration { + + @Autowired + private RestartEndpoint restartEndpoint; + + @Bean + public EnvironmentManagerMvcEndpoint environmentManagerEndpoint( + EnvironmentEndpoint delegate, EnvironmentManager environment) { + return new EnvironmentManagerMvcEndpoint(delegate, environment); + } + + @Bean + public MvcEndpoint refreshMvcEndpoint(RefreshEndpoint endpoint) { + return new GenericPostableMvcEndpoint(endpoint); + } + + @Bean + public RestartMvcEndpoint restartMvcEndpoint() { + return new RestartMvcEndpoint(restartEndpoint); + } + + @Bean + public MvcEndpoint pauseMvcEndpoint(RestartMvcEndpoint restartEndpoint) { + return restartEndpoint.getPauseEndpoint(); + } + + @Bean + public MvcEndpoint resumeMvcEndpoint(RestartMvcEndpoint restartEndpoint) { + return restartEndpoint.getResumeEndpoint(); + } + +} diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/autoconfigure/RefreshAutoConfiguration.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/autoconfigure/RefreshAutoConfiguration.java index 1362b6d4..a3632cdc 100644 --- a/spring-cloud-config-client/src/main/java/org/springframework/cloud/autoconfigure/RefreshAutoConfiguration.java +++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/autoconfigure/RefreshAutoConfiguration.java @@ -23,16 +23,13 @@ import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration; import org.springframework.boot.actuate.endpoint.Endpoint; -import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint; import org.springframework.boot.actuate.endpoint.InfoEndpoint; -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; 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; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -41,12 +38,9 @@ import org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfigu import org.springframework.cloud.config.client.RefreshEndpoint; import org.springframework.cloud.context.environment.EnvironmentChangeEvent; import org.springframework.cloud.context.environment.EnvironmentManager; -import org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint; import org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder; import org.springframework.cloud.context.restart.RestartEndpoint; -import org.springframework.cloud.context.restart.RestartMvcEndpoint; import org.springframework.cloud.context.scope.refresh.RefreshScope; -import org.springframework.cloud.endpoint.GenericPostableMvcEndpoint; import org.springframework.cloud.logging.LoggingRebinder; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; @@ -189,44 +183,6 @@ public class RefreshAutoConfiguration { return endpoint; } - @Bean - public MvcEndpoint refreshMvcEndpoint(RefreshEndpoint endpoint) { - return new GenericPostableMvcEndpoint(endpoint); - } - - } - - @Configuration - @ConditionalOnWebApplication - @ConditionalOnClass(EnvironmentEndpoint.class) - @ConditionalOnExpression("${endpoints.env.enabled:true}") - @ConditionalOnBean(EnvironmentEndpoint.class) - protected static class EnvironmentEndpointConfiguration { - - @Autowired - private RestartEndpoint restartEndpoint; - - @Bean - public EnvironmentManagerMvcEndpoint environmentManagerEndpoint( - EnvironmentEndpoint delegate, EnvironmentManager environment) { - return new EnvironmentManagerMvcEndpoint(delegate, environment); - } - - @Bean - public RestartMvcEndpoint restartMvcEndpoint() { - return new RestartMvcEndpoint(restartEndpoint); - } - - @Bean - public MvcEndpoint pauseMvcEndpoint(RestartMvcEndpoint restartEndpoint) { - return restartEndpoint.getPauseEndpoint(); - } - - @Bean - public MvcEndpoint resumeMvcEndpoint(RestartMvcEndpoint restartEndpoint) { - return restartEndpoint.getResumeEndpoint(); - } - } } diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerHealthIndicator.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerHealthIndicator.java index 8d12fe78..0c598b5d 100644 --- a/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerHealthIndicator.java +++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServerHealthIndicator.java @@ -35,7 +35,8 @@ public class ConfigServerHealthIndicator extends AbstractHealthIndicator { Field field = ReflectionUtils.findField(CompositePropertySource.class, "propertySources"); field.setAccessible(true); - Set> propertySources = (Set>) field.get(composite); + @SuppressWarnings("unchecked") + Set> propertySources = (Set>) field.get(composite); List sources = new ArrayList<>(); for (PropertySource ps : propertySources) { sources.add(ps.getName()); diff --git a/spring-cloud-config-client/src/main/java/org/springframework/cloud/context/restart/RestartEndpoint.java b/spring-cloud-config-client/src/main/java/org/springframework/cloud/context/restart/RestartEndpoint.java index 3c128abd..94171a97 100644 --- a/spring-cloud-config-client/src/main/java/org/springframework/cloud/context/restart/RestartEndpoint.java +++ b/spring-cloud-config-client/src/main/java/org/springframework/cloud/context/restart/RestartEndpoint.java @@ -62,19 +62,8 @@ public class RestartEndpoint extends AbstractEndpoint implements 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; @@ -160,7 +149,7 @@ public class RestartEndpoint extends AbstractEndpoint implements public synchronized ConfigurableApplicationContext restart() { if (context != null) { if (integrationShutdown != null) { - integrationShutdown.stop(forceShutdown, timeout); + integrationShutdown.stop(timeout); } application.setEnvironment(context.getEnvironment()); context.close(); @@ -206,8 +195,8 @@ public class RestartEndpoint extends AbstractEndpoint implements this.exporter = (IntegrationMBeanExporter) exporter; } - public void stop(boolean force, long timeout) { - exporter.stopActiveComponents(force, timeout); + public void stop(long timeout) { + exporter.stopActiveComponents(timeout); } } diff --git a/spring-cloud-config-client/src/main/resources/META-INF/spring.factories b/spring-cloud-config-client/src/main/resources/META-INF/spring.factories index 998b5320..b6359593 100644 --- a/spring-cloud-config-client/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-config-client/src/main/resources/META-INF/spring.factories @@ -1,6 +1,7 @@ # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.autoconfigure.RefreshAutoConfiguration,\ +org.springframework.cloud.autoconfigure.EnvironmentEndpointAutoConfiguration,\ org.springframework.cloud.autoconfigure.ConfigClientAutoConfiguration # Application Listeners diff --git a/spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/ImportRefreshScopeIntegrationTests.java b/spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/ImportRefreshScopeIntegrationTests.java new file mode 100644 index 00000000..c0e4500d --- /dev/null +++ b/spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/ImportRefreshScopeIntegrationTests.java @@ -0,0 +1,71 @@ +/* + * Copyright 2006-2007 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.cloud.context.scope.refresh; + +import static org.junit.Assert.assertEquals; + +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.cloud.context.scope.refresh.ImportRefreshScopeIntegrationTests.TestConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@SpringApplicationConfiguration(classes = TestConfiguration.class) +@RunWith(SpringJUnit4ClassRunner.class) +@Ignore("gh-43") +public class ImportRefreshScopeIntegrationTests { + + @Autowired + private ConfigurableListableBeanFactory beanFactory; + + @Autowired + private ExampleService service; + + @Autowired + private org.springframework.cloud.context.scope.refresh.RefreshScope scope; + + @Test + @DirtiesContext + public void testSimpleProperties() throws Exception { + assertEquals("Hello scope!", service.getMessage()); + assertEquals("refresh", beanFactory.getBeanDefinition("service").getScope()); + assertEquals("Hello scope!", service.getMessage()); + } + + @Configuration("service") + @RefreshScope + public static class ExampleService { + + public String getMessage() { + return "Hello scope!"; + } + + } + + @Configuration + @Import({ RefreshAutoConfiguration.class, ExampleService.class }) + protected static class TestConfiguration { + } + +} diff --git a/spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/ProxyRefreshScopeIntegrationTests.java b/spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/ProxyRefreshScopeIntegrationTests.java deleted file mode 100644 index 648b0bec..00000000 --- a/spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/ProxyRefreshScopeIntegrationTests.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright 2006-2007 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.cloud.context.scope.refresh; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertTrue; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.aop.framework.Advised; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.test.SpringApplicationConfiguration; -import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.cloud.context.scope.refresh.ProxyRefreshScopeIntegrationTests.TestConfiguration; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.jmx.export.annotation.ManagedAttribute; -import org.springframework.jmx.export.annotation.ManagedResource; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@SpringApplicationConfiguration(classes = TestConfiguration.class) -@RunWith(SpringJUnit4ClassRunner.class) -@Ignore -public class ProxyRefreshScopeIntegrationTests { - - @Autowired - private Service service; - - @Autowired - private TestProperties properties; - - @Autowired - private org.springframework.cloud.context.scope.refresh.RefreshScope scope; - - @Before - public void init() { - ExampleService.reset(); - } - - @Test - @DirtiesContext - public void testSimpleProperties() throws Exception { - assertEquals("Hello scope!", service.getMessage()); - assertTrue(service instanceof Advised); - // Change the dynamic property source... - properties.setMessage("Foo"); - // ...but don't refresh, so the bean stays the same: - assertEquals("Hello scope!", service.getMessage()); - assertEquals(1, ExampleService.getInitCount()); - assertEquals(0, ExampleService.getDestroyCount()); - } - - @Test - @DirtiesContext - public void testRefresh() throws Exception { - assertEquals("Hello scope!", service.getMessage()); - String id1 = service.toString(); - // Change the dynamic property source... - properties.setMessage("Foo"); - // ...and then refresh, so the bean is re-initialized: - scope.refreshAll(); - String id2 = service.toString(); - assertEquals("Foo", service.getMessage()); - assertEquals(2, ExampleService.getInitCount()); - assertEquals(1, ExampleService.getDestroyCount()); - assertNotSame(id1, id2); - } - - @Test - @DirtiesContext - public void testRefreshBean() throws Exception { - assertEquals("Hello scope!", service.getMessage()); - String id1 = service.toString(); - // Change the dynamic property source... - properties.setMessage("Foo"); - // ...and then refresh, so the bean is re-initialized: - scope.refresh("service"); - String id2 = service.toString(); - assertEquals("Foo", service.getMessage()); - assertEquals(2, ExampleService.getInitCount()); - assertEquals(1, ExampleService.getDestroyCount()); - assertNotSame(id1, id2); - } - - public static interface Service { - - String getMessage(); - - } - - @Configuration - @RefreshScope - public static class ExampleService implements Service, InitializingBean, - DisposableBean { - - @Autowired - private TestProperties properties; - - private static Log logger = LogFactory.getLog(ExampleService.class); - - private volatile static int initCount = 0; - private volatile static int destroyCount = 0; - - private String message = null; - private volatile long delay = 0; - - public void setDelay(long delay) { - this.delay = delay; - } - - public void afterPropertiesSet() throws Exception { - message = properties.getMessage(); - delay = properties.getDelay(); - logger.debug("Initializing message: " + message); - initCount++; - } - - public void destroy() throws Exception { - logger.debug("Destroying message: " + message); - destroyCount++; - message = null; - } - - public static void reset() { - initCount = 0; - destroyCount = 0; - } - - public static int getInitCount() { - return initCount; - } - - public static int getDestroyCount() { - return destroyCount; - } - - public void setMessage(String message) { - logger.debug("Setting message: " + message); - this.message = message; - } - - public String getMessage() { - logger.debug("Getting message: " + message); - try { - Thread.sleep(delay); - } - catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - logger.info("Returning message: " + message); - return message; - } - - } - - @Configuration - @EnableConfigurationProperties(TestProperties.class) - @Import({ RefreshAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, ExampleService.class }) - protected static class TestConfiguration { - } - - @ConfigurationProperties - @ManagedResource - protected static class TestProperties { - private String message; - private int delay; - - @ManagedAttribute - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - @ManagedAttribute - public int getDelay() { - return delay; - } - - public void setDelay(int delay) { - this.delay = delay; - } - } - -} diff --git a/spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/RefreshEndpointIntegrationTests.java b/spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/RefreshEndpointIntegrationTests.java new file mode 100644 index 00000000..029bb87a --- /dev/null +++ b/spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/RefreshEndpointIntegrationTests.java @@ -0,0 +1,103 @@ +/* + * 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.cloud.context.scope.refresh; + +import static org.junit.Assert.assertEquals; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.Collections; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.IntegrationTest; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.boot.test.TestRestTemplate; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.cloud.context.scope.refresh.RefreshEndpointIntegrationTests.ClientApp; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author Dave Syer + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = ClientApp.class) +@IntegrationTest("server.port:0") +@WebAppConfiguration +public class RefreshEndpointIntegrationTests { + + @Value("${local.server.port}") + private int port; + + @Test + public void webAccess() throws Exception { + TestRestTemplate template = new TestRestTemplate(); + template.exchange( + getUrlEncodedEntity("http://localhost:" + port + "/env", "message", + "Hello Dave!"), String.class); + template.postForObject("http://localhost:" + port + "/refresh", "", String.class); + String message = template.getForObject("http://localhost:" + port + "/", + String.class); + assertEquals("Hello Dave!", message); + } + + private RequestEntity getUrlEncodedEntity(String uri, String key, String value) + throws URISyntaxException { + MultiValueMap env = new LinkedMultiValueMap( + Collections.singletonMap("message", Arrays.asList("Hello Dave!"))); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + RequestEntity> entity = new RequestEntity>( + env, headers, HttpMethod.POST, new URI(uri)); + return entity; + } + + @Configuration + @EnableAutoConfiguration + @RestController + @RefreshScope + protected static class ClientApp { + + @Value("${message:Hello World!}") + String message; + + @RequestMapping("/") + public String hello() { + return message; + } + + public static void main(String[] args) { + SpringApplication.run(ClientApp.class, args); + } + + } + +} diff --git a/spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/RefreshScopeConfigurationIntegrationTests.java b/spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/RefreshScopeConfigurationIntegrationTests.java new file mode 100644 index 00000000..137e8ed1 --- /dev/null +++ b/spring-cloud-config-client/src/test/java/org/springframework/cloud/context/scope/refresh/RefreshScopeConfigurationIntegrationTests.java @@ -0,0 +1,87 @@ +/* + * 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.cloud.context.scope.refresh; + +import static org.junit.Assert.assertEquals; + +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.cloud.context.environment.EnvironmentManager; +import org.springframework.cloud.context.scope.refresh.RefreshScopeConfigurationIntegrationTests.ClientApp; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author Dave Syer + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = ClientApp.class) +@Ignore +public class RefreshScopeConfigurationIntegrationTests { + + @Autowired + private org.springframework.cloud.context.scope.refresh.RefreshScope scope; + + @Autowired + private EnvironmentManager environmentManager; + + @Autowired + private ClientApp application; + + /** + * See gh-43 + */ + @Test + public void beanAccess() throws Exception { + // Comment out this line and it works! + application.hello(); + environmentManager.setProperty("message", "Hello Dave!"); + scope.refreshAll(); + String message = application.hello(); + assertEquals("Hello Dave!", message); + } + + @Configuration + @EnableAutoConfiguration + @RestController + @RefreshScope + protected static class ClientApp { + + @Value("${message:Hello World!}") + String message; + + @RequestMapping("/") + public String hello() { + return message; + } + + public static void main(String[] args) { + SpringApplication.run(ClientApp.class, args); + } + + } + +} diff --git a/spring-cloud-config-client/src/test/resources/application.properties b/spring-cloud-config-client/src/test/resources/application.properties index 9999b13c..1fec7abc 100644 --- a/spring-cloud-config-client/src/test/resources/application.properties +++ b/spring-cloud-config-client/src/test/resources/application.properties @@ -1,3 +1,4 @@ message: Hello scope! delay: 0 -# debug: true \ No newline at end of file +# debug: true +logging.level.org.springframework.web: DEBUG \ No newline at end of file