Commit 854cec2f authored by Yiming Liu's avatar Yiming Liu

Merge pull request #16 from nobodyiam/apollo_config_server_merge

Config Server to load configurations from db
parents 05d14a21 77ce6722
...@@ -20,3 +20,6 @@ target ...@@ -20,3 +20,6 @@ target
# Idea # Idea
.idea .idea
*.iml *.iml
# git
*.orig
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>apollo</artifactId>
<groupId>com.ctrip.apollo</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apollo-biz</artifactId>
<name>Apollo BizLogic</name>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
package com.ctrip.apollo.biz.entity;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Entity
@Where(clause = "isDeleted = 0")
@SQLDelete(sql = "Update Cluster set isDeleted = 1 where id = ?")
public class Cluster {
@Id
@GeneratedValue
private long id;
private String name;
private long appId;
private boolean isDeleted;
public Cluster() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getAppId() {
return appId;
}
public void setAppId(long appId) {
this.appId = appId;
}
public boolean isDeleted() {
return isDeleted;
}
public void setDeleted(boolean deleted) {
isDeleted = deleted;
}
}
package com.ctrip.apollo.biz.entity;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Entity
@Where(clause = "isDeleted = 0")
@SQLDelete(sql = "Update Release set isDeleted = 1 where id = ?")
public class Release {
@Id
@GeneratedValue
private long id;
private String name;
private long appId;
private String comment;
private boolean isDeleted;
public Release() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getAppId() {
return appId;
}
public void setAppId(long appId) {
this.appId = appId;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public boolean isDeleted() {
return isDeleted;
}
public void setDeleted(boolean deleted) {
isDeleted = deleted;
}
}
package com.ctrip.apollo.biz.entity;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Entity
@Where(clause = "isDeleted = 0")
@SQLDelete(sql = "Update ReleaseSnapShot set isDeleted = 1 where id = ?")
public class ReleaseSnapShot {
@Id
@GeneratedValue
private long id;
private long releaseId;
private String clusterName;
private String configurations;
private boolean isDeleted;
public ReleaseSnapShot() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public long getReleaseId() {
return releaseId;
}
public void setReleaseId(long releaseId) {
this.releaseId = releaseId;
}
public String getClusterName() {
return clusterName;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public String getConfigurations() {
return configurations;
}
public void setConfigurations(String configurations) {
this.configurations = configurations;
}
public boolean isDeleted() {
return isDeleted;
}
public void setDeleted(boolean deleted) {
isDeleted = deleted;
}
}
package com.ctrip.apollo.biz.entity;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Entity
@Where(clause = "isDeleted = 0")
@SQLDelete(sql = "Update Version set isDeleted = 1 where id = ?")
public class Version {
@Id
@GeneratedValue
private long id;
private String name;
private long appId;
private long releaseId;
private long parentVersion;
private boolean isDeleted;
public Version() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getAppId() {
return appId;
}
public void setAppId(long appId) {
this.appId = appId;
}
public long getReleaseId() {
return releaseId;
}
public void setReleaseId(long releaseId) {
this.releaseId = releaseId;
}
public long getParentVersion() {
return parentVersion;
}
public void setParentVersion(long parentVersion) {
this.parentVersion = parentVersion;
}
public boolean isDeleted() {
return isDeleted;
}
public void setDeleted(boolean deleted) {
isDeleted = deleted;
}
}
package com.ctrip.apollo.biz.repository;
import com.ctrip.apollo.biz.entity.ReleaseSnapShot;
import org.springframework.data.repository.PagingAndSortingRepository;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public interface ReleaseSnapShotRepository extends PagingAndSortingRepository<ReleaseSnapShot, Long> {
ReleaseSnapShot findByReleaseIdAndClusterName(long releaseId, String clusterName);
}
package com.ctrip.apollo.biz.repository;
import com.ctrip.apollo.biz.entity.Version;
import org.springframework.data.repository.PagingAndSortingRepository;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public interface VersionRepository extends PagingAndSortingRepository<Version, Long> {
Version findByAppIdAndName(long appId, String name);
}
package com.ctrip.apollo.biz.service;
import com.ctrip.apollo.core.model.ApolloConfig;
/**
* Config Service
* @author Jason Song(song_s@ctrip.com)
*/
public interface ConfigService {
/**
* Load configuration from database
* @param appId
* @param clusterName
* @param versionName
* @return
*/
ApolloConfig loadConfig(long appId, String clusterName, String versionName);
}
package com.ctrip.apollo.biz.service.impl;
import com.ctrip.apollo.biz.entity.ReleaseSnapShot;
import com.ctrip.apollo.biz.entity.Version;
import com.ctrip.apollo.biz.repository.ReleaseSnapShotRepository;
import com.ctrip.apollo.biz.repository.VersionRepository;
import com.ctrip.apollo.biz.service.ConfigService;
import com.ctrip.apollo.core.model.ApolloConfig;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.Map;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Service("configService")
public class ConfigServiceImpl implements ConfigService {
@Autowired
private VersionRepository versionRepository;
@Autowired
private ReleaseSnapShotRepository releaseSnapShotRepository;
@Autowired
private ObjectMapper objectMapper;
private TypeReference<Map<String, Object>> configurationTypeReference =
new TypeReference<Map<String, Object>>() {
};
@Override
public ApolloConfig loadConfig(long appId, String clusterName, String versionName) {
Version version = versionRepository.findByAppIdAndName(appId, versionName);
if (version == null) {
return null;
}
ReleaseSnapShot releaseSnapShot =
releaseSnapShotRepository.findByReleaseIdAndClusterName(version.getReleaseId(), clusterName);
if (releaseSnapShot == null) {
return null;
}
return assembleConfig(version, releaseSnapShot);
}
private ApolloConfig assembleConfig(Version version, ReleaseSnapShot releaseSnapShot) {
ApolloConfig config =
new ApolloConfig(version.getAppId(), releaseSnapShot.getClusterName(), version.getName(), version.getReleaseId());
config.setConfigurations(transformConfigurationToMap(releaseSnapShot.getConfigurations()));
return config;
}
Map<String, Object> transformConfigurationToMap(String configurations) {
try {
return objectMapper.readValue(configurations, configurationTypeReference);
} catch (IOException e) {
e.printStackTrace();
return Maps.newHashMap();
}
}
}
spring.datasource.url = jdbc:h2:file:~/fxapolloconfigdb;mode=mysql
spring.datasource.username = sa
spring.datasource.password =
spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy
INSERT INTO Cluster (AppId, IsDeleted, Name) VALUES (100, 0, 'default');
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"}');
package com.ctrip.apollo.biz;
import com.ctrip.apollo.biz.service.impl.ConfigServiceImplTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({
ConfigServiceImplTest.class
})
public class AllTests {
}
package com.ctrip.apollo.biz.service.impl;
import com.ctrip.apollo.biz.entity.ReleaseSnapShot;
import com.ctrip.apollo.biz.entity.Version;
import com.ctrip.apollo.biz.repository.ReleaseSnapShotRepository;
import com.ctrip.apollo.biz.repository.VersionRepository;
import com.ctrip.apollo.core.model.ApolloConfig;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
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 java.io.IOException;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@RunWith(MockitoJUnitRunner.class)
public class ConfigServiceImplTest {
@Mock
private VersionRepository versionRepository;
@Mock
private ReleaseSnapShotRepository releaseSnapShotRepository;
@Mock
private ObjectMapper objectMapper;
private ConfigServiceImpl configService;
@Before
public void setUp() throws Exception {
configService = new ConfigServiceImpl();
ReflectionTestUtils.setField(configService, "versionRepository", versionRepository);
ReflectionTestUtils.setField(configService, "releaseSnapShotRepository", releaseSnapShotRepository);
ReflectionTestUtils.setField(configService, "objectMapper", objectMapper);
}
@Test
public void testLoadConfig() throws Exception {
long someAppId = 1;
String someClusterName = "someClusterName";
String someVersionName = "someVersionName";
long someReleaseId = 1;
String someValidConfiguration = "{\"apollo.bar\": \"foo\"}";
Version someVersion = assembleVersion(someAppId, someVersionName, someReleaseId);
ReleaseSnapShot someReleaseSnapShot = assembleReleaseSnapShot(someReleaseId, someClusterName, someValidConfiguration);
Map<String, Object> someMap = Maps.newHashMap();
when(versionRepository.findByAppIdAndName(someAppId, someVersionName)).thenReturn(someVersion);
when(releaseSnapShotRepository.findByReleaseIdAndClusterName(someReleaseId, someClusterName)).thenReturn(someReleaseSnapShot);
when(objectMapper.readValue(eq(someValidConfiguration), (TypeReference) anyObject())).thenReturn(someMap);
ApolloConfig result = configService.loadConfig(someAppId, someClusterName, someVersionName);
assertEquals(someAppId, result.getAppId());
assertEquals(someClusterName, result.getCluster());
assertEquals(someVersionName, result.getVersion());
assertEquals(someReleaseId, result.getReleaseId());
assertEquals(someMap, result.getConfigurations());
}
private Version assembleVersion(long appId, String versionName, long releaseId) {
Version version = new Version();
version.setAppId(appId);
version.setName(versionName);
version.setReleaseId(releaseId);
return version;
}
private ReleaseSnapShot assembleReleaseSnapShot(long releaseId, String clusterName, String configurations) {
ReleaseSnapShot releaseSnapShot = new ReleaseSnapShot();
releaseSnapShot.setReleaseId(releaseId);
releaseSnapShot.setClusterName(clusterName);
releaseSnapShot.setConfigurations(configurations);
return releaseSnapShot;
}
@Test
public void testTransformConfigurationToMapSuccessful() throws Exception {
String someValidConfiguration = "{\"apollo.bar\": \"foo\"}";
Map<String, String> someMap = Maps.newHashMap();
when(objectMapper.readValue(eq(someValidConfiguration), (TypeReference) anyObject())).thenReturn(someMap);
Map<String, Object> result = configService.transformConfigurationToMap(someValidConfiguration);
assertEquals(someMap, result);
verify(objectMapper, times(1)).readValue(eq(someValidConfiguration), (TypeReference) anyObject());
}
@Test
public void testTransformConfigurationToMapFailed() throws Exception {
String someInvalidConfiguration = "xxx";
when(objectMapper.readValue(eq(someInvalidConfiguration), (TypeReference) anyObject())).thenThrow(IOException.class);
Map<String, Object> result = configService.transformConfigurationToMap(someInvalidConfiguration);
assertTrue(result.isEmpty());
}
}
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
<artifactId>spring-web</artifactId> <artifactId>spring-web</artifactId>
</dependency> </dependency>
<!-- end of spring --> <!-- end of spring -->
<!-- util -->
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
......
...@@ -20,14 +20,14 @@ import org.springframework.core.env.MutablePropertySources; ...@@ -20,14 +20,14 @@ import org.springframework.core.env.MutablePropertySources;
* *
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
*/ */
public class ApolloConfig implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ApplicationContextAware { public class ApolloConfigManager implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ApplicationContextAware {
public static final String APOLLO_PROPERTY_SOURCE_NAME = "ApolloConfigProperties"; public static final String APOLLO_PROPERTY_SOURCE_NAME = "ApolloConfigProperties";
private ConfigLoader configLoader; private ConfigLoader configLoader;
private ConfigurableApplicationContext applicationContext; private ConfigurableApplicationContext applicationContext;
public ApolloConfig() { public ApolloConfigManager() {
this.configLoader = ConfigLoaderFactory.getInstance().getRemoteConfigLoader(); this.configLoader = ConfigLoaderFactory.getInstance().getRemoteConfigLoader();
} }
......
...@@ -3,8 +3,7 @@ package com.ctrip.apollo.client.loader.impl; ...@@ -3,8 +3,7 @@ package com.ctrip.apollo.client.loader.impl;
import com.ctrip.apollo.client.loader.ConfigLoader; import com.ctrip.apollo.client.loader.ConfigLoader;
import com.ctrip.apollo.client.model.ApolloRegistry; import com.ctrip.apollo.client.model.ApolloRegistry;
import com.ctrip.apollo.client.util.ConfigUtil; import com.ctrip.apollo.client.util.ConfigUtil;
import com.ctrip.apollo.core.environment.Environment; import com.ctrip.apollo.core.model.ApolloConfig;
import com.ctrip.apollo.core.environment.PropertySource;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -77,54 +76,58 @@ public class RemoteConfigLoader implements ConfigLoader { ...@@ -77,54 +76,58 @@ public class RemoteConfigLoader implements ConfigLoader {
} }
void doLoadRemoteApolloConfig(List<ApolloRegistry> apolloRegistries, CompositePropertySource compositePropertySource) throws Throwable { void doLoadRemoteApolloConfig(List<ApolloRegistry> apolloRegistries, CompositePropertySource compositePropertySource) throws Throwable {
List<Future<CompositePropertySource>> futures = Lists.newArrayList(); List<Future<MapPropertySource>> futures = Lists.newArrayList();
for (final ApolloRegistry apolloRegistry : apolloRegistries) { for (final ApolloRegistry apolloRegistry : apolloRegistries) {
futures.add(executorService.submit(new Callable<CompositePropertySource>() { futures.add(executorService.submit(new Callable<MapPropertySource>() {
@Override @Override
public CompositePropertySource call() throws Exception { public MapPropertySource call() throws Exception {
return loadSingleApolloConfig(apolloRegistry.getAppId(), apolloRegistry.getVersion()); return loadSingleApolloConfig(apolloRegistry.getAppId(), apolloRegistry.getVersion());
} }
})); }));
} }
for (Future<CompositePropertySource> future : futures) { for (Future<MapPropertySource> future : futures) {
try { try {
compositePropertySource.addPropertySource(future.get()); MapPropertySource result = future.get();
if (result == null) {
continue;
}
compositePropertySource.addPropertySource(result);
} catch (ExecutionException e) { } catch (ExecutionException e) {
throw e.getCause(); throw e.getCause();
} }
} }
} }
CompositePropertySource loadSingleApolloConfig(String appId, String version) { MapPropertySource loadSingleApolloConfig(long appId, String version) {
CompositePropertySource composite = new CompositePropertySource(appId + "-" + version); ApolloConfig result =
Environment result = this.getRemoteConfig(restTemplate, configUtil.getConfigServerUrl(), appId, configUtil.getCluster(), version);
this.getRemoteEnvironment(restTemplate, configUtil.getConfigServerUrl(), appId, configUtil.getCluster(), version);
if (result == null) { if (result == null) {
logger.error("Loaded environment as null..."); logger.error("Loaded config null...");
return composite; return null;
} }
logger.info("Loaded environment: name={}, cluster={}, label={}, version={}", result.getName(), result.getProfiles(), result.getLabel(), result.getVersion()); logger.info("Loaded config: {}", result);
for (PropertySource source : result.getPropertySources()) { return new MapPropertySource(assemblePropertySourceName(result), result.getConfigurations());
composite.addPropertySource(new MapPropertySource(source.getName(), source.getSource()));
}
return composite;
} }
Environment getRemoteEnvironment(RestTemplate restTemplate, String uri, String name, String cluster, String release) { private String assemblePropertySourceName(ApolloConfig apolloConfig) {
logger.info("Loading environment from {}, name={}, cluster={}, release={}", uri, name, cluster, release); return String.format("%d-%s-%s-%d", apolloConfig.getAppId(), apolloConfig.getCluster(), apolloConfig.getVersion(), apolloConfig.getReleaseId());
String path = "/{name}/{cluster}";
Object[] args = new String[] {name, cluster};
if (StringUtils.hasText(release)) {
args = new String[] {name, cluster, release};
path = path + "/{release}";
} }
ResponseEntity<Environment> response = null;
ApolloConfig getRemoteConfig(RestTemplate restTemplate, String uri, long appId, String cluster, String version) {
logger.info("Loading config from {}, appId={}, cluster={}, version={}", uri, appId, cluster, version);
String path = "/{appId}/{cluster}";
Object[] args = new String[] {String.valueOf(appId), cluster};
if (StringUtils.hasText(version)) {
args = new String[] {String.valueOf(appId), cluster, version};
path = path + "/{version}";
}
ResponseEntity<ApolloConfig> response = null;
try { try {
// TODO retry // TODO retry
response = restTemplate.exchange(uri response = restTemplate.exchange(uri
+ path, HttpMethod.GET, new HttpEntity<Void>((Void) null), Environment.class, args); + path, HttpMethod.GET, new HttpEntity<Void>((Void) null), ApolloConfig.class, args);
} catch (Exception e) { } catch (Exception e) {
throw e; throw e;
} }
...@@ -132,7 +135,7 @@ public class RemoteConfigLoader implements ConfigLoader { ...@@ -132,7 +135,7 @@ public class RemoteConfigLoader implements ConfigLoader {
if (response == null || response.getStatusCode() != HttpStatus.OK) { if (response == null || response.getStatusCode() != HttpStatus.OK) {
return null; return null;
} }
Environment result = response.getBody(); ApolloConfig result = response.getBody();
return result; return result;
} }
......
...@@ -4,19 +4,19 @@ package com.ctrip.apollo.client.model; ...@@ -4,19 +4,19 @@ package com.ctrip.apollo.client.model;
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
*/ */
public class ApolloRegistry { public class ApolloRegistry {
private String appId; private long appId;
private String version; private String version;
public String getAppId() { public long getAppId() {
return appId; return appId;
} }
public String getVersion() { public void setAppId(long appId) {
return version; this.appId = appId;
} }
public void setAppId(String appId) { public String getVersion() {
this.appId = appId; return version;
} }
public void setVersion(String version) { public void setVersion(String version) {
......
package com.ctrip.apollo.client.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class ClassLoaderUtil {
private static final Logger logger = LoggerFactory.getLogger(ClassLoaderUtil.class);
private static ClassLoader loader = Thread.currentThread().getContextClassLoader();
static {
if (loader == null) {
logger.info("Using system class loader");
loader = ClassLoader.getSystemClassLoader();
}
}
public static ClassLoader getLoader() {
return loader;
}
}
...@@ -47,7 +47,7 @@ public class ConfigUtil { ...@@ -47,7 +47,7 @@ public class ConfigUtil {
public List<ApolloRegistry> loadApolloRegistries() throws IOException { public List<ApolloRegistry> loadApolloRegistries() throws IOException {
List<URL> resourceUrls = List<URL> resourceUrls =
Collections.list(Thread.currentThread().getContextClassLoader().getResources(APOLLO_PROPERTY)); Collections.list(ClassLoaderUtil.getLoader().getResources(APOLLO_PROPERTY));
List<ApolloRegistry> registries = List<ApolloRegistry> registries =
FluentIterable.from(resourceUrls).transform(new Function<URL, ApolloRegistry>() { FluentIterable.from(resourceUrls).transform(new Function<URL, ApolloRegistry>() {
@Override @Override
...@@ -57,7 +57,7 @@ public class ConfigUtil { ...@@ -57,7 +57,7 @@ public class ConfigUtil {
return null; return null;
} }
ApolloRegistry registry = new ApolloRegistry(); ApolloRegistry registry = new ApolloRegistry();
registry.setAppId(properties.getProperty(Constants.APP_ID)); registry.setAppId(Long.parseLong(properties.getProperty(Constants.APP_ID)));
registry.setVersion(properties.getProperty(Constants.VERSION, Constants.DEFAULT_VERSION_NAME)); registry.setVersion(properties.getProperty(Constants.VERSION, Constants.DEFAULT_VERSION_NAME));
return registry; return registry;
} }
......
appId=apollo appId=101
version=master version=1.0
...@@ -8,7 +8,7 @@ import org.junit.runners.Suite.SuiteClasses; ...@@ -8,7 +8,7 @@ import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class) @RunWith(Suite.class)
@SuiteClasses({ @SuiteClasses({
ApolloConfigTest.class, RemoteConfigLoaderTest.class, ConfigUtilTest.class ApolloConfigManagerTest.class, RemoteConfigLoaderTest.class, ConfigUtilTest.class
}) })
public class AllTests { public class AllTests {
......
...@@ -14,15 +14,16 @@ import org.springframework.core.env.ConfigurableEnvironment; ...@@ -14,15 +14,16 @@ import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.MutablePropertySources;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
*/ */
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class ApolloConfigTest { public class ApolloConfigManagerTest {
private ApolloConfig apolloConfig; private ApolloConfigManager apolloConfigManager;
@Mock @Mock
private ConfigLoader configLoader; private ConfigLoader configLoader;
@Mock @Mock
...@@ -34,19 +35,19 @@ public class ApolloConfigTest { ...@@ -34,19 +35,19 @@ public class ApolloConfigTest {
@Before @Before
public void setUp() { public void setUp() {
apolloConfig = new ApolloConfig(); apolloConfigManager = new ApolloConfigManager();
when(applicationContext.getEnvironment()).thenReturn(env); when(applicationContext.getEnvironment()).thenReturn(env);
when(env.getPropertySources()).thenReturn(mutablePropertySources); when(env.getPropertySources()).thenReturn(mutablePropertySources);
apolloConfig.setApplicationContext(applicationContext); apolloConfigManager.setApplicationContext(applicationContext);
ReflectionTestUtils.setField(apolloConfig, "configLoader", configLoader); ReflectionTestUtils.setField(apolloConfigManager, "configLoader", configLoader);
} }
@Test(expected = RuntimeException.class) @Test(expected = RuntimeException.class)
public void testInvalidApplicationContext() { public void testInvalidApplicationContext() {
ApplicationContext someInvalidApplication = mock(ApplicationContext.class); ApplicationContext someInvalidApplication = mock(ApplicationContext.class);
apolloConfig.setApplicationContext(someInvalidApplication); apolloConfigManager.setApplicationContext(someInvalidApplication);
} }
@Test @Test
...@@ -56,14 +57,14 @@ public class ApolloConfigTest { ...@@ -56,14 +57,14 @@ public class ApolloConfigTest {
when(configLoader.loadPropertySource()).thenReturn(somePropertySource); when(configLoader.loadPropertySource()).thenReturn(somePropertySource);
apolloConfig.preparePropertySource(); apolloConfigManager.preparePropertySource();
verify(configLoader, times(1)).loadPropertySource(); verify(configLoader, times(1)).loadPropertySource();
verify(mutablePropertySources, times(1)).addFirst(captor.capture()); verify(mutablePropertySources, times(1)).addFirst(captor.capture());
final CompositePropertySource insertedPropertySource = captor.getValue(); final CompositePropertySource insertedPropertySource = captor.getValue();
assertEquals(ApolloConfig.APOLLO_PROPERTY_SOURCE_NAME, insertedPropertySource.getName()); assertEquals(ApolloConfigManager.APOLLO_PROPERTY_SOURCE_NAME, insertedPropertySource.getName());
assertTrue(insertedPropertySource.getPropertySources().contains(somePropertySource)); assertTrue(insertedPropertySource.getPropertySources().contains(somePropertySource));
} }
......
...@@ -2,10 +2,7 @@ package com.ctrip.apollo.client.loader.impl; ...@@ -2,10 +2,7 @@ package com.ctrip.apollo.client.loader.impl;
import com.ctrip.apollo.client.model.ApolloRegistry; import com.ctrip.apollo.client.model.ApolloRegistry;
import com.ctrip.apollo.client.util.ConfigUtil; import com.ctrip.apollo.client.util.ConfigUtil;
import com.ctrip.apollo.core.environment.Environment; import com.ctrip.apollo.core.model.ApolloConfig;
import com.ctrip.apollo.core.environment.PropertySource;
import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import org.junit.Before; import org.junit.Before;
...@@ -14,9 +11,9 @@ import org.junit.runner.RunWith; ...@@ -14,9 +11,9 @@ import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner; import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.MapPropertySource;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import java.util.List;
import java.util.Map; import java.util.Map;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
...@@ -41,10 +38,12 @@ public class RemoteConfigLoaderTest { ...@@ -41,10 +38,12 @@ public class RemoteConfigLoaderTest {
@Test @Test
public void testLoadPropertySource() throws Exception { public void testLoadPropertySource() throws Exception {
ApolloRegistry someApolloRegistry = assembleSomeApolloRegistry("someAppId", "someVersion"); long someAppId = 100;
ApolloRegistry anotherApolloRegistry = assembleSomeApolloRegistry("anotherAppId", "anotherVersion"); long anotherAppId = 101;
CompositePropertySource somePropertySource = mock(CompositePropertySource.class); ApolloRegistry someApolloRegistry = assembleSomeApolloRegistry(someAppId, "someVersion");
CompositePropertySource anotherPropertySource = mock(CompositePropertySource.class); ApolloRegistry anotherApolloRegistry = assembleSomeApolloRegistry(anotherAppId, "anotherVersion");
MapPropertySource somePropertySource = mock(MapPropertySource.class);
MapPropertySource anotherPropertySource = mock(MapPropertySource.class);
doReturn(Lists.newArrayList(someApolloRegistry, anotherApolloRegistry)).when(configUtil).loadApolloRegistries(); doReturn(Lists.newArrayList(someApolloRegistry, anotherApolloRegistry)).when(configUtil).loadApolloRegistries();
doReturn(somePropertySource).when(remoteConfigLoader).loadSingleApolloConfig(someApolloRegistry.getAppId(), someApolloRegistry.getVersion()); doReturn(somePropertySource).when(remoteConfigLoader).loadSingleApolloConfig(someApolloRegistry.getAppId(), someApolloRegistry.getVersion());
...@@ -68,7 +67,8 @@ public class RemoteConfigLoaderTest { ...@@ -68,7 +67,8 @@ public class RemoteConfigLoaderTest {
@Test(expected = RuntimeException.class) @Test(expected = RuntimeException.class)
public void testLoadPropertySourceWithError() throws Exception { public void testLoadPropertySourceWithError() throws Exception {
Exception someException = mock(Exception.class); Exception someException = mock(Exception.class);
ApolloRegistry someApolloRegistry = assembleSomeApolloRegistry("someAppId", "someVersion"); long someAppId = 100;
ApolloRegistry someApolloRegistry = assembleSomeApolloRegistry(someAppId, "someVersion");
doReturn(Lists.newArrayList(someApolloRegistry)).when(configUtil).loadApolloRegistries(); doReturn(Lists.newArrayList(someApolloRegistry)).when(configUtil).loadApolloRegistries();
doThrow(someException).when(remoteConfigLoader).loadSingleApolloConfig(someApolloRegistry.getAppId(), someApolloRegistry.getVersion()); doThrow(someException).when(remoteConfigLoader).loadSingleApolloConfig(someApolloRegistry.getAppId(), someApolloRegistry.getVersion());
...@@ -78,35 +78,19 @@ public class RemoteConfigLoaderTest { ...@@ -78,35 +78,19 @@ public class RemoteConfigLoaderTest {
@Test @Test
public void testLoadSingleApolloConfig() throws Exception { public void testLoadSingleApolloConfig() throws Exception {
Environment someRemoteEnv = mock(Environment.class); ApolloConfig someApolloConfig = mock(ApolloConfig.class);
String someSourceName = "someSource";
String anotherSourceName = "anotherSource";
Map<String, Object> someMap = Maps.newHashMap(); Map<String, Object> someMap = Maps.newHashMap();
PropertySource somePropertySource = mock(PropertySource.class);
PropertySource anotherPropertySource = mock(PropertySource.class);
when(somePropertySource.getSource()).thenReturn(someMap); when(someApolloConfig.getConfigurations()).thenReturn(someMap);
when(somePropertySource.getName()).thenReturn(someSourceName); doReturn(someApolloConfig).when(remoteConfigLoader).getRemoteConfig(any(RestTemplate.class), anyString(), anyLong(), anyString(), anyString());
when(anotherPropertySource.getSource()).thenReturn(someMap);
when(anotherPropertySource.getName()).thenReturn(anotherSourceName);
when(someRemoteEnv.getPropertySources()).thenReturn(Lists.newArrayList(somePropertySource, anotherPropertySource));
doReturn(someRemoteEnv).when(remoteConfigLoader).getRemoteEnvironment(any(RestTemplate.class), anyString(), anyString(), anyString(), anyString());
CompositePropertySource result = remoteConfigLoader.loadSingleApolloConfig("someAppId", "someVersion"); long someAppId = 100;
MapPropertySource result = remoteConfigLoader.loadSingleApolloConfig(someAppId, "someVersion");
assertEquals(2, result.getPropertySources().size()); assertEquals(someMap, result.getSource());
List<String> resultPropertySourceNames = FluentIterable.from(result.getPropertySources()).transform(new Function<org.springframework.core.env.PropertySource<?>, String>() {
@Override
public String apply(org.springframework.core.env.PropertySource<?> input) {
return input.getName();
}
}).toList();
assertTrue(resultPropertySourceNames.containsAll(Lists.newArrayList(someSourceName, anotherSourceName)));
} }
private ApolloRegistry assembleSomeApolloRegistry(String someAppId, String someVersion) { private ApolloRegistry assembleSomeApolloRegistry(long someAppId, String someVersion) {
ApolloRegistry someApolloRegistry = new ApolloRegistry(); ApolloRegistry someApolloRegistry = new ApolloRegistry();
someApolloRegistry.setAppId(someAppId); someApolloRegistry.setAppId(someAppId);
someApolloRegistry.setVersion(someVersion); someApolloRegistry.setVersion(someVersion);
......
...@@ -17,7 +17,8 @@ import java.util.Enumeration; ...@@ -17,7 +17,8 @@ import java.util.Enumeration;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import static org.junit.Assert.*; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
/** /**
...@@ -41,7 +42,7 @@ public class ConfigUtilTest { ...@@ -41,7 +42,7 @@ public class ConfigUtilTest {
Properties someProperties = mock(Properties.class); Properties someProperties = mock(Properties.class);
preparePropertiesFromLocalResource(someProperties); preparePropertiesFromLocalResource(someProperties);
String someAppId = "someApp"; String someAppId = "1";
String someVersionId = "someVersion"; String someVersionId = "someVersion";
when(someProperties.containsKey(Constants.APP_ID)).thenReturn(true); when(someProperties.containsKey(Constants.APP_ID)).thenReturn(true);
...@@ -52,7 +53,7 @@ public class ConfigUtilTest { ...@@ -52,7 +53,7 @@ public class ConfigUtilTest {
ApolloRegistry apolloRegistry = apolloRegistries.get(0); ApolloRegistry apolloRegistry = apolloRegistries.get(0);
assertEquals(1, apolloRegistries.size()); assertEquals(1, apolloRegistries.size());
assertEquals(someAppId, apolloRegistry.getAppId()); assertEquals(Long.parseLong(someAppId), apolloRegistry.getAppId());
assertEquals(someVersionId, apolloRegistry.getVersion()); assertEquals(someVersionId, apolloRegistry.getVersion());
} }
......
...@@ -10,32 +10,52 @@ ...@@ -10,32 +10,52 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>apollo-configserver</artifactId> <artifactId>apollo-configserver</artifactId>
<name>Apollo ConfigServer</name> <name>Apollo ConfigServer</name>
<packaging>war</packaging>
<dependencies> <dependencies>
<!-- apollo -->
<dependency> <dependency>
<groupId>com.ctrip.apollo</groupId> <groupId>com.ctrip.apollo</groupId>
<artifactId>apollo-core</artifactId> <artifactId>apollo-biz</artifactId>
</dependency> </dependency>
<!-- end of apollo -->
<!-- web -->
<dependency> <dependency>
<groupId>org.springframework.cloud</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-cloud-config-server</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.cloud</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId> <artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency> </dependency>
<!-- end of web -->
<!-- redis -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.data</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId> <artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!-- end of redis -->
<!-- eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency> </dependency>
<!-- end of eureka -->
<!-- jsp -->
<dependency> <dependency>
<groupId>com.h2database</groupId> <groupId>javax.servlet</groupId>
<artifactId>h2</artifactId> <artifactId>jstl</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>org.apache.tomcat.embed</groupId>
<artifactId>mysql-connector-java</artifactId> <artifactId>tomcat-embed-jasper</artifactId>
<scope>runtime</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- end of jsp -->
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
......
package com.ctrip.apollo.configserver; package com.ctrip.apollo;
import com.jcraft.jsch.JSch;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.config.server.EnableConfigServer;
/**
* Spring boot application entry point
* @author Jason Song(song_s@ctrip.com)
*/
@SpringBootApplication @SpringBootApplication
@EnableConfigServer
@EnableDiscoveryClient @EnableDiscoveryClient
public class ConfigServerApplication { public class ServerApplication {
public static void main(String[] args) { public static void main(String[] args) {
JSch.setConfig("StrictHostKeyChecking", "no");//for git server key SpringApplication.run(ServerApplication.class, args);
SpringApplication.run(ConfigServerApplication.class, args);
} }
} }
package com.ctrip.apollo;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
/**
* Entry point for traditional web app
* @author Jason Song(song_s@ctrip.com)
*/
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(ServerApplication.class);
}
}
package com.ctrip.apollo.server.config;
import org.h2.server.web.WebServlet;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("welcome");
registry.addViewController("/index").setViewName("welcome");
}
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver
= new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("/");
}
@Bean
ServletRegistrationBean h2servletRegistration(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean( new WebServlet());
registrationBean.addUrlMappings("/console/*");
return registrationBean;
}
}
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);
}
}
spring:
application:
name: apollo-configserver
cloud:
config:
server:
git:
uri: ssh://git@10.3.2.56:1022/spring-cloud-config-repo.git
server: server:
port: 8888 port: 8888
......
spring:
application:
name: apollo-configserver
eureka: eureka:
instance: instance:
hostname: localhost hostname: localhost
......
<!DOCTYPE html>
<%@page contentType="text/html" pageEncoding="UTF-8" %>
<html>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>Apollo Config Server</title>
<body>
<h2>Welcome to Apollo Config Server!</h2>
</body>
</html>
package com.ctrip.apollo.configserver; package com.ctrip.apollo.configserver;
import com.ctrip.apollo.ServerApplication;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ConfigServerApplication.class) @SpringApplicationConfiguration(classes = ServerApplication.class)
public abstract class AbstractConfigServerTest { public abstract class AbstractConfigServerTest {
} }
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 {
}
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);
}
}
...@@ -23,5 +23,11 @@ ...@@ -23,5 +23,11 @@
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
</dependency> </dependency>
<!-- end of json --> <!-- end of json -->
<!-- util -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<!-- end of util -->
</dependencies> </dependencies>
</project> </project>
package com.ctrip.apollo.core.environment;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class Environment {
private String name;
private String[] profiles = new String[0];
private String label;
private List<PropertySource> propertySources = new ArrayList<PropertySource>();
private String version;
public Environment(String name, String... profiles) {
this(name, profiles, "master", null);
}
@JsonCreator
public Environment(@JsonProperty("name") String name,
@JsonProperty("profiles") String[] profiles,
@JsonProperty("label") String label,
@JsonProperty("version") String version) {
super();
this.name = name;
this.profiles = profiles;
this.label = label;
this.version = version;
}
public void add(PropertySource propertySource) {
this.propertySources.add(propertySource);
}
public void addFirst(PropertySource propertySource) {
this.propertySources.add(0, propertySource);
}
public List<PropertySource> getPropertySources() {
return propertySources;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String[] getProfiles() {
return profiles;
}
public void setProfiles(String[] profiles) {
this.profiles = profiles;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
@Override
public String toString() {
return "Environment [name=" + name + ", profiles=" + Arrays.asList(profiles) + ", label="
+ label + ", propertySources=" + propertySources + ", version=" + version + "]";
}
}
package com.ctrip.apollo.core.environment;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Map;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class PropertySource {
private String name;
private Map<String, Object> source;
@JsonCreator
public PropertySource(@JsonProperty("name") String name, @JsonProperty("source") Map<String, Object> source) {
this.name = name;
this.source = source;
}
public String getName() {
return name;
}
public Map<String, Object> getSource() {
return source;
}
@Override
public String toString() {
return "PropertySource [name=" + name + "]";
}
}
package com.ctrip.apollo.core.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.MoreObjects;
import java.util.Map;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class ApolloConfig {
private long appId;
private String cluster;
private String version;
private Map<String, Object> configurations;
private long releaseId;
@JsonCreator
public ApolloConfig(@JsonProperty("appId") long appId,
@JsonProperty("cluster") String cluster,
@JsonProperty("version") String version,
@JsonProperty("releaseId") long releaseId) {
super();
this.appId = appId;
this.cluster = cluster;
this.version = version;
this.releaseId = releaseId;
}
public Map<String, Object> getConfigurations() {
return configurations;
}
public void setConfigurations(Map<String, Object> configurations) {
this.configurations = configurations;
}
public long getAppId() {
return appId;
}
public String getCluster() {
return cluster;
}
public String getVersion() {
return version;
}
public long getReleaseId() {
return releaseId;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.omitNullValues()
.add("appId", appId)
.add("cluster", cluster)
.add("version", version)
.add("releaseId", releaseId)
.add("configurations", configurations)
.toString();
}
}
package com.ctrip.apollo.demo; package com.ctrip.apollo.demo;
import com.ctrip.apollo.client.ApolloConfig; import com.ctrip.apollo.client.ApolloConfigManager;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -13,8 +13,8 @@ import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; ...@@ -13,8 +13,8 @@ import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
@ComponentScan(value = "com.ctrip.apollo.demo") @ComponentScan(value = "com.ctrip.apollo.demo")
public class AppConfig { public class AppConfig {
@Bean @Bean
public ApolloConfig apolloConfig() { public ApolloConfigManager apolloConfigManager() {
return new ApolloConfig(); return new ApolloConfigManager();
} }
@Bean @Bean
......
appId=hermes appId=102
version=master version=1.0
...@@ -71,6 +71,7 @@ ...@@ -71,6 +71,7 @@
<module>apollo-portal</module> <module>apollo-portal</module>
<module>apollo-assembly</module> <module>apollo-assembly</module>
<module>apollo-demo</module> <module>apollo-demo</module>
<module>apollo-biz</module>
</modules> </modules>
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
...@@ -79,6 +80,11 @@ ...@@ -79,6 +80,11 @@
<artifactId>apollo-core</artifactId> <artifactId>apollo-core</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo-biz</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.dianping.cat</groupId> <groupId>com.dianping.cat</groupId>
<artifactId>cat-client</artifactId> <artifactId>cat-client</artifactId>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment