Skip to content

Commit

Permalink
Allow users to config comma-separated namespaces for ApolloConfigChan…
Browse files Browse the repository at this point in the history
…geListener (#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 <anandhjoshi@outlook.com>
  • Loading branch information
anandjoshisn and anandjoshi91 authored Dec 28, 2022
1 parent 041fdf4 commit af2751f
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 5 deletions.
2 changes: 1 addition & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ Apollo Java 2.1.0
* [Apollo Client Support Spring Boot 3.0](https://github.com/apolloconfig/apollo-java/pull/4)
* [apollo-client-config-data support spring boot 3.0](https://github.com/apolloconfig/apollo-java/pull/5)
* [Add apollo-plugin-log4j2 module to support log4j2.xml integration](https://github.com/apolloconfig/apollo-java/pull/6)

* [Allow users to config comma-separated namespaces for ApolloConfigChangeListener](https://github.com/apolloconfig/apollo-java/pull/11)
------------------
All issues and pull requests are [here](https://github.com/apolloconfig/apollo-java/milestone/1?closed=1)
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@
import com.ctrip.framework.apollo.spring.util.SpringInjector;
import com.ctrip.framework.apollo.util.ConfigUtil;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Nullable;
import org.slf4j.Logger;
Expand All @@ -54,6 +56,11 @@ public class ApolloAnnotationProcessor extends ApolloProcessor implements BeanFa
EnvironmentAware {

private static final Logger logger = LoggerFactory.getLogger(ApolloAnnotationProcessor.class);

private static final String NAMESPACE_DELIMITER = ",";

private static final Splitter NAMESPACE_SPLITTER = Splitter.on(NAMESPACE_DELIMITER)
.omitEmptyStrings().trimResults();
private static final Gson GSON = new Gson();

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

for (String namespace : namespaces) {
final String resolvedNamespace = this.environment.resolveRequiredPlaceholders(namespace);
Config config = ConfigService.getConfig(resolvedNamespace);
Set<String> resolvedNamespaces = processResolveNamespaceValue(namespaces);

for (String namespace : resolvedNamespaces) {
Config config = ConfigService.getConfig(namespace);

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

/**
* Evaluate and resolve namespaces from env/properties.
* Split delimited namespaces
* @param namespaces
* @return resolved namespaces
*/
private Set<String> processResolveNamespaceValue(String[] namespaces) {

Set<String> resolvedNamespaces = new HashSet<>();

for (String namespace : namespaces) {
final String resolvedNamespace = this.environment.resolveRequiredPlaceholders(namespace);

if (resolvedNamespace.contains(NAMESPACE_DELIMITER)) {
resolvedNamespaces.addAll(NAMESPACE_SPLITTER.splitToList(resolvedNamespace));
} else {
resolvedNamespaces.add(resolvedNamespace);
}
}

return resolvedNamespaces;
}

private void processApolloJsonValue(Object bean, String beanName, Field field) {
ApolloJsonValue apolloJsonValue = AnnotationUtils.getAnnotation(field, ApolloJsonValue.class);
if (apolloJsonValue == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@
* //handle change event
* }
* <br />
* //The namespace could also be specified as a placeholder for a comma separated namespaces, e.g. ${app.allNamespaces}, where "all.allNamespaces" = "someNamespace,anotherNamespace,yetAnotherNamespace"
* &#064;ApolloConfigChangeListener({"${app.allNamespaces}"})
* private void onChange(ConfigChangeEvent changeEvent) {
* //handle change event
* }
* <br />
* //Listener on namespaces of "someNamespace" and "anotherNamespace", will only be notified when "someKey" or "anotherKey" is changed
* &#064;ApolloConfigChangeListener(value = {"someNamespace","anotherNamespace"}, interestedKeys = {"someKey", "anotherKey"})
* private void onChange(ConfigChangeEvent changeEvent) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

Expand Down Expand Up @@ -94,6 +94,7 @@ public void tearDown() throws Exception {
System.clearProperty(SystemPropertyKeyConstants.FROM_SYSTEM_YAML_NAMESPACE);
System.clearProperty(SystemPropertyKeyConstants.FROM_NAMESPACE_APPLICATION_KEY);
System.clearProperty(SystemPropertyKeyConstants.FROM_NAMESPACE_APPLICATION_KEY_YAML);
System.clearProperty(SystemPropertyKeyConstants.DELIMITED_NAMESPACES);
System.clearProperty(ApolloClientSystemConsts.APOLLO_PROPERTY_NAMES_CACHE_ENABLE);
super.tearDown();
}
Expand Down Expand Up @@ -471,6 +472,57 @@ public void testApolloConfigChangeListenerResolveExpressionSimple() {
verify(applicationConfig, times(3)).addChangeListener(any(ConfigChangeListener.class));
}


/**
* resolve namespace's from comma separated namespaces
*/
@Test
public void testApolloConfigChangeListenerWithCommaSeparatedNameSpaces() {

final String propValue = "app1,app2,app3";
System.setProperty(SystemPropertyKeyConstants.DELIMITED_NAMESPACES, propValue);

Config app1Config = mock(Config.class);
mockConfig("app1", app1Config);

Config app2Config = mock(Config.class);
mockConfig("app2", app2Config);

Config app3Config = mock(Config.class);
mockConfig("app3", app3Config);

getSimpleBean(TestApolloConfigChangeListenerWithCommaSeparatedNameSpaces.class);

verify(app1Config, times(1)).addChangeListener(any(ConfigChangeListener.class));
verify(app2Config, times(1)).addChangeListener(any(ConfigChangeListener.class));
verify(app3Config, times(1)).addChangeListener(any(ConfigChangeListener.class));
}

/**
* resolve namespace's from comma separated namespaces
*/
@Test
public void testApolloConfigChangeListenerWithCommaSeparatedNameSpacesMergedWithOnesInValue() {

final String propValue = "app1,app2";
System.setProperty(SystemPropertyKeyConstants.DELIMITED_NAMESPACES, propValue);

Config app1Config = mock(Config.class);
mockConfig("app1", app1Config);

Config app2Config = mock(Config.class);
mockConfig("app2", app2Config);

Config appConfig = mock(Config.class);
mockConfig("app", appConfig);

getSimpleBean(TestApolloConfigChangeListenerWithCommaSeparatedNameSpacesMergedWithOnesInValue.class);

verify(app1Config, times(1)).addChangeListener(any(ConfigChangeListener.class));
verify(app2Config, times(1)).addChangeListener(any(ConfigChangeListener.class));
verify(appConfig, times(1)).addChangeListener(any(ConfigChangeListener.class));
}

/**
* resolve namespace's name from system property.
*/
Expand Down Expand Up @@ -597,6 +649,7 @@ private static class SystemPropertyKeyConstants {
static final String FROM_SYSTEM_YAML_NAMESPACE = "from.system.yaml.namespace";
static final String FROM_NAMESPACE_APPLICATION_KEY = "from.namespace.application.key";
static final String FROM_NAMESPACE_APPLICATION_KEY_YAML = "from.namespace.application.key.yaml";
static final String DELIMITED_NAMESPACES = "delimited.namespaces";
}

@EnableApolloConfig
Expand Down Expand Up @@ -670,6 +723,24 @@ private void onChange(ConfigChangeEvent event) {
}
}

@Configuration
@EnableApolloConfig
static class TestApolloConfigChangeListenerWithCommaSeparatedNameSpaces {

@ApolloConfigChangeListener("${" + SystemPropertyKeyConstants.DELIMITED_NAMESPACES + "}")
private void onChange(ConfigChangeEvent changeEvent) {
}
}

@Configuration
@EnableApolloConfig
static class TestApolloConfigChangeListenerWithCommaSeparatedNameSpacesMergedWithOnesInValue {

@ApolloConfigChangeListener(value = {"app", "${" + SystemPropertyKeyConstants.DELIMITED_NAMESPACES + "}"})
private void onChange(ConfigChangeEvent changeEvent) {
}
}

@Configuration
@EnableApolloConfig
static class TestApolloConfigChangeListenerResolveExpressionFromSystemPropertyConfiguration {
Expand Down

0 comments on commit af2751f

Please sign in to comment.