提交 f5d513fb 编写于 作者: J Jason Song

Use HttpURLConnection and gson to remove Spring and Jackson dependencies

上级 76528a11
package com.ctrip.apollo.biz.service; package com.ctrip.apollo.biz.service;
import java.io.IOException; import com.google.common.collect.Maps;
import java.util.Map; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ctrip.apollo.biz.entity.Release; import com.ctrip.apollo.biz.entity.Release;
import com.ctrip.apollo.biz.repository.ReleaseRepository; import com.ctrip.apollo.biz.repository.ReleaseRepository;
import com.ctrip.apollo.core.dto.ApolloConfig; import com.ctrip.apollo.core.dto.ApolloConfig;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired;
import com.google.common.collect.Maps; import org.springframework.stereotype.Service;
import java.lang.reflect.Type;
import java.util.Map;
/** /**
* Config Service * Config Service
...@@ -24,10 +25,9 @@ public class ConfigService { ...@@ -24,10 +25,9 @@ public class ConfigService {
@Autowired @Autowired
private ReleaseRepository releaseRepository; private ReleaseRepository releaseRepository;
private ObjectMapper objectMapper = new ObjectMapper(); private Gson gson = new Gson();
private TypeReference<Map<String, String>> configurationTypeReference = private Type configurationTypeReference = new TypeToken<Map<String, String>>(){}.getType();
new TypeReference<Map<String, String>>() {};
public Release findRelease(String appId, String clusterName, String namespaceName) { public Release findRelease(String appId, String clusterName, String namespaceName) {
Release release = releaseRepository.findLatest(appId, clusterName, namespaceName); Release release = releaseRepository.findLatest(appId, clusterName, namespaceName);
...@@ -49,8 +49,8 @@ public class ConfigService { ...@@ -49,8 +49,8 @@ public class ConfigService {
Map<String, String> transformConfigurationToMap(String configurations) { Map<String, String> transformConfigurationToMap(String configurations) {
try { try {
return objectMapper.readValue(configurations, configurationTypeReference); return gson.fromJson(configurations, configurationTypeReference);
} catch (IOException e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
return Maps.newHashMap(); return Maps.newHashMap();
} }
......
package com.ctrip.apollo.biz.service; package com.ctrip.apollo.biz.service;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.ctrip.apollo.biz.entity.Release; import com.ctrip.apollo.biz.entity.Release;
import com.ctrip.apollo.biz.repository.ReleaseRepository; import com.ctrip.apollo.biz.repository.ReleaseRepository;
import com.ctrip.apollo.biz.service.ConfigService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
...@@ -14,16 +12,10 @@ import org.mockito.Mock; ...@@ -14,16 +12,10 @@ import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner; import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import java.io.IOException;
import java.util.Map; import java.util.Map;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.anyObject;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
...@@ -32,8 +24,6 @@ import static org.mockito.Mockito.when; ...@@ -32,8 +24,6 @@ import static org.mockito.Mockito.when;
public class ConfigServiceTest { public class ConfigServiceTest {
@Mock @Mock
private ReleaseRepository releaseRepository; private ReleaseRepository releaseRepository;
@Mock
private ObjectMapper objectMapper;
private ConfigService configService; private ConfigService configService;
@Before @Before
...@@ -41,7 +31,6 @@ public class ConfigServiceTest { ...@@ -41,7 +31,6 @@ public class ConfigServiceTest {
configService = new ConfigService(); configService = new ConfigService();
ReflectionTestUtils ReflectionTestUtils
.setField(configService, "releaseRepository", releaseRepository); .setField(configService, "releaseRepository", releaseRepository);
ReflectionTestUtils.setField(configService, "objectMapper", objectMapper);
} }
// @Test // @Test
...@@ -131,21 +120,16 @@ public class ConfigServiceTest { ...@@ -131,21 +120,16 @@ public class ConfigServiceTest {
public void testTransformConfigurationToMapSuccessful() throws Exception { public void testTransformConfigurationToMapSuccessful() throws Exception {
String someValidConfiguration = "{\"apollo.bar\": \"foo\"}"; String someValidConfiguration = "{\"apollo.bar\": \"foo\"}";
Map<String, String> someMap = Maps.newHashMap(); Map<String, String> someMap = Maps.newHashMap();
when(objectMapper.readValue(eq(someValidConfiguration), (TypeReference) anyObject())) someMap.put("apollo.bar", "foo");
.thenReturn(someMap);
Map<String, String> result = configService.transformConfigurationToMap(someValidConfiguration); Map<String, String> result = configService.transformConfigurationToMap(someValidConfiguration);
assertEquals(someMap, result); assertEquals(someMap, result);
verify(objectMapper, times(1))
.readValue(eq(someValidConfiguration), (TypeReference) anyObject());
} }
@Test @Test
public void testTransformConfigurationToMapFailed() throws Exception { public void testTransformConfigurationToMapFailed() throws Exception {
String someInvalidConfiguration = "xxx"; String someInvalidConfiguration = "xxx";
when(objectMapper.readValue(eq(someInvalidConfiguration), (TypeReference) anyObject()))
.thenThrow(IOException.class);
Map<String, String> Map<String, String>
result = result =
......
...@@ -24,38 +24,29 @@ ...@@ -24,38 +24,29 @@
<groupId>com.dianping.cat</groupId> <groupId>com.dianping.cat</groupId>
<artifactId>cat-client</artifactId> <artifactId>cat-client</artifactId>
</dependency> </dependency>
<!-- spring -->
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.slf4j</groupId>
<artifactId>spring-web</artifactId> <artifactId>slf4j-api</artifactId>
</dependency>
<!-- end of spring -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<!-- end of util -->
<!-- test -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId> <artifactId>log4j-slf4j-impl</artifactId>
<scope>test</scope> <exclusions>
</dependency> <exclusion>
<dependency> <groupId>org.slf4j</groupId>
<groupId>org.apache.logging.log4j</groupId> <artifactId>slf4j-api</artifactId>
<artifactId>log4j-api</artifactId> </exclusion>
<scope>test</scope> <exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</exclusion>
</exclusions>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId> <artifactId>log4j-core</artifactId>
<scope>test</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- end of test -->
</dependencies> </dependencies>
</project> </project>
package com.ctrip.apollo.build; package com.ctrip.apollo.build;
import com.ctrip.apollo.internals.ConfigServiceLocator;
import com.ctrip.apollo.internals.DefaultConfigManager; import com.ctrip.apollo.internals.DefaultConfigManager;
import com.ctrip.apollo.spi.DefaultConfigFactory; import com.ctrip.apollo.spi.DefaultConfigFactory;
import com.ctrip.apollo.spi.DefaultConfigFactoryManager; import com.ctrip.apollo.spi.DefaultConfigFactoryManager;
import com.ctrip.apollo.spi.DefaultConfigRegistry; import com.ctrip.apollo.spi.DefaultConfigRegistry;
import com.ctrip.apollo.util.ConfigUtil;
import com.ctrip.apollo.util.http.HttpUtil;
import org.unidal.lookup.configuration.AbstractResourceConfigurator; import org.unidal.lookup.configuration.AbstractResourceConfigurator;
import org.unidal.lookup.configuration.Component; import org.unidal.lookup.configuration.Component;
...@@ -27,6 +30,9 @@ public class ComponentConfigurator extends AbstractResourceConfigurator { ...@@ -27,6 +30,9 @@ public class ComponentConfigurator extends AbstractResourceConfigurator {
all.add(A(DefaultConfigFactory.class)); all.add(A(DefaultConfigFactory.class));
all.add(A(DefaultConfigRegistry.class)); all.add(A(DefaultConfigRegistry.class));
all.add(A(DefaultConfigFactoryManager.class)); all.add(A(DefaultConfigFactoryManager.class));
all.add(A(ConfigUtil.class));
all.add(A(ConfigServiceLocator.class));
all.add(A(HttpUtil.class));
return all; return all;
} }
......
...@@ -2,38 +2,46 @@ package com.ctrip.apollo.internals; ...@@ -2,38 +2,46 @@ package com.ctrip.apollo.internals;
import com.ctrip.apollo.core.dto.ServiceDTO; import com.ctrip.apollo.core.dto.ServiceDTO;
import com.ctrip.apollo.env.ClientEnvironment; import com.ctrip.apollo.env.ClientEnvironment;
import com.ctrip.apollo.util.http.HttpRequest;
import com.ctrip.apollo.util.http.HttpResponse;
import com.ctrip.apollo.util.http.HttpUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.web.client.RestTemplate; import org.unidal.lookup.annotation.Inject;
import org.unidal.lookup.annotation.Named;
import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@Named(type = ConfigServiceLocator.class)
public class ConfigServiceLocator { public class ConfigServiceLocator {
private static final Logger logger = LoggerFactory.getLogger(ConfigServiceLocator.class); private static final Logger logger = LoggerFactory.getLogger(ConfigServiceLocator.class);
@Inject
private RestTemplate restTemplate = new RestTemplate(); private HttpUtil m_httpUtil;
private List<ServiceDTO> serviceCaches = new ArrayList<>(); private List<ServiceDTO> serviceCaches = new ArrayList<>();
public List<ServiceDTO> getConfigServices() { public List<ServiceDTO> getConfigServices() {
ClientEnvironment env = ClientEnvironment.getInstance(); ClientEnvironment env = ClientEnvironment.getInstance();
String domainName = env.getMetaServerDomainName(); String domainName = env.getMetaServerDomainName();
String url = domainName + "/services/config"; String url = domainName + "/services/config";
HttpRequest request = new HttpRequest(url);
try { try {
ServiceDTO[] services = restTemplate.getForObject(new URI(url), ServiceDTO[].class); HttpResponse<ServiceDTO[]> response = m_httpUtil.doGet(request, ServiceDTO[].class);
ServiceDTO[] services = response.getBody();
if (services != null && services.length > 0) { if (services != null && services.length > 0) {
serviceCaches.clear(); serviceCaches.clear();
for (ServiceDTO service : services) { for (ServiceDTO service : services) {
serviceCaches.add(service); serviceCaches.add(service);
} }
} }
} catch (Exception ex) { } catch (Throwable t) {
logger.warn(ex.getMessage()); logger.error("Get config services failed", t);
throw new RuntimeException("Get config services failed", t);
} }
return serviceCaches; return serviceCaches;
} }
} }
...@@ -4,6 +4,9 @@ import com.ctrip.apollo.Config; ...@@ -4,6 +4,9 @@ import com.ctrip.apollo.Config;
import com.ctrip.apollo.core.utils.ClassLoaderUtil; import com.ctrip.apollo.core.utils.ClassLoaderUtil;
import com.dianping.cat.Cat; import com.dianping.cat.Cat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Properties; import java.util.Properties;
...@@ -12,6 +15,7 @@ import java.util.Properties; ...@@ -12,6 +15,7 @@ import java.util.Properties;
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
*/ */
public class DefaultConfig implements Config { public class DefaultConfig implements Config {
private static final Logger logger = LoggerFactory.getLogger(DefaultConfig.class);
private final String m_namespace; private final String m_namespace;
private Properties m_resourceProperties; private Properties m_resourceProperties;
private Properties m_configProperties; private Properties m_configProperties;
...@@ -28,9 +32,10 @@ public class DefaultConfig implements Config { ...@@ -28,9 +32,10 @@ public class DefaultConfig implements Config {
try { try {
m_configProperties = m_configRepository.loadConfig(); m_configProperties = m_configRepository.loadConfig();
} catch (Throwable ex) { } catch (Throwable ex) {
throw new RuntimeException( String message = String.format("Init Apollo Local Config failed - namespace: %s",
String.format("Init Apollo Local Config failed - namespace: %s", m_namespace);
m_namespace), ex); logger.error(message, ex);
throw new RuntimeException(message, ex);
} }
} }
...@@ -74,6 +79,7 @@ public class DefaultConfig implements Config { ...@@ -74,6 +79,7 @@ public class DefaultConfig implements Config {
try { try {
properties.load(in); properties.load(in);
} catch (IOException e) { } catch (IOException e) {
logger.error("Load resource config for namespace {} failed", namespace, e);
Cat.logError(e); Cat.logError(e);
} finally { } finally {
try { try {
......
...@@ -5,9 +5,14 @@ import com.google.common.base.Preconditions; ...@@ -5,9 +5,14 @@ import com.google.common.base.Preconditions;
import com.ctrip.apollo.util.ConfigUtil; import com.ctrip.apollo.util.ConfigUtil;
import com.dianping.cat.Cat; import com.dianping.cat.Cat;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.unidal.lookup.ContainerLoader;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
...@@ -18,16 +23,23 @@ import java.util.Properties; ...@@ -18,16 +23,23 @@ import java.util.Properties;
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
*/ */
public class LocalFileConfigRepository implements ConfigRepository { public class LocalFileConfigRepository implements ConfigRepository {
private static final Logger logger = LoggerFactory.getLogger(LocalFileConfigRepository.class);
private PlexusContainer m_container;
private final String m_namespace; private final String m_namespace;
private final File m_baseDir; private final File m_baseDir;
private final ConfigUtil m_configUtil; private final ConfigUtil m_configUtil;
private Properties m_fileProperties; private Properties m_fileProperties;
private ConfigRepository m_fallback; private ConfigRepository m_fallback;
public LocalFileConfigRepository(File baseDir, String namespace, ConfigUtil configUtil) { public LocalFileConfigRepository(File baseDir, String namespace) {
m_baseDir = baseDir; m_baseDir = baseDir;
m_namespace = namespace; m_namespace = namespace;
m_configUtil = configUtil; m_container = ContainerLoader.getDefaultContainer();
try {
m_configUtil = m_container.lookup(ConfigUtil.class);
} catch (ComponentLookupException e) {
throw new IllegalStateException("Unable to load component!", e);
}
} }
@Override @Override
...@@ -53,6 +65,7 @@ public class LocalFileConfigRepository implements ConfigRepository { ...@@ -53,6 +65,7 @@ public class LocalFileConfigRepository implements ConfigRepository {
persistLocalCacheFile(m_baseDir, m_namespace); persistLocalCacheFile(m_baseDir, m_namespace);
return; return;
} catch (Throwable ex) { } catch (Throwable ex) {
logger.error("Load config from fallback loader failed", ex);
Cat.logError(ex); Cat.logError(ex);
} }
} }
...@@ -79,6 +92,7 @@ public class LocalFileConfigRepository implements ConfigRepository { ...@@ -79,6 +92,7 @@ public class LocalFileConfigRepository implements ConfigRepository {
properties = new Properties(); properties = new Properties();
properties.load(in); properties.load(in);
} catch (IOException e) { } catch (IOException e) {
logger.error("Loading config from local cache file {} failed", file.getAbsolutePath(), e);
Cat.logError(e); Cat.logError(e);
throw e; throw e;
} finally { } finally {
...@@ -91,7 +105,10 @@ public class LocalFileConfigRepository implements ConfigRepository { ...@@ -91,7 +105,10 @@ public class LocalFileConfigRepository implements ConfigRepository {
} }
} }
} else { } else {
//TODO error handling String message =
String.format("Cannot read from local cache file %s", file.getAbsolutePath());
logger.error(message);
throw new RuntimeException(message);
} }
return properties; return properties;
...@@ -108,9 +125,8 @@ public class LocalFileConfigRepository implements ConfigRepository { ...@@ -108,9 +125,8 @@ public class LocalFileConfigRepository implements ConfigRepository {
try { try {
out = new FileOutputStream(file); out = new FileOutputStream(file);
m_fileProperties.store(out, "Persisted by DefaultConfig"); m_fileProperties.store(out, "Persisted by DefaultConfig");
} catch (FileNotFoundException ex) {
Cat.logError(ex);
} catch (IOException ex) { } catch (IOException ex) {
logger.error("Persist local cache file {} failed", file.getAbsolutePath(), ex);
Cat.logError(ex); Cat.logError(ex);
} finally { } finally {
if (out != null) { if (out != null) {
......
package com.ctrip.apollo.internals; package com.ctrip.apollo.internals;
import com.google.common.collect.Maps; import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.ctrip.apollo.core.dto.ApolloConfig; import com.ctrip.apollo.core.dto.ApolloConfig;
import com.ctrip.apollo.core.dto.ServiceDTO; import com.ctrip.apollo.core.dto.ServiceDTO;
import com.ctrip.apollo.util.ConfigUtil; import com.ctrip.apollo.util.ConfigUtil;
import com.ctrip.apollo.util.http.HttpRequest;
import com.ctrip.apollo.util.http.HttpResponse;
import com.ctrip.apollo.util.http.HttpUtil;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity; import org.unidal.lookup.ContainerLoader;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.atomic.AtomicReference;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
*/ */
public class RemoteConfigRepository implements ConfigRepository { public class RemoteConfigRepository implements ConfigRepository {
private static final Logger logger = LoggerFactory.getLogger(RemoteConfigRepository.class); private static final Logger logger = LoggerFactory.getLogger(RemoteConfigRepository.class);
private RestTemplate m_restTemplate; private PlexusContainer m_container;
private ConfigServiceLocator m_serviceLocator; private ConfigServiceLocator m_serviceLocator;
private HttpUtil m_httpUtil;
private ConfigUtil m_configUtil; private ConfigUtil m_configUtil;
private Properties m_remoteProperties; private AtomicReference<ApolloConfig> m_configCache;
private String m_namespace; private String m_namespace;
public RemoteConfigRepository(RestTemplate restTemplate, public RemoteConfigRepository(String namespace) {
ConfigServiceLocator serviceLocator,
ConfigUtil configUtil, String namespace) {
m_restTemplate = restTemplate;
m_serviceLocator = serviceLocator;
m_configUtil = configUtil;
m_namespace = namespace; m_namespace = namespace;
m_configCache = new AtomicReference<>();
m_container = ContainerLoader.getDefaultContainer();
try {
m_configUtil = m_container.lookup(ConfigUtil.class);
m_httpUtil = m_container.lookup(HttpUtil.class);
m_serviceLocator = m_container.lookup(ConfigServiceLocator.class);
} catch (ComponentLookupException e) {
throw new IllegalStateException("Unable to load component!", e);
}
} }
@Override @Override
public Properties loadConfig() { public Properties loadConfig() {
if (m_remoteProperties == null) { if (m_configCache.get() == null) {
initRemoteConfig(); initRemoteConfig();
} }
Properties result = new Properties(); return transformApolloConfigToProperties(m_configCache.get());
result.putAll(m_remoteProperties);
return result;
} }
@Override @Override
...@@ -55,79 +59,60 @@ public class RemoteConfigRepository implements ConfigRepository { ...@@ -55,79 +59,60 @@ public class RemoteConfigRepository implements ConfigRepository {
} }
private void initRemoteConfig() { private void initRemoteConfig() {
ApolloConfig apolloConfig = this.loadApolloConfig(); m_configCache.set(this.loadApolloConfig());
m_remoteProperties = new Properties(); }
m_remoteProperties.putAll(apolloConfig.getConfigurations());
private Properties transformApolloConfigToProperties(ApolloConfig apolloConfig) {
Properties result = new Properties();
result.putAll(apolloConfig.getConfigurations());
return result;
} }
private ApolloConfig loadApolloConfig() { private ApolloConfig loadApolloConfig() {
String appId = m_configUtil.getAppId(); String appId = m_configUtil.getAppId();
String cluster = m_configUtil.getCluster(); String cluster = m_configUtil.getCluster();
String uri = getConfigServiceUrl();
logger.info("Loading config from {}, appId={}, cluster={}, namespace={}", uri, appId, cluster,
m_namespace);
HttpRequest request =
new HttpRequest(assembleUrl(uri, appId, cluster, m_namespace, m_configCache.get()));
try { try {
ApolloConfig result = HttpResponse<ApolloConfig> response = m_httpUtil.doGet(request, ApolloConfig.class);
this.getRemoteConfig(m_restTemplate, getConfigServiceUrl(), if (response.getStatusCode() == 304) {
appId, cluster, return m_configCache.get();
m_namespace,
null);
if (result == null) {
return null;
} }
logger.info("Loaded config: {}", result);
return result; logger.info("Loaded config: {}", response.getBody());
} catch (Throwable ex) {
throw new RuntimeException( return response.getBody();
} catch (Throwable t) {
String message =
String.format("Load Apollo Config failed - appId: %s, cluster: %s, namespace: %s", appId, String.format("Load Apollo Config failed - appId: %s, cluster: %s, namespace: %s", appId,
cluster, m_namespace), ex); cluster, m_namespace);
logger.error(message, t);
throw new RuntimeException(message, t);
} }
} }
private String assembleUrl(String uri, String appId, String cluster, String namespace,
ApolloConfig previousConfig) {
String path = "/config/%s/%s";
List<String> params = Lists.newArrayList(appId, cluster);
private ApolloConfig getRemoteConfig(RestTemplate restTemplate, String uri, if (!Strings.isNullOrEmpty(namespace)) {
String appId, String cluster, String namespace, path = path + "/%s";
ApolloConfig previousConfig) { params.add(namespace);
logger.info("Loading config from {}, appId={}, cluster={}, namespace={}", uri, appId, cluster,
namespace);
String path = "/config/{appId}/{cluster}";
Map<String, Object> paramMap = Maps.newHashMap();
paramMap.put("appId", appId);
paramMap.put("cluster", cluster);
if (StringUtils.hasText(namespace)) {
path = path + "/{namespace}";
paramMap.put("namespace", namespace);
} }
if (previousConfig != null) { if (previousConfig != null) {
path = path + "?releaseId={releaseId}"; path = path + "?releaseId=%s";
paramMap.put("releaseId", previousConfig.getReleaseId()); params.add(String.valueOf(previousConfig.getReleaseId()));
} }
ResponseEntity<ApolloConfig> response; String pathExpanded = String.format(path, params.toArray());
return uri + pathExpanded;
try {
// TODO retry
response = restTemplate.exchange(uri
+ path, HttpMethod.GET, new HttpEntity<Void>((Void) null), ApolloConfig.class, paramMap);
} catch (Throwable ex) {
throw ex;
}
if (response == null) {
throw new RuntimeException("Load apollo config failed, response is null");
}
if (response.getStatusCode() == HttpStatus.NOT_MODIFIED) {
return null;
}
if (response.getStatusCode() != HttpStatus.OK) {
throw new RuntimeException(
String.format("Load apollo config failed, response status %s", response.getStatusCode()));
}
ApolloConfig result = response.getBody();
return result;
} }
private String getConfigServiceUrl() { private String getConfigServiceUrl() {
......
...@@ -2,12 +2,16 @@ package com.ctrip.apollo.internals; ...@@ -2,12 +2,16 @@ package com.ctrip.apollo.internals;
import com.ctrip.apollo.Config; import com.ctrip.apollo.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Properties; import java.util.Properties;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
*/ */
public class SimpleConfig implements Config { public class SimpleConfig implements Config {
private static final Logger logger = LoggerFactory.getLogger(SimpleConfig.class);
private String m_namespace; private String m_namespace;
private ConfigRepository m_configRepository; private ConfigRepository m_configRepository;
private Properties m_configProperties; private Properties m_configProperties;
...@@ -22,9 +26,10 @@ public class SimpleConfig implements Config { ...@@ -22,9 +26,10 @@ public class SimpleConfig implements Config {
try { try {
m_configProperties = m_configRepository.loadConfig(); m_configProperties = m_configRepository.loadConfig();
} catch (Throwable ex) { } catch (Throwable ex) {
throw new RuntimeException( String message = String.format("Init Apollo Remote Config failed - namespace: %s",
String.format("Init Apollo Remote Config failed - namespace: %s", m_namespace);
m_namespace), ex); logger.error(message, ex);
throw new RuntimeException(message, ex);
} }
} }
......
...@@ -2,11 +2,10 @@ package com.ctrip.apollo.spi; ...@@ -2,11 +2,10 @@ package com.ctrip.apollo.spi;
import com.ctrip.apollo.Config; import com.ctrip.apollo.Config;
import com.ctrip.apollo.core.utils.ClassLoaderUtil; import com.ctrip.apollo.core.utils.ClassLoaderUtil;
import com.ctrip.apollo.internals.*; import com.ctrip.apollo.internals.DefaultConfig;
import com.ctrip.apollo.internals.LocalFileConfigRepository;
import com.ctrip.apollo.internals.RemoteConfigRepository; import com.ctrip.apollo.internals.RemoteConfigRepository;
import com.ctrip.apollo.util.ConfigUtil;
import org.springframework.web.client.RestTemplate;
import org.unidal.lookup.annotation.Named; import org.unidal.lookup.annotation.Named;
import java.io.File; import java.io.File;
...@@ -28,20 +27,20 @@ public class DefaultConfigFactory implements ConfigFactory { ...@@ -28,20 +27,20 @@ public class DefaultConfigFactory implements ConfigFactory {
@Override @Override
public Config create(String namespace) { public Config create(String namespace) {
DefaultConfig defaultConfig = new DefaultConfig(namespace, createLocalConfigRepository(namespace)); DefaultConfig defaultConfig =
new DefaultConfig(namespace, createLocalConfigRepository(namespace));
return defaultConfig; return defaultConfig;
} }
LocalFileConfigRepository createLocalConfigRepository(String namespace) { LocalFileConfigRepository createLocalConfigRepository(String namespace) {
LocalFileConfigRepository LocalFileConfigRepository
localFileConfigLoader = localFileConfigLoader =
new LocalFileConfigRepository(m_baseDir, namespace, ConfigUtil.getInstance()); new LocalFileConfigRepository(m_baseDir, namespace);
localFileConfigLoader.setFallback(createRemoteConfigRepository(namespace)); localFileConfigLoader.setFallback(createRemoteConfigRepository(namespace));
return localFileConfigLoader; return localFileConfigLoader;
} }
RemoteConfigRepository createRemoteConfigRepository(String namespace) { RemoteConfigRepository createRemoteConfigRepository(String namespace) {
return new RemoteConfigRepository(new RestTemplate(), new ConfigServiceLocator(), return new RemoteConfigRepository(namespace);
ConfigUtil.getInstance(), namespace);
} }
} }
package com.ctrip.apollo.util; package com.ctrip.apollo.util;
import org.slf4j.Logger; import org.unidal.lookup.annotation.Named;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
* @author Jason Song(song_s@ctrip.com) * @author Jason Song(song_s@ctrip.com)
*/ */
@Named(type = ConfigUtil.class)
public class ConfigUtil { public class ConfigUtil {
//TODO read from config? //TODO read from config?
private static final int refreshInterval = 5; private static final int refreshInterval = 5;
private static final TimeUnit refreshIntervalTimeUnit = TimeUnit.MINUTES; private static final TimeUnit refreshIntervalTimeUnit = TimeUnit.MINUTES;
private static final int connectTimeout = 5000; //5 seconds
private static ConfigUtil configUtil = new ConfigUtil(); private static final int readTimeout = 10000; //10 seconds
private ConfigUtil() {
}
public static ConfigUtil getInstance() {
return configUtil;
}
public String getAppId() { public String getAppId() {
// TODO return the actual app id // TODO return the actual app id
...@@ -36,6 +25,14 @@ public class ConfigUtil { ...@@ -36,6 +25,14 @@ public class ConfigUtil {
return "default"; return "default";
} }
public int getConnectTimeout() {
return connectTimeout;
}
public int getReadTimeout() {
return readTimeout;
}
public int getRefreshInterval() { public int getRefreshInterval() {
return refreshInterval; return refreshInterval;
} }
......
package com.ctrip.apollo.util.http;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class HttpRequest {
private String m_url;
private int m_connectTimeout;
private int m_readTimeout;
public HttpRequest(String url) {
this.m_url = url;
m_connectTimeout = -1;
m_readTimeout = -1;
}
public String getUrl() {
return m_url;
}
public int getConnectTimeout() {
return m_connectTimeout;
}
public void setConnectTimeout(int connectTimeout) {
this.m_connectTimeout = connectTimeout;
}
public int getReadTimeout() {
return m_readTimeout;
}
public void setReadTimeout(int readTimeout) {
this.m_readTimeout = readTimeout;
}
}
package com.ctrip.apollo.util.http;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class HttpResponse<T> {
private final int m_statusCode;
private final T m_body;
public HttpResponse(int statusCode, T body) {
this.m_statusCode = statusCode;
this.m_body = body;
}
public int getStatusCode() {
return m_statusCode;
}
public T getBody() {
return m_body;
}
}
package com.ctrip.apollo.util.http;
import com.google.common.base.Charsets;
import com.google.gson.Gson;
import com.ctrip.apollo.util.ConfigUtil;
import org.unidal.helper.Files;
import org.unidal.lookup.annotation.Inject;
import org.unidal.lookup.annotation.Named;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* @author Jason Song(song_s@ctrip.com)
*/
@Named(type = HttpUtil.class)
public class HttpUtil {
@Inject
private ConfigUtil m_configUtil;
private Gson gson;
public HttpUtil() {
gson = new Gson();
}
/**
* Do get operation for the http request
*
* @throws RuntimeException if any error happened or response code is neither 200 nor 304
*/
public <T> HttpResponse<T> doGet(HttpRequest httpRequest, Class<T> responseType) {
InputStream is = null;
try {
HttpURLConnection conn = (HttpURLConnection) new URL(httpRequest.getUrl()).openConnection();
conn.setRequestMethod("GET");
if (httpRequest.getConnectTimeout() < 0) {
conn.setConnectTimeout(m_configUtil.getConnectTimeout());
} else {
conn.setConnectTimeout(httpRequest.getConnectTimeout());
}
if (httpRequest.getReadTimeout() < 0) {
conn.setReadTimeout(m_configUtil.getReadTimeout());
} else {
conn.setReadTimeout(httpRequest.getReadTimeout());
}
conn.connect();
int statusCode = conn.getResponseCode();
if (statusCode == 200) {
is = conn.getInputStream();
String content = Files.IO.INSTANCE.readFrom(is, Charsets.UTF_8.name());
return new HttpResponse<>(statusCode, gson.fromJson(content, responseType));
}
if (statusCode == 304) {
return new HttpResponse<>(statusCode, null);
}
throw new RuntimeException(
String.format("Get operation failed, status code - %d", statusCode));
} catch (Throwable ex) {
throw new RuntimeException("Could not complete get operation", ex);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
//ignore
}
}
}
}
}
...@@ -26,5 +26,27 @@ ...@@ -26,5 +26,27 @@
</requirement> </requirement>
</requirements> </requirements>
</component> </component>
<component>
<role>com.ctrip.apollo.util.ConfigUtil</role>
<implementation>com.ctrip.apollo.util.ConfigUtil</implementation>
</component>
<component>
<role>com.ctrip.apollo.internals.ConfigServiceLocator</role>
<implementation>com.ctrip.apollo.internals.ConfigServiceLocator</implementation>
<requirements>
<requirement>
<role>com.ctrip.apollo.util.http.HttpUtil</role>
</requirement>
</requirements>
</component>
<component>
<role>com.ctrip.apollo.util.http.HttpUtil</role>
<implementation>com.ctrip.apollo.util.http.HttpUtil</implementation>
<requirements>
<requirement>
<role>com.ctrip.apollo.util.ConfigUtil</role>
</requirement>
</requirements>
</component>
</components> </components>
</plexus> </plexus>
...@@ -28,7 +28,7 @@ public class DefaultConfigTest { ...@@ -28,7 +28,7 @@ public class DefaultConfigTest {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
someResourceDir = new File(ClassLoaderUtil.getClassPath() + "/META-INF/config"); someResourceDir = new File(ClassLoaderUtil.getClassPath() + "/META-INF/config");
someResourceDir.mkdir(); someResourceDir.mkdirs();
someNamespace = "someName"; someNamespace = "someName";
configRepository = mock(ConfigRepository.class); configRepository = mock(ConfigRepository.class);
} }
......
...@@ -8,6 +8,7 @@ import com.ctrip.apollo.util.ConfigUtil; ...@@ -8,6 +8,7 @@ import com.ctrip.apollo.util.ConfigUtil;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.unidal.lookup.ComponentTestCase;
import java.io.File; import java.io.File;
import java.util.Properties; import java.util.Properties;
...@@ -21,15 +22,17 @@ import static org.mockito.Mockito.when; ...@@ -21,15 +22,17 @@ import static org.mockito.Mockito.when;
/** /**
* Created by Jason on 4/9/16. * Created by Jason on 4/9/16.
*/ */
public class LocalFileConfigRepositoryTest { public class LocalFileConfigRepositoryTest extends ComponentTestCase {
private File someBaseDir; private File someBaseDir;
private String someNamespace; private String someNamespace;
private ConfigRepository fallbackRepo; private ConfigRepository fallbackRepo;
private Properties someProperties; private Properties someProperties;
private ConfigUtil someConfigUtil; private static String someAppId = "someApp";
private static String someCluster = "someCluster";
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp();
someBaseDir = new File("src/test/resources/config-cache"); someBaseDir = new File("src/test/resources/config-cache");
someBaseDir.mkdir(); someBaseDir.mkdir();
...@@ -39,12 +42,7 @@ public class LocalFileConfigRepositoryTest { ...@@ -39,12 +42,7 @@ public class LocalFileConfigRepositoryTest {
fallbackRepo = mock(ConfigRepository.class); fallbackRepo = mock(ConfigRepository.class);
when(fallbackRepo.loadConfig()).thenReturn(someProperties); when(fallbackRepo.loadConfig()).thenReturn(someProperties);
String someAppId = "someApp"; defineComponent(ConfigUtil.class, MockConfigUtil.class);
String someCluster = "someCluster";
someConfigUtil = mock(ConfigUtil.class);
when(someConfigUtil.getAppId()).thenReturn(someAppId);
when(someConfigUtil.getCluster()).thenReturn(someCluster);
} }
@After @After
...@@ -66,8 +64,8 @@ public class LocalFileConfigRepositoryTest { ...@@ -66,8 +64,8 @@ public class LocalFileConfigRepositoryTest {
} }
private String assembleLocalCacheFileName() { private String assembleLocalCacheFileName() {
return String.format("%s-%s-%s.properties", someConfigUtil.getAppId(), return String.format("%s-%s-%s.properties", someAppId,
someConfigUtil.getCluster(), someNamespace); someCluster, someNamespace);
} }
@Test @Test
...@@ -84,7 +82,7 @@ public class LocalFileConfigRepositoryTest { ...@@ -84,7 +82,7 @@ public class LocalFileConfigRepositoryTest {
Files.write(someKey + "=" + someValue, file, Charsets.UTF_8); Files.write(someKey + "=" + someValue, file, Charsets.UTF_8);
LocalFileConfigRepository localRepo = new LocalFileConfigRepository(someBaseDir, someNamespace, someConfigUtil); LocalFileConfigRepository localRepo = new LocalFileConfigRepository(someBaseDir, someNamespace);
Properties properties = localRepo.loadConfig(); Properties properties = localRepo.loadConfig();
assertEquals(someValue, properties.getProperty(someKey)); assertEquals(someValue, properties.getProperty(someKey));
...@@ -95,7 +93,7 @@ public class LocalFileConfigRepositoryTest { ...@@ -95,7 +93,7 @@ public class LocalFileConfigRepositoryTest {
public void testLoadConfigWithNoLocalFile() throws Exception { public void testLoadConfigWithNoLocalFile() throws Exception {
LocalFileConfigRepository LocalFileConfigRepository
localFileConfigRepository = localFileConfigRepository =
new LocalFileConfigRepository(someBaseDir, someNamespace, someConfigUtil); new LocalFileConfigRepository(someBaseDir, someNamespace);
localFileConfigRepository.setFallback(fallbackRepo); localFileConfigRepository.setFallback(fallbackRepo);
...@@ -109,7 +107,7 @@ public class LocalFileConfigRepositoryTest { ...@@ -109,7 +107,7 @@ public class LocalFileConfigRepositoryTest {
@Test @Test
public void testLoadConfigWithNoLocalFileMultipleTimes() throws Exception { public void testLoadConfigWithNoLocalFileMultipleTimes() throws Exception {
LocalFileConfigRepository localRepo = LocalFileConfigRepository localRepo =
new LocalFileConfigRepository(someBaseDir, someNamespace, someConfigUtil); new LocalFileConfigRepository(someBaseDir, someNamespace);
localRepo.setFallback(fallbackRepo); localRepo.setFallback(fallbackRepo);
...@@ -117,7 +115,7 @@ public class LocalFileConfigRepositoryTest { ...@@ -117,7 +115,7 @@ public class LocalFileConfigRepositoryTest {
LocalFileConfigRepository LocalFileConfigRepository
anotherLocalRepoWithNoFallback = anotherLocalRepoWithNoFallback =
new LocalFileConfigRepository(someBaseDir, someNamespace, someConfigUtil); new LocalFileConfigRepository(someBaseDir, someNamespace);
Properties anotherProperties = anotherLocalRepoWithNoFallback.loadConfig(); Properties anotherProperties = anotherLocalRepoWithNoFallback.loadConfig();
...@@ -127,4 +125,16 @@ public class LocalFileConfigRepositoryTest { ...@@ -127,4 +125,16 @@ public class LocalFileConfigRepositoryTest {
} }
} public static class MockConfigUtil extends ConfigUtil {
\ No newline at end of file @Override
public String getAppId() {
return someAppId;
}
@Override
public String getCluster() {
return someCluster;
}
}
}
...@@ -6,26 +6,22 @@ import com.google.common.collect.Maps; ...@@ -6,26 +6,22 @@ import com.google.common.collect.Maps;
import com.ctrip.apollo.core.dto.ApolloConfig; import com.ctrip.apollo.core.dto.ApolloConfig;
import com.ctrip.apollo.core.dto.ServiceDTO; import com.ctrip.apollo.core.dto.ServiceDTO;
import com.ctrip.apollo.util.ConfigUtil; import com.ctrip.apollo.util.ConfigUtil;
import com.ctrip.apollo.util.http.HttpRequest;
import com.ctrip.apollo.util.http.HttpResponse;
import com.ctrip.apollo.util.http.HttpUtil;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; 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.http.HttpEntity; import org.unidal.lookup.ComponentTestCase;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyMap;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
...@@ -33,27 +29,23 @@ import static org.mockito.Mockito.when; ...@@ -33,27 +29,23 @@ import static org.mockito.Mockito.when;
* Created by Jason on 4/9/16. * Created by Jason on 4/9/16.
*/ */
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class RemoteConfigRepositoryTest { public class RemoteConfigRepositoryTest extends ComponentTestCase {
@Mock
private RestTemplate restTemplate;
@Mock @Mock
private ConfigServiceLocator configServiceLocator; private ConfigServiceLocator configServiceLocator;
private String someNamespace; private String someNamespace;
@Mock @Mock
private ResponseEntity<ApolloConfig> someResponse; private static HttpResponse<ApolloConfig> someResponse;
@Mock @Mock
private ConfigUtil someConfigUtil; private ConfigUtil someConfigUtil;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp();
someNamespace = "someName"; someNamespace = "someName";
String someServerUrl = "http://someServer";
mockConfigServiceLocator(someServerUrl);
String someAppId = "someApp"; defineComponent(ConfigUtil.class, MockConfigUtil.class);
String someCluster = "someCluster"; defineComponent(ConfigServiceLocator.class, MockConfigServiceLocator.class);
when(someConfigUtil.getAppId()).thenReturn(someAppId); defineComponent(HttpUtil.class, MockHttpUtil.class);
when(someConfigUtil.getCluster()).thenReturn(someCluster);
} }
@Test @Test
...@@ -64,13 +56,10 @@ public class RemoteConfigRepositoryTest { ...@@ -64,13 +56,10 @@ public class RemoteConfigRepositoryTest {
configurations.put(someKey, someValue); configurations.put(someKey, someValue);
ApolloConfig someApolloConfig = assembleApolloConfig(configurations); ApolloConfig someApolloConfig = assembleApolloConfig(configurations);
when(someResponse.getStatusCode()).thenReturn(HttpStatus.OK); when(someResponse.getStatusCode()).thenReturn(200);
when(someResponse.getBody()).thenReturn(someApolloConfig); when(someResponse.getBody()).thenReturn(someApolloConfig);
when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class),
eq(ApolloConfig.class), anyMap())).thenReturn(someResponse);
RemoteConfigRepository remoteConfigRepository = new RemoteConfigRepository(restTemplate, configServiceLocator, someConfigUtil, someNamespace); RemoteConfigRepository remoteConfigRepository = new RemoteConfigRepository(someNamespace);
Properties config = remoteConfigRepository.loadConfig(); Properties config = remoteConfigRepository.loadConfig();
assertEquals(configurations, config); assertEquals(configurations, config);
...@@ -79,11 +68,9 @@ public class RemoteConfigRepositoryTest { ...@@ -79,11 +68,9 @@ public class RemoteConfigRepositoryTest {
@Test(expected = RuntimeException.class) @Test(expected = RuntimeException.class)
public void testGetRemoteConfigWithServerError() throws Exception { public void testGetRemoteConfigWithServerError() throws Exception {
when(someResponse.getStatusCode()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR); when(someResponse.getStatusCode()).thenReturn(500);
when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class),
eq(ApolloConfig.class), anyMap())).thenReturn(someResponse);
RemoteConfigRepository remoteConfigRepository = new RemoteConfigRepository(restTemplate, configServiceLocator, someConfigUtil, someNamespace); RemoteConfigRepository remoteConfigRepository = new RemoteConfigRepository(someNamespace);
remoteConfigRepository.loadConfig(); remoteConfigRepository.loadConfig();
} }
...@@ -99,10 +86,35 @@ public class RemoteConfigRepositoryTest { ...@@ -99,10 +86,35 @@ public class RemoteConfigRepositoryTest {
return apolloConfig; return apolloConfig;
} }
private void mockConfigServiceLocator(String serverUrl) { public static class MockConfigUtil extends ConfigUtil {
ServiceDTO serviceDTO = mock(ServiceDTO.class); @Override
public String getAppId() {
return "someApp";
}
when(serviceDTO.getHomepageUrl()).thenReturn(serverUrl); @Override
when(configServiceLocator.getConfigServices()).thenReturn(Lists.newArrayList(serviceDTO)); public String getCluster() {
return "someCluster";
}
} }
public static class MockConfigServiceLocator extends ConfigServiceLocator {
@Override
public List<ServiceDTO> getConfigServices() {
String someServerUrl = "http://someServer";
ServiceDTO serviceDTO = mock(ServiceDTO.class);
when(serviceDTO.getHomepageUrl()).thenReturn(someServerUrl);
return Lists.newArrayList(serviceDTO);
}
}
public static class MockHttpUtil extends HttpUtil {
@Override
public <T> HttpResponse<T> doGet(HttpRequest httpRequest, Class<T> responseType) {
return (HttpResponse<T>) someResponse;
}
}
} }
...@@ -15,12 +15,8 @@ ...@@ -15,12 +15,8 @@
<dependencies> <dependencies>
<!-- json --> <!-- json -->
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>jackson-annotations</artifactId> <artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency> </dependency>
<!-- end of json --> <!-- end of json -->
<!-- util --> <!-- util -->
......
...@@ -2,9 +2,6 @@ package com.ctrip.apollo.core.dto; ...@@ -2,9 +2,6 @@ package com.ctrip.apollo.core.dto;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Map; import java.util.Map;
/** /**
...@@ -22,11 +19,10 @@ public class ApolloConfig { ...@@ -22,11 +19,10 @@ public class ApolloConfig {
private long releaseId; private long releaseId;
@JsonCreator public ApolloConfig(String appId,
public ApolloConfig(@JsonProperty("appId") String appId, String cluster,
@JsonProperty("cluster") String cluster, String namespace,
@JsonProperty("namespace") String namespace, long releaseId) {
@JsonProperty("releaseId") long releaseId) {
super(); super();
this.appId = appId; this.appId = appId;
this.cluster = cluster; this.cluster = cluster;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册