Commit 6888ff73 by Yiming Liu

Merge pull request #57 from nobodyiam/non-spring-client-merge

Add non-spring-client support and added a demo for it
parents 46d6e00e efa84db2
......@@ -23,10 +23,6 @@
<!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
......
......@@ -31,7 +31,8 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicReference;
/**
* Client side config manager
* Apollo Config for Spring Application
* Requires Spring 3.1+
*
* @author Jason Song(song_s@ctrip.com)
*/
......@@ -57,7 +58,7 @@ public class ApolloConfigManager
this.configLoaderManager = ConfigLoaderFactory.getInstance().getConfigLoaderManager();
this.configUtil = ConfigUtil.getInstance();
executorService =
Executors.newScheduledThreadPool(1, ApolloThreadFactory.create("ConfigManager", true));
Executors.newScheduledThreadPool(1, ApolloThreadFactory.create("ApolloConfigManager", true));
}
@Override
......@@ -135,6 +136,8 @@ public class ApolloConfigManager
}
void schedulePeriodicRefresh() {
logger.info("Schedule periodic refresh with interval: {} {}",
configUtil.getRefreshInterval(), configUtil.getRefreshTimeUnit());
executorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
......
package com.ctrip.apollo.client;
import com.ctrip.apollo.client.model.PropertyChange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.CompositePropertySource;
import java.util.List;
/**
* Apollo config for non-Spring application
*
* @author Jason Song(song_s@ctrip.com)
*/
public class ApolloEnvironment {
private static final Logger logger = LoggerFactory.getLogger(ApolloEnvironment.class);
private static ApolloEnvironment instance = new ApolloEnvironment();
private volatile CompositePropertySource propertySource;
private ApolloEnvironmentManager apolloEnvironmentManager;
private ApolloEnvironment() {
apolloEnvironmentManager = new ApolloEnvironmentManager(this);
}
public void init() {
this.apolloEnvironmentManager.init();
}
public static ApolloEnvironment getInstance() {
return instance;
}
/**
* Return the property value with the given key, or {@code null}
* if the key doesn't exist.
*
* @param key the property name
* @return the property value
*/
public String getProperty(String key) {
if (this.propertySource == null) {
throw new IllegalStateException(
"ApolloEnvironment not initialized, please call ApolloEnvironment.init() first");
}
Object value = this.propertySource.getProperty(key);
if (value == null) {
return null;
}
return (String) value;
}
/**
* Return the property value with the given key, or
* {@code defaultValue} if the key doesn't exist.
*/
public String getProperty(String key, String defaultValue) {
String value = getProperty(key);
return value == null ? defaultValue : value;
}
void updatePropertySource(CompositePropertySource propertySource) {
this.propertySource = propertySource;
}
void updatePropertySource(CompositePropertySource propertySource, List<PropertyChange> changes) {
this.updatePropertySource(propertySource);
//TODO broadcast changes
}
}
package com.ctrip.apollo.client;
import com.ctrip.apollo.client.loader.ConfigLoaderFactory;
import com.ctrip.apollo.client.loader.ConfigLoaderManager;
import com.ctrip.apollo.client.model.PropertySourceReloadResult;
import com.ctrip.apollo.client.util.ConfigUtil;
import com.ctrip.apollo.core.utils.ApolloThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author Jason Song(song_s@ctrip.com)
*/
class ApolloEnvironmentManager {
private static final Logger logger = LoggerFactory.getLogger(ApolloEnvironmentManager.class);
private ConfigLoaderManager configLoaderManager;
private ConfigUtil configUtil;
private ScheduledExecutorService executorService;
private ApolloEnvironment apolloEnvironment;
private AtomicBoolean initDone;
ApolloEnvironmentManager(ApolloEnvironment apolloEnvironment) {
this.apolloEnvironment = apolloEnvironment;
this.configLoaderManager = ConfigLoaderFactory.getInstance().getConfigLoaderManager();
this.configUtil = ConfigUtil.getInstance();
this.executorService =
Executors
.newScheduledThreadPool(1,
ApolloThreadFactory.create("ApolloEnvironmentManager", true));
this.initDone = new AtomicBoolean();
}
synchronized void init() {
if (initDone.get()) {
logger.warn("ApolloEnvironmentManager init already done");
return;
}
this.apolloEnvironment.updatePropertySource(this.configLoaderManager.loadPropertySource());
this.schedulePeriodicRefresh();
initDone.set(true);
}
void schedulePeriodicRefresh() {
logger.info("Schedule periodic refresh with interval: {} {}",
configUtil.getRefreshInterval(), configUtil.getRefreshTimeUnit());
this.executorService.scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
try {
updatePropertySource();
} catch (Throwable ex) {
logger.error("Refreshing config failed", ex);
}
}
}, configUtil.getRefreshInterval(), configUtil.getRefreshInterval(),
configUtil.getRefreshTimeUnit());
}
void updatePropertySource() {
PropertySourceReloadResult result = this.configLoaderManager.reloadPropertySource();
if (result.hasChanges()) {
logger.info("Found changes, refresh environment.");
this.apolloEnvironment.updatePropertySource(result.getPropertySource(), result.getChanges());
}
}
}
......@@ -11,7 +11,7 @@ import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({
ApolloConfigManagerTest.class, ConfigLoaderManagerTest.class, RemoteConfigLoaderTest.class,
ConfigUtilTest.class
ConfigUtilTest.class, ApolloEnvironmentTest.class, ApolloEnvironmentManagerTest.class
})
public class AllTests {
......
package com.ctrip.apollo.client;
import com.google.common.collect.Lists;
import com.ctrip.apollo.client.loader.ConfigLoaderManager;
import com.ctrip.apollo.client.model.PropertyChange;
import com.ctrip.apollo.client.model.PropertySourceReloadResult;
import com.ctrip.apollo.client.util.ConfigUtil;
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.core.env.CompositePropertySource;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
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)
*/
@RunWith(MockitoJUnitRunner.class)
public class ApolloEnvironmentManagerTest {
private ApolloEnvironmentManager apolloEnvironmentManager;
@Mock
private ConfigLoaderManager configLoaderManager;
@Mock
private ConfigUtil configUtil;
@Mock
private ApolloEnvironment apolloEnvironment;
@Before
public void setUp() throws Exception {
apolloEnvironmentManager = spy(new ApolloEnvironmentManager(apolloEnvironment));
ReflectionTestUtils
.setField(apolloEnvironmentManager, "configLoaderManager", configLoaderManager);
ReflectionTestUtils.setField(apolloEnvironmentManager, "configUtil", configUtil);
int someInterval = 1;
TimeUnit someUnit = TimeUnit.MINUTES;
when(configUtil.getRefreshInterval()).thenReturn(someInterval);
when(configUtil.getRefreshTimeUnit()).thenReturn(someUnit);
}
@Test
public void testInit() throws Exception {
CompositePropertySource somePropertySource = mock(CompositePropertySource.class);
when(configLoaderManager.loadPropertySource()).thenReturn(somePropertySource);
apolloEnvironmentManager.init();
verify(configLoaderManager, times(1)).loadPropertySource();
verify(apolloEnvironment, times(1)).updatePropertySource(somePropertySource);
}
@Test
public void testUpdatePropertySource() throws Exception {
PropertySourceReloadResult someResult = mock(PropertySourceReloadResult.class);
CompositePropertySource somePropertySource = mock(CompositePropertySource.class);
List<PropertyChange> someChanges = Lists.newArrayList();
when(someResult.hasChanges()).thenReturn(true);
when(someResult.getPropertySource()).thenReturn(somePropertySource);
when(someResult.getChanges()).thenReturn(someChanges);
when(configLoaderManager.reloadPropertySource()).thenReturn(someResult);
apolloEnvironmentManager.updatePropertySource();
verify(configLoaderManager, times(1)).reloadPropertySource();
verify(apolloEnvironment, times(1)).updatePropertySource(somePropertySource, someChanges);
}
}
package com.ctrip.apollo.client;
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.core.env.CompositePropertySource;
import org.springframework.test.util.ReflectionTestUtils;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
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)
*/
@RunWith(MockitoJUnitRunner.class)
public class ApolloEnvironmentTest {
private ApolloEnvironment apolloEnvironment;
@Mock
private ApolloEnvironmentManager apolloEnvironmentManager;
@Before
public void setUp() throws Exception {
apolloEnvironment = spy(ApolloEnvironment.getInstance());
ReflectionTestUtils
.setField(apolloEnvironment, "apolloEnvironmentManager", apolloEnvironmentManager);
}
@Test
public void testInit() throws Exception {
apolloEnvironment.init();
verify(apolloEnvironmentManager, times(1)).init();
}
@Test
public void testGetProperty() throws Exception {
CompositePropertySource somePropertySource = mock(CompositePropertySource.class);
String someKey = "someKey";
String someValue = "someValue";
apolloEnvironment.updatePropertySource(somePropertySource);
when(somePropertySource.getProperty(someKey)).thenReturn(someValue);
String result = apolloEnvironment.getProperty(someKey);
assertEquals(someValue, result);
}
@Test
public void testGetPropertyWithDefaultValue() throws Exception {
CompositePropertySource somePropertySource = mock(CompositePropertySource.class);
String someKey = "someKey";
String someDefaultValue = "someDefault";
apolloEnvironment.updatePropertySource(somePropertySource);
when(somePropertySource.getProperty(someKey)).thenReturn(null);
String result = apolloEnvironment.getProperty(someKey, someDefaultValue);
assertEquals(someDefaultValue, result);
}
@Test(expected = IllegalStateException.class)
public void testGetPropertyWithNoPropertySource() throws Exception {
String someKey = "someKey";
apolloEnvironment.getProperty(someKey);
}
}
<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/maven-v4_0_0.xsd">
<?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>
......@@ -7,9 +9,8 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apollo-demo</artifactId>
<packaging>war</packaging>
<name>Apollo Demo</name>
<url>http://maven.apache.org</url>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.ctrip.apollo</groupId>
......@@ -17,23 +18,6 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.tuckey</groupId>
<artifactId>urlrewritefilter</artifactId>
<version>4.0.4</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
......@@ -50,7 +34,6 @@
<artifactId>commons-logging</artifactId>
</dependency>
</dependencies>
<build>
<finalName>apollo-demo</finalName>
</build>
</project>
import com.ctrip.apollo.client.ApolloEnvironment;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class ApolloConfigDemo {
private ApolloEnvironment env;
public ApolloConfigDemo() {
env = ApolloEnvironment.getInstance();
env.init();
}
private String getConfig(String key) {
String result = env.getProperty(key, "undefined");
System.out.println(String.format("Loading key: %s with value: %s", key, result));
return result;
}
public static void main(String[] args) throws IOException {
ApolloConfigDemo apolloConfigDemo = new ApolloConfigDemo();
System.out.println(
"Apollo Config Demo. Please input key to get the value.");
while (true) {
System.out.print("> ");
String input = (new BufferedReader(new InputStreamReader(System.in)).readLine()).trim();
if (input.equalsIgnoreCase("quit")) {
System.exit(0);
}
apolloConfigDemo.getConfig(input);
}
}
}
<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/maven-v4_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-spring-demo</artifactId>
<packaging>war</packaging>
<name>Apollo Spring Demo</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>com.ctrip.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.tuckey</groupId>
<artifactId>urlrewritefilter</artifactId>
<version>4.0.4</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</dependency>
</dependencies>
<build>
<finalName>apollo-spring-demo</finalName>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<configuration monitorInterval="60">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="[apollo-demo][%t]%d %-5p [%c] %m%n"/>
</Console>
<Async name="Async" includeLocation="true">
<AppenderRef ref="Console"/>
</Async>
</appenders>
<loggers>
<logger name="com.ctrip.apollo" additivity="false" level="trace">
<AppenderRef ref="Async" level="DEBUG"/>
</logger>
<root level="INFO">
<AppenderRef ref="Async"/>
</root>
</loggers>
</configuration>
......@@ -93,6 +93,7 @@
<module>apollo-configservice</module>
<module>apollo-adminservice</module>
<module>apollo-portal</module>
<module>apollo-spring-demo</module>
<module>apollo-demo</module>
</modules>
......
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