spring-cloud / spring-cloud/spring-cloud-consul
Spring Cloud Consul does not work well with application context hierarchies and profiles
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 822
- Forks
- 539
- Avg merge
- 9h 31m
- Merged PRs (30d)
- 7
Description
Describe the bug
Spring Cloud Consul: 3.0.4
Spring Boot: 2.5.14
Java: 11
Given the following application context hierarchy:
final SpringApplicationBuilder parentBuilder = new SpringApplicationBuilder()
.profiles("A")
.web(WebApplicationType.NONE);
parentBuilder.run(args);
parentBuilder.child(BootstrapApplication.class)
.web(WebApplicationType.NONE)
.profiles("A", "B")
.run(args)
.close();
parentBuilder.child(ApplicationConfiguration.class)
.profiles("A")
.web(WebApplicationType.SERVLET)
.run(args);
And given that ConsulPropertySourceLocator is a singleton in the bootstrap context, when the empty parent context (parentBuilder) is loaded it's Environment contains the following ConsulPropertySource's:
0 = "config/service,A/"
1 = "config/service/"
2 = "config/application,A/"
3 = "config/application/"
This is all good and normal, but when the second context is loaded, it's Environment contains the following ConsulPropertySource's:
0 = "config/service,A/"
1 = "config/service/"
2 = "config/application,A/"
3 = "config/application/"
4 = "config/service,A/"
5 = "config/service,B/"
6 = "config/service/"
7 = "config/application,A/"
8 = "config/application,B/"
9 = "config/application/"
The problem is that the ConsulPropertySourceLocator is caching Consul context's from the previous ApplicationContext and just appending them together. And properties from the "B" profile that override properties from the "default" profile are not being picked up.
The current workaround I have, which is very much a hack is a @BoostrapConfiguration class that registers a BeanPostProcessor to wrap the ConsulPropertySourceLocator and clear() the context's before the next invocation of locate() is called.
@BootstrapConfiguration
public class FixConsulPropertySourceLocatorBootstrapConfiguration {
@Bean
public BeanPostProcessor fixConsulPropertySourceLocatorBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
if (bean instanceof ConsulPropertySourceLocator) {
return new FixedConsulPropertySourceLocator((ConsulPropertySourceLocator) bean);
} else {
return bean;
}
}
};
}
static class FixedConsulPropertySourceLocator implements PropertySourceLocator, ConsulConfigIndexes {
private final ConsulPropertySourceLocator delegate;
public FixedConsulPropertySourceLocator(final ConsulPropertySourceLocator delegate) {
this.delegate = delegate;
}
@Override
public PropertySource<?> locate(final Environment environment) {
delegate.getContexts().clear();
return delegate.locate(environment);
}
@Override
public LinkedHashMap<String, Long> getIndexes() {
return delegate.getIndexes();
}
}
}
It would be nice if this was fixed upstream and in a better manor than I have attempted here.
This then makes the ConsulPropertySource's for that Environment appear as expected:
0 = "config/service,A/"
1 = "config/service,B/"
2 = "config/service/"
3 = "config/application,A/"
4 = "config/application,B/"
5 = "config/application/"
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with ConsulPropertySourceLocator, especially locate(Environment), getContexts(), and the ConsulConfigIndexes state described in the report. Reproduce the supplied SpringApplicationBuilder context hierarchy with profiles A and B, then verify that the resulting ConsulPropertySource list contains each expected context once and that profile B overrides the default profile.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring, spring-boot
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100