From e7b09f7933fda5d0ec9fe76bad9ddd5ed5172d57 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Tue, 22 Mar 2016 11:39:36 +0800 Subject: [PATCH] Add RefreshScope support and ConfigServer return 304 when configuration is not changed --- .../apollo/biz/service/ConfigService.java | 17 +++ .../biz/service/impl/ConfigServiceImpl.java | 13 +- apollo-biz/src/main/resources/import.sql | 4 +- .../service/impl/ConfigServiceImplTest.java | 32 +++++ apollo-client/pom.xml | 4 + .../apollo/client/ApolloConfigManager.java | 35 +++++- .../client/loader/ConfigLoaderFactory.java | 5 - .../client/loader/impl/MockConfigLoader.java | 31 ----- .../client/ApolloConfigManagerTest.java | 15 ++- .../config/WebConfig.java | 2 +- .../controller/ConfigController.java | 52 ++++++++ .../server/controller/ConfigController.java | 25 ---- .../ctrip/apollo/configserver/AllTests.java | 3 +- .../controller/ConfigControllerTest.java | 111 ++++++++++++++++++ .../com/ctrip/apollo/server/AllTests.java | 14 --- .../controller/ConfigControllerTest.java | 45 ------- .../java/com/ctrip/apollo/demo/AppConfig.java | 14 ++- .../demo/controller/DemoController.java | 26 ++-- .../apollo/demo/service/DemoService.java | 23 ++++ 19 files changed, 331 insertions(+), 140 deletions(-) delete mode 100644 apollo-client/src/main/java/com/ctrip/apollo/client/loader/impl/MockConfigLoader.java rename apollo-configserver/src/main/java/com/ctrip/apollo/{server => configserver}/config/WebConfig.java (97%) create mode 100644 apollo-configserver/src/main/java/com/ctrip/apollo/configserver/controller/ConfigController.java delete mode 100644 apollo-configserver/src/main/java/com/ctrip/apollo/server/controller/ConfigController.java create mode 100644 apollo-configserver/src/test/java/com/ctrip/apollo/configserver/controller/ConfigControllerTest.java delete mode 100644 apollo-configserver/src/test/java/com/ctrip/apollo/server/AllTests.java delete mode 100644 apollo-configserver/src/test/java/com/ctrip/apollo/server/controller/ConfigControllerTest.java create mode 100644 apollo-demo/src/main/java/com/ctrip/apollo/demo/service/DemoService.java diff --git a/apollo-biz/src/main/java/com/ctrip/apollo/biz/service/ConfigService.java b/apollo-biz/src/main/java/com/ctrip/apollo/biz/service/ConfigService.java index ea2838658..da373f675 100644 --- a/apollo-biz/src/main/java/com/ctrip/apollo/biz/service/ConfigService.java +++ b/apollo-biz/src/main/java/com/ctrip/apollo/biz/service/ConfigService.java @@ -1,5 +1,6 @@ package com.ctrip.apollo.biz.service; +import com.ctrip.apollo.biz.entity.Version; import com.ctrip.apollo.core.model.ApolloConfig; /** @@ -15,4 +16,20 @@ public interface ConfigService { * @return */ ApolloConfig loadConfig(long appId, String clusterName, String versionName); + + /** + * Load Version by appId and versionName from database + * @param appId + * @param versionName + * @return + */ + Version loadVersionByAppIdAndVersionName(long appId, String versionName); + + /** + * Load Config by version and clusterName from database + * @param version + * @param clusterName + * @return + */ + ApolloConfig loadConfigByVersionAndClusterName(Version version, String clusterName); } diff --git a/apollo-biz/src/main/java/com/ctrip/apollo/biz/service/impl/ConfigServiceImpl.java b/apollo-biz/src/main/java/com/ctrip/apollo/biz/service/impl/ConfigServiceImpl.java index 5a20af912..a747b5c87 100644 --- a/apollo-biz/src/main/java/com/ctrip/apollo/biz/service/impl/ConfigServiceImpl.java +++ b/apollo-biz/src/main/java/com/ctrip/apollo/biz/service/impl/ConfigServiceImpl.java @@ -32,10 +32,21 @@ public class ConfigServiceImpl implements ConfigService { @Override public ApolloConfig loadConfig(long appId, String clusterName, String versionName) { - Version version = versionRepository.findByAppIdAndName(appId, versionName); + Version version = loadVersionByAppIdAndVersionName(appId, versionName); if (version == null) { return null; } + + return loadConfigByVersionAndClusterName(version, clusterName); + } + + @Override + public Version loadVersionByAppIdAndVersionName(long appId, String versionName) { + return versionRepository.findByAppIdAndName(appId, versionName); + } + + @Override + public ApolloConfig loadConfigByVersionAndClusterName(Version version, String clusterName) { ReleaseSnapShot releaseSnapShot = releaseSnapShotRepository.findByReleaseIdAndClusterName(version.getReleaseId(), clusterName); if (releaseSnapShot == null) { diff --git a/apollo-biz/src/main/resources/import.sql b/apollo-biz/src/main/resources/import.sql index dd4b29bad..14d70fc36 100644 --- a/apollo-biz/src/main/resources/import.sql +++ b/apollo-biz/src/main/resources/import.sql @@ -4,5 +4,5 @@ INSERT INTO Cluster (AppId, IsDeleted, Name) VALUES (101, 0, 'default'); INSERT INTO Version (AppId, IsDeleted, Name, ReleaseId) VALUES (101, 0, '1.0', 1); INSERT INTO Version (AppId, IsDeleted, Name, ReleaseId) VALUES (102, 0, '1.0', 2); -INSERT INTO RELEASESNAPSHOT (ClusterName, IsDeleted, ReleaseId, Configurations) VALUES ('default', 0, 1, '{"apollo.foo":"bar"}'); -INSERT INTO RELEASESNAPSHOT (ClusterName, IsDeleted, ReleaseId, Configurations) VALUES ('default', 0, 2, '{"apollo.bar":"foo"}'); +INSERT INTO RELEASESNAPSHOT (ClusterName, IsDeleted, ReleaseId, Configurations) VALUES ('default', 0, 1, '{"apollo.foo":"bar", "apollo.bar":"foo"}'); +INSERT INTO RELEASESNAPSHOT (ClusterName, IsDeleted, ReleaseId, Configurations) VALUES ('default', 0, 2, '{"demo.foo":"demo1", "demo.bar":"demo2"}'); diff --git a/apollo-biz/src/test/java/com/ctrip/apollo/biz/service/impl/ConfigServiceImplTest.java b/apollo-biz/src/test/java/com/ctrip/apollo/biz/service/impl/ConfigServiceImplTest.java index f01ea31e4..281b7f8eb 100644 --- a/apollo-biz/src/test/java/com/ctrip/apollo/biz/service/impl/ConfigServiceImplTest.java +++ b/apollo-biz/src/test/java/com/ctrip/apollo/biz/service/impl/ConfigServiceImplTest.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.util.Map; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.*; @@ -66,7 +67,38 @@ public class ConfigServiceImplTest { assertEquals(someVersionName, result.getVersion()); assertEquals(someReleaseId, result.getReleaseId()); assertEquals(someMap, result.getConfigurations()); + } + + @Test + public void testLoadConfigWithVersionNotFound() throws Exception { + long someAppId = 1; + String someClusterName = "someClusterName"; + String someVersionName = "someVersionName"; + + when(versionRepository.findByAppIdAndName(someAppId, someVersionName)).thenReturn(null); + + ApolloConfig result = configService.loadConfig(someAppId, someClusterName, someVersionName); + + assertNull(result); + verify(versionRepository, times(1)).findByAppIdAndName(someAppId, someVersionName); + } + + @Test + public void testLoadConfigWithConfigNotFound() throws Exception { + long someAppId = 1; + String someClusterName = "someClusterName"; + String someVersionName = "someVersionName"; + long someReleaseId = 1; + Version someVersion = assembleVersion(someAppId, someVersionName, someReleaseId); + + when(versionRepository.findByAppIdAndName(someAppId, someVersionName)).thenReturn(someVersion); + when(releaseSnapShotRepository.findByReleaseIdAndClusterName(someReleaseId, someClusterName)).thenReturn(null); + + ApolloConfig result = configService.loadConfig(someAppId, someClusterName, someVersionName); + assertNull(result); + verify(versionRepository, times(1)).findByAppIdAndName(someAppId, someVersionName); + verify(releaseSnapShotRepository, times(1)).findByReleaseIdAndClusterName(someReleaseId, someClusterName); } private Version assembleVersion(long appId, String versionName, long releaseId) { diff --git a/apollo-client/pom.xml b/apollo-client/pom.xml index 86d3b43e8..5a2f3c4f3 100644 --- a/apollo-client/pom.xml +++ b/apollo-client/pom.xml @@ -29,6 +29,10 @@ org.springframework spring-web + + org.springframework.cloud + spring-cloud-context + com.google.guava diff --git a/apollo-client/src/main/java/com/ctrip/apollo/client/ApolloConfigManager.java b/apollo-client/src/main/java/com/ctrip/apollo/client/ApolloConfigManager.java index 20ed7e555..3d7338fa7 100644 --- a/apollo-client/src/main/java/com/ctrip/apollo/client/ApolloConfigManager.java +++ b/apollo-client/src/main/java/com/ctrip/apollo/client/ApolloConfigManager.java @@ -4,19 +4,23 @@ import com.ctrip.apollo.client.loader.ConfigLoader; import com.ctrip.apollo.client.loader.ConfigLoaderFactory; import com.ctrip.apollo.client.util.ConfigUtil; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; +import org.springframework.cloud.context.scope.refresh.RefreshScope; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.core.Ordered; import org.springframework.core.PriorityOrdered; import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.MutablePropertySources; /** - * Client side config + * Client side config manager * * @author Jason Song(song_s@ctrip.com) */ @@ -48,9 +52,27 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor, */ @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { + registerDependentBeans(registry); preparePropertySource(); } + /** + * Register beans needed for Apollo Config Client + *
  • + * - RefreshScope: used to refresh beans when configurations changes + *
  • + *
  • + * - PropertySourcesPlaceholderConfigurer: used to support placeholder configuration injection + *
  • + * @param registry + */ + private void registerDependentBeans(BeanDefinitionRegistry registry) { + BeanDefinition refreshScope = BeanDefinitionBuilder.genericBeanDefinition(RefreshScope.class).getBeanDefinition(); + registry.registerBeanDefinition("refreshScope", refreshScope); + BeanDefinition propertySourcesPlaceholderConfigurer = BeanDefinitionBuilder.genericBeanDefinition(PropertySourcesPlaceholderConfigurer.class).getBeanDefinition(); + registry.registerBeanDefinition("propertySourcesPlaceholderConfigurer", propertySourcesPlaceholderConfigurer); + } + /** * This is executed after postProcessBeanDefinitionRegistry */ @@ -58,11 +80,20 @@ public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor, public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } + /** + * Make sure this bean is called before other beans + * @return + */ @Override public int getOrder() { - return Ordered.HIGHEST_PRECEDENCE + 1; + return Ordered.HIGHEST_PRECEDENCE; } + /** + * Prepare property sources + * First try to load from remote + * If loading from remote failed, then fall back to local cached properties + */ void preparePropertySource() { MutablePropertySources currentPropertySources = applicationContext.getEnvironment().getPropertySources(); if (currentPropertySources.contains(APOLLO_PROPERTY_SOURCE_NAME)) { diff --git a/apollo-client/src/main/java/com/ctrip/apollo/client/loader/ConfigLoaderFactory.java b/apollo-client/src/main/java/com/ctrip/apollo/client/loader/ConfigLoaderFactory.java index ee5ecf6dd..54de60121 100644 --- a/apollo-client/src/main/java/com/ctrip/apollo/client/loader/ConfigLoaderFactory.java +++ b/apollo-client/src/main/java/com/ctrip/apollo/client/loader/ConfigLoaderFactory.java @@ -1,6 +1,5 @@ package com.ctrip.apollo.client.loader; -import com.ctrip.apollo.client.loader.impl.MockConfigLoader; import com.ctrip.apollo.client.loader.impl.RemoteConfigLoader; /** @@ -16,10 +15,6 @@ public class ConfigLoaderFactory { return configLoaderFactory; } - public ConfigLoader getMockConfigLoader() { - return new MockConfigLoader(); - } - public ConfigLoader getRemoteConfigLoader() { return new RemoteConfigLoader(); } diff --git a/apollo-client/src/main/java/com/ctrip/apollo/client/loader/impl/MockConfigLoader.java b/apollo-client/src/main/java/com/ctrip/apollo/client/loader/impl/MockConfigLoader.java deleted file mode 100644 index c76631ee4..000000000 --- a/apollo-client/src/main/java/com/ctrip/apollo/client/loader/impl/MockConfigLoader.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.ctrip.apollo.client.loader.impl; - -import com.ctrip.apollo.client.loader.ConfigLoader; -import com.google.common.collect.Maps; -import org.springframework.core.env.CompositePropertySource; -import org.springframework.core.env.MapPropertySource; - -import java.util.Map; - -/** - * Mock config - * @author Jason Song(song_s@ctrip.com) - */ -public class MockConfigLoader implements ConfigLoader { - private static final String PROPERTY_SOURCE_NAME = "ApolloMockConfigProperties"; - - @Override - public CompositePropertySource loadPropertySource() { - CompositePropertySource composite = new CompositePropertySource(PROPERTY_SOURCE_NAME); - composite.addPropertySource(mock()); - return composite; - } - - private MapPropertySource mock() { - Map source = Maps.newHashMap(); - source.put("apollo.foo" ,"bar"); - MapPropertySource propertySource = new MapPropertySource("mock source", source); - - return propertySource; - } -} diff --git a/apollo-client/src/test/java/com/ctrip/apollo/client/ApolloConfigManagerTest.java b/apollo-client/src/test/java/com/ctrip/apollo/client/ApolloConfigManagerTest.java index 79365d160..7911b921f 100644 --- a/apollo-client/src/test/java/com/ctrip/apollo/client/ApolloConfigManagerTest.java +++ b/apollo-client/src/test/java/com/ctrip/apollo/client/ApolloConfigManagerTest.java @@ -7,6 +7,8 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.CompositePropertySource; @@ -32,10 +34,12 @@ public class ApolloConfigManagerTest { private ConfigurableEnvironment env; @Mock private MutablePropertySources mutablePropertySources; + @Mock + private BeanDefinitionRegistry beanDefinitionRegistry; @Before public void setUp() { - apolloConfigManager = new ApolloConfigManager(); + apolloConfigManager = spy(new ApolloConfigManager()); when(applicationContext.getEnvironment()).thenReturn(env); when(env.getPropertySources()).thenReturn(mutablePropertySources); @@ -68,4 +72,13 @@ public class ApolloConfigManagerTest { assertTrue(insertedPropertySource.getPropertySources().contains(somePropertySource)); } + @Test + public void testPostProcessBeanDefinitionRegistry() { + doNothing().when(apolloConfigManager).preparePropertySource(); + + apolloConfigManager.postProcessBeanDefinitionRegistry(beanDefinitionRegistry); + + verify(beanDefinitionRegistry, times(2)).registerBeanDefinition(anyString(), any(BeanDefinition.class)); + } + } diff --git a/apollo-configserver/src/main/java/com/ctrip/apollo/server/config/WebConfig.java b/apollo-configserver/src/main/java/com/ctrip/apollo/configserver/config/WebConfig.java similarity index 97% rename from apollo-configserver/src/main/java/com/ctrip/apollo/server/config/WebConfig.java rename to apollo-configserver/src/main/java/com/ctrip/apollo/configserver/config/WebConfig.java index 69a176cb9..744c937a4 100644 --- a/apollo-configserver/src/main/java/com/ctrip/apollo/server/config/WebConfig.java +++ b/apollo-configserver/src/main/java/com/ctrip/apollo/configserver/config/WebConfig.java @@ -1,4 +1,4 @@ -package com.ctrip.apollo.server.config; +package com.ctrip.apollo.configserver.config; import org.h2.server.web.WebServlet; import org.springframework.boot.context.embedded.ServletRegistrationBean; diff --git a/apollo-configserver/src/main/java/com/ctrip/apollo/configserver/controller/ConfigController.java b/apollo-configserver/src/main/java/com/ctrip/apollo/configserver/controller/ConfigController.java new file mode 100644 index 000000000..769f402fd --- /dev/null +++ b/apollo-configserver/src/main/java/com/ctrip/apollo/configserver/controller/ConfigController.java @@ -0,0 +1,52 @@ +package com.ctrip.apollo.configserver.controller; + +import com.ctrip.apollo.biz.entity.Version; +import com.ctrip.apollo.biz.service.ConfigService; +import com.ctrip.apollo.core.model.ApolloConfig; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author Jason Song(song_s@ctrip.com) + */ +@RestController +public class ConfigController { + @Resource(name = "configService") + private ConfigService configService; + + @RequestMapping(value = "/{appId}/{clusterName}/{versionName:.*}") + public ApolloConfig queryConfig(@PathVariable long appId, + @PathVariable String clusterName, + @PathVariable String versionName, + @RequestParam(value = "releaseId", defaultValue = "-1") long clientSideReleaseId, + HttpServletResponse response) throws IOException { + Version version = configService.loadVersionByAppIdAndVersionName(appId, versionName); + if (version == null) { + response.sendError(HttpServletResponse.SC_NOT_FOUND, + String.format("Could not load version with appId: %d, versionName: %s", appId, versionName)); + return null; + } + if (version.getReleaseId() == clientSideReleaseId) { + //Client side configuration is the same with server side, return 304 + response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); + return null; + } + + ApolloConfig apolloConfig = + configService.loadConfigByVersionAndClusterName(version, clusterName); + + if (apolloConfig == null) { + response.sendError(HttpServletResponse.SC_NOT_FOUND, + String.format("Could not load config with releaseId: %d, clusterName: %s", version.getReleaseId(), clusterName)); + return null; + } + + return apolloConfig; + } +} diff --git a/apollo-configserver/src/main/java/com/ctrip/apollo/server/controller/ConfigController.java b/apollo-configserver/src/main/java/com/ctrip/apollo/server/controller/ConfigController.java deleted file mode 100644 index 984fa3f63..000000000 --- a/apollo-configserver/src/main/java/com/ctrip/apollo/server/controller/ConfigController.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.ctrip.apollo.server.controller; - -import com.ctrip.apollo.biz.service.ConfigService; -import com.ctrip.apollo.core.model.ApolloConfig; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; - -/** - * @author Jason Song(song_s@ctrip.com) - */ -@RestController -public class ConfigController { - @Resource(name = "configService") - private ConfigService configService; - - @RequestMapping(value = "/{appId}/{clusterName}/{version:.*}") - public ApolloConfig queryConfig(@PathVariable long appId, - @PathVariable String clusterName, - @PathVariable String version) { - return configService.loadConfig(appId, clusterName, version); - } -} diff --git a/apollo-configserver/src/test/java/com/ctrip/apollo/configserver/AllTests.java b/apollo-configserver/src/test/java/com/ctrip/apollo/configserver/AllTests.java index 7239a6c31..f5f5929e8 100644 --- a/apollo-configserver/src/test/java/com/ctrip/apollo/configserver/AllTests.java +++ b/apollo-configserver/src/test/java/com/ctrip/apollo/configserver/AllTests.java @@ -1,12 +1,13 @@ package com.ctrip.apollo.configserver; +import com.ctrip.apollo.configserver.controller.ConfigControllerTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) @SuiteClasses({ - +ConfigControllerTest.class }) public class AllTests { diff --git a/apollo-configserver/src/test/java/com/ctrip/apollo/configserver/controller/ConfigControllerTest.java b/apollo-configserver/src/test/java/com/ctrip/apollo/configserver/controller/ConfigControllerTest.java new file mode 100644 index 000000000..89601f7bf --- /dev/null +++ b/apollo-configserver/src/test/java/com/ctrip/apollo/configserver/controller/ConfigControllerTest.java @@ -0,0 +1,111 @@ +package com.ctrip.apollo.configserver.controller; + +import com.ctrip.apollo.biz.entity.Version; +import com.ctrip.apollo.biz.service.ConfigService; +import com.ctrip.apollo.core.model.ApolloConfig; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +import javax.servlet.http.HttpServletResponse; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.*; + +/** + * @author Jason Song(song_s@ctrip.com) + */ +@RunWith(MockitoJUnitRunner.class) +public class ConfigControllerTest { + private ConfigController configController; + @Mock + private ConfigService configService; + + @Before + public void setUp() throws Exception { + configController = new ConfigController(); + ReflectionTestUtils.setField(configController, "configService", configService); + } + + @Test + public void testQueryConfig() throws Exception { + ApolloConfig someApolloConfig = mock(ApolloConfig.class); + long someAppId = 1; + String someClusterName = "someClusterName"; + String someVersionName = "someVersion"; + long someClientSideReleaseId = 1; + long someServerSideNewReleaseId = 2; + HttpServletResponse someResponse = mock(HttpServletResponse.class); + Version someVersion = mock(Version.class); + + when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName)).thenReturn(someVersion); + when(someVersion.getReleaseId()).thenReturn(someServerSideNewReleaseId); + when(configService.loadConfigByVersionAndClusterName(someVersion, someClusterName)).thenReturn(someApolloConfig); + + ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId, someResponse); + + assertEquals(someApolloConfig, result); + verify(configService, times(1)).loadVersionByAppIdAndVersionName(someAppId, someVersionName); + verify(configService, times(1)).loadConfigByVersionAndClusterName(someVersion, someClusterName); + } + + @Test + public void testQueryConfigWithVersionNotFound() throws Exception { + long someAppId = 1; + String someClusterName = "someClusterName"; + String someVersionName = "someVersion"; + long someClientSideReleaseId = 1; + HttpServletResponse someResponse = mock(HttpServletResponse.class); + + when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName)).thenReturn(null); + + ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId, someResponse); + + assertNull(result); + verify(someResponse, times(1)).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString()); + } + + @Test + public void testQueryConfigWithApolloConfigNotFound() throws Exception { + long someAppId = 1; + String someClusterName = "someClusterName"; + String someVersionName = "someVersion"; + long someClientSideReleaseId = 1; + long someServerSideNewReleaseId = 2; + HttpServletResponse someResponse = mock(HttpServletResponse.class); + Version someVersion = mock(Version.class); + + when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName)).thenReturn(someVersion); + when(someVersion.getReleaseId()).thenReturn(someServerSideNewReleaseId); + when(configService.loadConfigByVersionAndClusterName(someVersion, someClusterName)).thenReturn(null); + + ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId, someResponse); + + assertNull(result); + verify(someResponse, times(1)).sendError(eq(HttpServletResponse.SC_NOT_FOUND), anyString()); + } + + @Test + public void testQueryConfigWithApolloConfigNotModified() throws Exception { + long someAppId = 1; + String someClusterName = "someClusterName"; + String someVersionName = "someVersion"; + long someClientSideReleaseId = 1; + long someServerSideReleaseId = someClientSideReleaseId; + HttpServletResponse someResponse = mock(HttpServletResponse.class); + Version someVersion = mock(Version.class); + + when(configService.loadVersionByAppIdAndVersionName(someAppId, someVersionName)).thenReturn(someVersion); + when(someVersion.getReleaseId()).thenReturn(someServerSideReleaseId); + + ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersionName, someClientSideReleaseId, someResponse); + + assertNull(result); + verify(someResponse, times(1)).setStatus(HttpServletResponse.SC_NOT_MODIFIED); + verify(configService, never()).loadConfigByVersionAndClusterName(any(Version.class), anyString()); + } +} diff --git a/apollo-configserver/src/test/java/com/ctrip/apollo/server/AllTests.java b/apollo-configserver/src/test/java/com/ctrip/apollo/server/AllTests.java deleted file mode 100644 index 65c318c54..000000000 --- a/apollo-configserver/src/test/java/com/ctrip/apollo/server/AllTests.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.ctrip.apollo.server; - -import com.ctrip.apollo.server.controller.ConfigControllerTest; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({ -ConfigControllerTest.class -}) -public class AllTests { - -} diff --git a/apollo-configserver/src/test/java/com/ctrip/apollo/server/controller/ConfigControllerTest.java b/apollo-configserver/src/test/java/com/ctrip/apollo/server/controller/ConfigControllerTest.java deleted file mode 100644 index e2655da0a..000000000 --- a/apollo-configserver/src/test/java/com/ctrip/apollo/server/controller/ConfigControllerTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.ctrip.apollo.server.controller; - -import com.ctrip.apollo.biz.service.ConfigService; -import com.ctrip.apollo.core.model.ApolloConfig; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; -import org.springframework.test.util.ReflectionTestUtils; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.*; - -/** - * @author Jason Song(song_s@ctrip.com) - */ -@RunWith(MockitoJUnitRunner.class) -public class ConfigControllerTest { - private ConfigController configController; - @Mock - private ConfigService configService; - - @Before - public void setUp() throws Exception { - configController = new ConfigController(); - ReflectionTestUtils.setField(configController, "configService", configService); - } - - @Test - public void testQueryConfig() throws Exception { - ApolloConfig someApolloConfig = mock(ApolloConfig.class); - long someAppId = 1; - String someClusterName = "someClusterName"; - String someVersion = "someVersion"; - - when(configService.loadConfig(someAppId, someClusterName, someVersion)).thenReturn(someApolloConfig); - - ApolloConfig result = configController.queryConfig(someAppId, someClusterName, someVersion); - - assertEquals(someApolloConfig, result); - verify(configService, times(1)).loadConfig(someAppId, someClusterName, someVersion); - - } -} diff --git a/apollo-demo/src/main/java/com/ctrip/apollo/demo/AppConfig.java b/apollo-demo/src/main/java/com/ctrip/apollo/demo/AppConfig.java index 15b098fc9..0aaa5924b 100644 --- a/apollo-demo/src/main/java/com/ctrip/apollo/demo/AppConfig.java +++ b/apollo-demo/src/main/java/com/ctrip/apollo/demo/AppConfig.java @@ -4,7 +4,6 @@ import com.ctrip.apollo.client.ApolloConfigManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; -import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; /** * @author Jason Song(song_s@ctrip.com) @@ -17,8 +16,13 @@ public class AppConfig { return new ApolloConfigManager(); } - @Bean - public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { - return new PropertySourcesPlaceholderConfigurer(); - } +// @Bean +// public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { +// return new PropertySourcesPlaceholderConfigurer(); +// } +// +// @Bean +// public static RefreshScope refreshScope() { +// return new RefreshScope(); +// } } diff --git a/apollo-demo/src/main/java/com/ctrip/apollo/demo/controller/DemoController.java b/apollo-demo/src/main/java/com/ctrip/apollo/demo/controller/DemoController.java index 2e18907f7..2bc85e89a 100644 --- a/apollo-demo/src/main/java/com/ctrip/apollo/demo/controller/DemoController.java +++ b/apollo-demo/src/main/java/com/ctrip/apollo/demo/controller/DemoController.java @@ -1,11 +1,11 @@ package com.ctrip.apollo.demo.controller; -import com.ctrip.apollo.client.ApolloConfigManager; import com.ctrip.apollo.client.model.ApolloRegistry; import com.ctrip.apollo.client.util.ConfigUtil; import com.ctrip.apollo.demo.model.Config; +import com.ctrip.apollo.demo.service.DemoService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.context.scope.refresh.RefreshScope; import org.springframework.context.annotation.PropertySource; import org.springframework.core.env.Environment; import org.springframework.web.bind.annotation.PathVariable; @@ -26,20 +26,32 @@ public class DemoController { @Autowired private Environment env; @Autowired - private ApolloConfigManager apolloConfigManager; - //Apollo config client internal impl, not intended to be use by application, only for this test page + private DemoService demoService; + //Apollo config client internal impl, not intended to be used by application, only for this test page private ConfigUtil configUtil = ConfigUtil.getInstance(); - @Value("${apollo.foo}") - private String foo; + @Autowired + private RefreshScope scope; @RequestMapping(value = "/config/{configName:.*}", method = RequestMethod.GET) public Config queryConfig(@PathVariable String configName) { - return new Config(configName, env.getProperty(configName, "undefined")); + String value; + if (configName.equals("foo")) { + value = demoService.getFoo(); + } else { + value = env.getProperty(configName, "undefined"); + } + return new Config(configName, value); } @RequestMapping(value = "/client/registries", method = RequestMethod.GET) public List loadApolloRegistries() throws IOException { return configUtil.loadApolloRegistries(); } + + @RequestMapping(value = "/refresh", method = RequestMethod.POST) + public String refreshBeans() { + this.scope.refreshAll(); + return "ok"; + } } diff --git a/apollo-demo/src/main/java/com/ctrip/apollo/demo/service/DemoService.java b/apollo-demo/src/main/java/com/ctrip/apollo/demo/service/DemoService.java new file mode 100644 index 000000000..8bc558a26 --- /dev/null +++ b/apollo-demo/src/main/java/com/ctrip/apollo/demo/service/DemoService.java @@ -0,0 +1,23 @@ +package com.ctrip.apollo.demo.service; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.stereotype.Service; + +/** + * @author Jason Song(song_s@ctrip.com) + */ +@Service +@RefreshScope +public class DemoService { + private String foo; + + @Value("${apollo.foo}") + private void setFoo(String foo) { + this.foo = foo; + } + + public String getFoo() { + return foo; + } +} -- GitLab