Apply bootstrap initializers to all contexts in a hierarchy
The fix for gh-153 was sensible, but has now exposed another issue which is that the bootstrap initializers, whilst they are now only created once, actually only get applied to the parent context in a hierarchy. Most of the time this doesn't matter because the child contexts all benefit from environment changes and additional beans added to the parent. If the children are supposed to actually have different environments, though, there is a problem. So this change locates the existing bootstrap context and applies it to each new context created separately. Unfortunately we have to use reflection to do that for now because there is no way to discover the parent with a public API before the context is refreshed. See gh-190
This commit is contained in:
@@ -1,6 +1,14 @@
|
||||
package org.springframework.cloud.bootstrap;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
|
||||
import static org.springframework.cloud.bootstrap.TestHigherPriorityBootstrapConfiguration.firstToBeCreated;
|
||||
|
||||
@@ -8,10 +16,28 @@ import static org.springframework.cloud.bootstrap.TestHigherPriorityBootstrapCon
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Order(0)
|
||||
@Configuration
|
||||
public class TestBootstrapConfiguration {
|
||||
|
||||
public TestBootstrapConfiguration() {
|
||||
firstToBeCreated.compareAndSet(null, TestBootstrapConfiguration.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ApplicationContextInitializer<ConfigurableApplicationContext> customInitializer() {
|
||||
return new ApplicationContextInitializer<ConfigurableApplicationContext>() {
|
||||
|
||||
@Override
|
||||
public void initialize(ConfigurableApplicationContext applicationContext) {
|
||||
ConfigurableEnvironment environment = applicationContext.getEnvironment();
|
||||
environment.getPropertySources()
|
||||
.addLast(new MapPropertySource("customProperties",
|
||||
Collections.<String, Object>singletonMap("custom.foo",
|
||||
environment.resolvePlaceholders(
|
||||
"${spring.application.name:bar}"))));
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
@@ -54,6 +55,8 @@ public class BootstrapConfigurationTests {
|
||||
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
private ConfigurableApplicationContext sibling;
|
||||
|
||||
@Rule
|
||||
public ExpectedException expected = ExpectedException.none();
|
||||
|
||||
@@ -68,6 +71,9 @@ public class BootstrapConfigurationTests {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
if (this.sibling != null) {
|
||||
this.sibling.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -197,7 +203,7 @@ public class BootstrapConfigurationTests {
|
||||
PropertySourceConfiguration.MAP.put("spring.cloud.config.allowOverride", "true");
|
||||
ConfigurableEnvironment environment = new StandardEnvironment();
|
||||
environment.getPropertySources().addLast(new MapPropertySource("last",
|
||||
Collections.<String, Object> singletonMap("bootstrap.foo", "splat")));
|
||||
Collections.<String, Object>singletonMap("bootstrap.foo", "splat")));
|
||||
this.context = new SpringApplicationBuilder().web(false).environment(environment)
|
||||
.sources(BareConfiguration.class).run();
|
||||
assertEquals("splat", this.context.getEnvironment().getProperty("bootstrap.foo"));
|
||||
@@ -282,6 +288,32 @@ public class BootstrapConfigurationTests {
|
||||
assertNotNull(context.getParent());
|
||||
assertEquals("bootstrap", context.getParent().getParent().getId());
|
||||
assertNull(context.getParent().getParent().getParent());
|
||||
assertEquals("bar", context.getEnvironment().getProperty("custom.foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bootstrapContextSharedBySiblings() {
|
||||
TestHigherPriorityBootstrapConfiguration.count.set(0);
|
||||
PropertySourceConfiguration.MAP.put("bootstrap.foo", "bar");
|
||||
SpringApplicationBuilder builder = new SpringApplicationBuilder()
|
||||
.sources(BareConfiguration.class);
|
||||
this.sibling = builder.child(BareConfiguration.class)
|
||||
.properties("spring.application.name=sibling").web(false).run();
|
||||
this.context = builder.child(BareConfiguration.class)
|
||||
.properties("spring.application.name=context").web(false).run();
|
||||
assertEquals(1, TestHigherPriorityBootstrapConfiguration.count.get());
|
||||
assertNotNull(context.getParent());
|
||||
assertEquals("bootstrap", context.getParent().getParent().getId());
|
||||
assertNull(context.getParent().getParent().getParent());
|
||||
assertEquals("context", context.getEnvironment().getProperty("custom.foo"));
|
||||
assertEquals("context",
|
||||
context.getEnvironment().getProperty("spring.application.name"));
|
||||
assertNotNull(sibling.getParent());
|
||||
assertEquals("bootstrap", sibling.getParent().getParent().getId());
|
||||
assertNull(sibling.getParent().getParent().getParent());
|
||||
assertEquals("sibling", sibling.getEnvironment().getProperty("custom.foo"));
|
||||
assertEquals("sibling",
|
||||
sibling.getEnvironment().getProperty("spring.application.name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -340,7 +372,7 @@ public class BootstrapConfigurationTests {
|
||||
protected static class PropertySourceConfiguration implements PropertySourceLocator {
|
||||
|
||||
public static Map<String, Object> MAP = new HashMap<String, Object>(
|
||||
Collections.<String, Object> singletonMap("bootstrap.foo", "bar"));
|
||||
Collections.<String, Object>singletonMap("bootstrap.foo", "bar"));
|
||||
|
||||
private String name;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user