Skip to content

Commit af2751f

Browse files
Allow users to config comma-separated namespaces for ApolloConfigChangeListener (#11)
* test java 8 build * provide optional param to inject comma separated strings of namespaces * revert import reorder * process values and split namespaces by comma * revert extra new line, add description how namespace parsing is happening * rename vars * namespace splitting should be handled in annotation processor class * update documentation * revert NamespaceHandler.java * update changelog with approproate PR name * remove unused import * refactor pr name / function name as per review Co-authored-by: anandjoshi91 <[email protected]>
1 parent 041fdf4 commit af2751f

File tree

4 files changed

+113
-5
lines changed

4 files changed

+113
-5
lines changed

CHANGES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ Apollo Java 2.1.0
1616
* [Apollo Client Support Spring Boot 3.0](https://github.com/apolloconfig/apollo-java/pull/4)
1717
* [apollo-client-config-data support spring boot 3.0](https://github.com/apolloconfig/apollo-java/pull/5)
1818
* [Add apollo-plugin-log4j2 module to support log4j2.xml integration](https://github.com/apolloconfig/apollo-java/pull/6)
19-
19+
* [Allow users to config comma-separated namespaces for ApolloConfigChangeListener](https://github.com/apolloconfig/apollo-java/pull/11)
2020
------------------
2121
All issues and pull requests are [here](https://github.com/apolloconfig/apollo-java/milestone/1?closed=1)

apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloAnnotationProcessor.java

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,13 @@
2727
import com.ctrip.framework.apollo.spring.util.SpringInjector;
2828
import com.ctrip.framework.apollo.util.ConfigUtil;
2929
import com.google.common.base.Preconditions;
30+
import com.google.common.base.Splitter;
3031
import com.google.common.collect.Sets;
3132
import com.google.gson.Gson;
3233
import java.lang.reflect.Field;
3334
import java.lang.reflect.Method;
3435
import java.lang.reflect.Type;
36+
import java.util.HashSet;
3537
import java.util.Set;
3638
import javax.annotation.Nullable;
3739
import org.slf4j.Logger;
@@ -54,6 +56,11 @@ public class ApolloAnnotationProcessor extends ApolloProcessor implements BeanFa
5456
EnvironmentAware {
5557

5658
private static final Logger logger = LoggerFactory.getLogger(ApolloAnnotationProcessor.class);
59+
60+
private static final String NAMESPACE_DELIMITER = ",";
61+
62+
private static final Splitter NAMESPACE_SPLITTER = Splitter.on(NAMESPACE_DELIMITER)
63+
.omitEmptyStrings().trimResults();
5764
private static final Gson GSON = new Gson();
5865

5966
private final ConfigUtil configUtil;
@@ -128,9 +135,10 @@ private void processApolloConfigChangeListener(final Object bean, final Method m
128135
annotatedInterestedKeyPrefixes.length > 0 ? Sets.newHashSet(annotatedInterestedKeyPrefixes)
129136
: null;
130137

131-
for (String namespace : namespaces) {
132-
final String resolvedNamespace = this.environment.resolveRequiredPlaceholders(namespace);
133-
Config config = ConfigService.getConfig(resolvedNamespace);
138+
Set<String> resolvedNamespaces = processResolveNamespaceValue(namespaces);
139+
140+
for (String namespace : resolvedNamespaces) {
141+
Config config = ConfigService.getConfig(namespace);
134142

135143
if (interestedKeys == null && interestedKeyPrefixes == null) {
136144
config.addChangeListener(configChangeListener);
@@ -140,6 +148,29 @@ private void processApolloConfigChangeListener(final Object bean, final Method m
140148
}
141149
}
142150

151+
/**
152+
* Evaluate and resolve namespaces from env/properties.
153+
* Split delimited namespaces
154+
* @param namespaces
155+
* @return resolved namespaces
156+
*/
157+
private Set<String> processResolveNamespaceValue(String[] namespaces) {
158+
159+
Set<String> resolvedNamespaces = new HashSet<>();
160+
161+
for (String namespace : namespaces) {
162+
final String resolvedNamespace = this.environment.resolveRequiredPlaceholders(namespace);
163+
164+
if (resolvedNamespace.contains(NAMESPACE_DELIMITER)) {
165+
resolvedNamespaces.addAll(NAMESPACE_SPLITTER.splitToList(resolvedNamespace));
166+
} else {
167+
resolvedNamespaces.add(resolvedNamespace);
168+
}
169+
}
170+
171+
return resolvedNamespaces;
172+
}
173+
143174
private void processApolloJsonValue(Object bean, String beanName, Field field) {
144175
ApolloJsonValue apolloJsonValue = AnnotationUtils.getAnnotation(field, ApolloJsonValue.class);
145176
if (apolloJsonValue == null) {

apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloConfigChangeListener.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@
4040
* //handle change event
4141
* }
4242
* <br />
43+
* //The namespace could also be specified as a placeholder for a comma separated namespaces, e.g. ${app.allNamespaces}, where "all.allNamespaces" = "someNamespace,anotherNamespace,yetAnotherNamespace"
44+
* &#064;ApolloConfigChangeListener({"${app.allNamespaces}"})
45+
* private void onChange(ConfigChangeEvent changeEvent) {
46+
* //handle change event
47+
* }
48+
* <br />
4349
* //Listener on namespaces of "someNamespace" and "anotherNamespace", will only be notified when "someKey" or "anotherKey" is changed
4450
* &#064;ApolloConfigChangeListener(value = {"someNamespace","anotherNamespace"}, interestedKeys = {"someKey", "anotherKey"})
4551
* private void onChange(ConfigChangeEvent changeEvent) {

apollo-client/src/test/java/com/ctrip/framework/apollo/spring/JavaConfigAnnotationTest.java

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@
6363
import static org.mockito.Mockito.doAnswer;
6464
import static org.mockito.Mockito.mock;
6565
import static org.mockito.Mockito.never;
66-
import static org.mockito.Mockito.times;
6766
import static org.mockito.Mockito.spy;
67+
import static org.mockito.Mockito.times;
6868
import static org.mockito.Mockito.verify;
6969
import static org.mockito.Mockito.when;
7070

@@ -94,6 +94,7 @@ public void tearDown() throws Exception {
9494
System.clearProperty(SystemPropertyKeyConstants.FROM_SYSTEM_YAML_NAMESPACE);
9595
System.clearProperty(SystemPropertyKeyConstants.FROM_NAMESPACE_APPLICATION_KEY);
9696
System.clearProperty(SystemPropertyKeyConstants.FROM_NAMESPACE_APPLICATION_KEY_YAML);
97+
System.clearProperty(SystemPropertyKeyConstants.DELIMITED_NAMESPACES);
9798
System.clearProperty(ApolloClientSystemConsts.APOLLO_PROPERTY_NAMES_CACHE_ENABLE);
9899
super.tearDown();
99100
}
@@ -471,6 +472,57 @@ public void testApolloConfigChangeListenerResolveExpressionSimple() {
471472
verify(applicationConfig, times(3)).addChangeListener(any(ConfigChangeListener.class));
472473
}
473474

475+
476+
/**
477+
* resolve namespace's from comma separated namespaces
478+
*/
479+
@Test
480+
public void testApolloConfigChangeListenerWithCommaSeparatedNameSpaces() {
481+
482+
final String propValue = "app1,app2,app3";
483+
System.setProperty(SystemPropertyKeyConstants.DELIMITED_NAMESPACES, propValue);
484+
485+
Config app1Config = mock(Config.class);
486+
mockConfig("app1", app1Config);
487+
488+
Config app2Config = mock(Config.class);
489+
mockConfig("app2", app2Config);
490+
491+
Config app3Config = mock(Config.class);
492+
mockConfig("app3", app3Config);
493+
494+
getSimpleBean(TestApolloConfigChangeListenerWithCommaSeparatedNameSpaces.class);
495+
496+
verify(app1Config, times(1)).addChangeListener(any(ConfigChangeListener.class));
497+
verify(app2Config, times(1)).addChangeListener(any(ConfigChangeListener.class));
498+
verify(app3Config, times(1)).addChangeListener(any(ConfigChangeListener.class));
499+
}
500+
501+
/**
502+
* resolve namespace's from comma separated namespaces
503+
*/
504+
@Test
505+
public void testApolloConfigChangeListenerWithCommaSeparatedNameSpacesMergedWithOnesInValue() {
506+
507+
final String propValue = "app1,app2";
508+
System.setProperty(SystemPropertyKeyConstants.DELIMITED_NAMESPACES, propValue);
509+
510+
Config app1Config = mock(Config.class);
511+
mockConfig("app1", app1Config);
512+
513+
Config app2Config = mock(Config.class);
514+
mockConfig("app2", app2Config);
515+
516+
Config appConfig = mock(Config.class);
517+
mockConfig("app", appConfig);
518+
519+
getSimpleBean(TestApolloConfigChangeListenerWithCommaSeparatedNameSpacesMergedWithOnesInValue.class);
520+
521+
verify(app1Config, times(1)).addChangeListener(any(ConfigChangeListener.class));
522+
verify(app2Config, times(1)).addChangeListener(any(ConfigChangeListener.class));
523+
verify(appConfig, times(1)).addChangeListener(any(ConfigChangeListener.class));
524+
}
525+
474526
/**
475527
* resolve namespace's name from system property.
476528
*/
@@ -597,6 +649,7 @@ private static class SystemPropertyKeyConstants {
597649
static final String FROM_SYSTEM_YAML_NAMESPACE = "from.system.yaml.namespace";
598650
static final String FROM_NAMESPACE_APPLICATION_KEY = "from.namespace.application.key";
599651
static final String FROM_NAMESPACE_APPLICATION_KEY_YAML = "from.namespace.application.key.yaml";
652+
static final String DELIMITED_NAMESPACES = "delimited.namespaces";
600653
}
601654

602655
@EnableApolloConfig
@@ -670,6 +723,24 @@ private void onChange(ConfigChangeEvent event) {
670723
}
671724
}
672725

726+
@Configuration
727+
@EnableApolloConfig
728+
static class TestApolloConfigChangeListenerWithCommaSeparatedNameSpaces {
729+
730+
@ApolloConfigChangeListener("${" + SystemPropertyKeyConstants.DELIMITED_NAMESPACES + "}")
731+
private void onChange(ConfigChangeEvent changeEvent) {
732+
}
733+
}
734+
735+
@Configuration
736+
@EnableApolloConfig
737+
static class TestApolloConfigChangeListenerWithCommaSeparatedNameSpacesMergedWithOnesInValue {
738+
739+
@ApolloConfigChangeListener(value = {"app", "${" + SystemPropertyKeyConstants.DELIMITED_NAMESPACES + "}"})
740+
private void onChange(ConfigChangeEvent changeEvent) {
741+
}
742+
}
743+
673744
@Configuration
674745
@EnableApolloConfig
675746
static class TestApolloConfigChangeListenerResolveExpressionFromSystemPropertyConfiguration {

0 commit comments

Comments
 (0)