Skip to content

Commit 331e790

Browse files
author
Dave Syer
committed
Ensure there is a single bootstrap parent context
Only one neds to be created, and once it is in place in the hierarchy it should be usable by all the child contexts that get added. Fixes spring-projectsgh-153
1 parent 8347c57 commit 331e790

File tree

4 files changed

+123
-0
lines changed

4 files changed

+123
-0
lines changed

spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapApplicationListener.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
8181
if (environment.getPropertySources().contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
8282
return;
8383
}
84+
for (ApplicationContextInitializer<?> initializer : event.getSpringApplication().getInitializers()) {
85+
if (initializer instanceof ParentContextApplicationContextInitializer) {
86+
return;
87+
}
88+
}
8489
ConfigurableApplicationContext context = bootstrapServiceContext(environment,
8590
event.getSpringApplication());
8691
apply(context, event.getSpringApplication(), environment);

spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/TestHigherPriorityBootstrapConfiguration.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.springframework.cloud.bootstrap;
22

3+
import java.util.concurrent.atomic.AtomicInteger;
34
import java.util.concurrent.atomic.AtomicReference;
45

56
import org.springframework.core.Ordered;
@@ -12,8 +13,11 @@
1213
public class TestHigherPriorityBootstrapConfiguration {
1314

1415
static final AtomicReference<Class<?>> firstToBeCreated = new AtomicReference<>();
16+
17+
public static final AtomicInteger count = new AtomicInteger();
1518

1619
public TestHigherPriorityBootstrapConfiguration() {
20+
count.incrementAndGet();
1721
firstToBeCreated.compareAndSet(null, TestHigherPriorityBootstrapConfiguration.class);
1822
}
1923

spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/config/BootstrapConfigurationTests.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.springframework.boot.builder.SpringApplicationBuilder;
2929
import org.springframework.boot.context.properties.ConfigurationProperties;
3030
import org.springframework.boot.context.properties.EnableConfigurationProperties;
31+
import org.springframework.cloud.bootstrap.TestHigherPriorityBootstrapConfiguration;
3132
import org.springframework.context.ApplicationContextInitializer;
3233
import org.springframework.context.ConfigurableApplicationContext;
3334
import org.springframework.context.annotation.Configuration;
@@ -42,6 +43,7 @@
4243
import static org.junit.Assert.assertFalse;
4344
import static org.junit.Assert.assertNotNull;
4445
import static org.junit.Assert.assertNotSame;
46+
import static org.junit.Assert.assertNull;
4547
import static org.junit.Assert.assertTrue;
4648

4749
/**
@@ -270,6 +272,18 @@ public void environmentEnrichedOnceWhenSharedWithChildContext() {
270272
assertEquals(0, sources.precedenceOf(bootstrap));
271273
}
272274

275+
@Test
276+
public void onlyOneBootstrapContext() {
277+
TestHigherPriorityBootstrapConfiguration.count.set(0);
278+
PropertySourceConfiguration.MAP.put("bootstrap.foo", "bar");
279+
this.context = new SpringApplicationBuilder().sources(BareConfiguration.class)
280+
.child(BareConfiguration.class).web(false).run();
281+
assertEquals(1, TestHigherPriorityBootstrapConfiguration.count.get());
282+
assertNotNull(context.getParent());
283+
assertEquals("bootstrap", context.getParent().getParent().getId());
284+
assertNull(context.getParent().getParent().getParent());
285+
}
286+
273287
@Test
274288
public void environmentEnrichedInParentContext() {
275289
PropertySourceConfiguration.MAP.put("bootstrap.foo", "bar");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright 2013-2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.bootstrap.config;
18+
19+
import static org.junit.Assert.assertEquals;
20+
import static org.junit.Assert.assertNotNull;
21+
import static org.junit.Assert.assertNull;
22+
23+
import org.junit.Test;
24+
import org.springframework.boot.builder.SpringApplicationBuilder;
25+
import org.springframework.context.ConfigurableApplicationContext;
26+
import org.springframework.context.annotation.Bean;
27+
import org.springframework.context.annotation.Configuration;
28+
29+
/**
30+
* Integration tests for Bootstrap Listener's functionality of adding a bootstrap context
31+
* as the root Application Context
32+
*
33+
* @author Biju Kunjummen
34+
*/
35+
public class BootstrapListenerHierarchyIntegrationTests {
36+
37+
@Test
38+
public void shouldAddInABootstrapContext() {
39+
ConfigurableApplicationContext context = new SpringApplicationBuilder()
40+
.sources(BasicConfiguration.class).web(false).run();
41+
42+
assertNotNull(context.getParent());
43+
}
44+
45+
@Test
46+
public void shouldAddInOneBootstrapForABasicParentChildHierarchy() {
47+
ConfigurableApplicationContext context = new SpringApplicationBuilder()
48+
.sources(RootConfiguration.class).web(false)
49+
.child(BasicConfiguration.class).web(false).run();
50+
51+
// Should be RootConfiguration based context
52+
ConfigurableApplicationContext parent = (ConfigurableApplicationContext) context
53+
.getParent();
54+
assertEquals("rootBean", parent.getBean("rootBean", String.class));
55+
56+
// Parent should have the bootstrap context as parent
57+
assertNotNull(parent.getParent());
58+
59+
ConfigurableApplicationContext bootstrapContext = (ConfigurableApplicationContext) parent
60+
.getParent();
61+
62+
// Bootstrap should be the root, there should be no other parent
63+
assertNull(bootstrapContext.getParent());
64+
}
65+
66+
@Test
67+
public void shouldAddInOneBootstrapForSiblingsBasedHierarchy() {
68+
ConfigurableApplicationContext context = new SpringApplicationBuilder()
69+
.sources(RootConfiguration.class).web(false)
70+
.child(BasicConfiguration.class).web(false)
71+
.sibling(BasicConfiguration.class).web(false).run();
72+
73+
// Should be RootConfiguration based context
74+
ConfigurableApplicationContext parent = (ConfigurableApplicationContext) context
75+
.getParent();
76+
assertEquals("rootBean", parent.getBean("rootBean", String.class));
77+
78+
// Parent should have the bootstrap context as parent
79+
assertNotNull(parent.getParent());
80+
81+
ConfigurableApplicationContext bootstrapContext = (ConfigurableApplicationContext) parent
82+
.getParent();
83+
84+
// Bootstrap should be the root, there should be no other parent
85+
assertNull(bootstrapContext.getParent());
86+
}
87+
88+
@Configuration
89+
static class BasicConfiguration {
90+
}
91+
92+
@Configuration
93+
static class RootConfiguration {
94+
95+
@Bean
96+
public String rootBean() {
97+
return "rootBean";
98+
}
99+
}
100+
}

0 commit comments

Comments
 (0)