diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapApplicationListener.java b/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapApplicationListener.java index 76428941..648c5361 100644 --- a/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapApplicationListener.java +++ b/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapApplicationListener.java @@ -81,6 +81,11 @@ public class BootstrapApplicationListener if (environment.getPropertySources().contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) { return; } + for (ApplicationContextInitializer initializer : event.getSpringApplication().getInitializers()) { + if (initializer instanceof ParentContextApplicationContextInitializer) { + return; + } + } ConfigurableApplicationContext context = bootstrapServiceContext(environment, event.getSpringApplication()); apply(context, event.getSpringApplication(), environment); diff --git a/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/TestHigherPriorityBootstrapConfiguration.java b/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/TestHigherPriorityBootstrapConfiguration.java index 2494a5b6..90aa8b5c 100644 --- a/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/TestHigherPriorityBootstrapConfiguration.java +++ b/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/TestHigherPriorityBootstrapConfiguration.java @@ -1,5 +1,6 @@ package org.springframework.cloud.bootstrap; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import org.springframework.core.Ordered; @@ -12,8 +13,11 @@ import org.springframework.core.annotation.Order; public class TestHigherPriorityBootstrapConfiguration { static final AtomicReference> firstToBeCreated = new AtomicReference<>(); + + public static final AtomicInteger count = new AtomicInteger(); public TestHigherPriorityBootstrapConfiguration() { + count.incrementAndGet(); firstToBeCreated.compareAndSet(null, TestHigherPriorityBootstrapConfiguration.class); } diff --git a/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/config/BootstrapConfigurationTests.java b/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/config/BootstrapConfigurationTests.java index 6267fcd1..87ad1f3a 100644 --- a/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/config/BootstrapConfigurationTests.java +++ b/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/config/BootstrapConfigurationTests.java @@ -28,6 +28,7 @@ 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; +import org.springframework.cloud.bootstrap.TestHigherPriorityBootstrapConfiguration; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Configuration; @@ -42,6 +43,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; /** @@ -270,6 +272,18 @@ public class BootstrapConfigurationTests { assertEquals(0, sources.precedenceOf(bootstrap)); } + @Test + public void onlyOneBootstrapContext() { + TestHigherPriorityBootstrapConfiguration.count.set(0); + PropertySourceConfiguration.MAP.put("bootstrap.foo", "bar"); + this.context = new SpringApplicationBuilder().sources(BareConfiguration.class) + .child(BareConfiguration.class).web(false).run(); + assertEquals(1, TestHigherPriorityBootstrapConfiguration.count.get()); + assertNotNull(context.getParent()); + assertEquals("bootstrap", context.getParent().getParent().getId()); + assertNull(context.getParent().getParent().getParent()); + } + @Test public void environmentEnrichedInParentContext() { PropertySourceConfiguration.MAP.put("bootstrap.foo", "bar"); diff --git a/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/config/BootstrapListenerHierarchyIntegrationTests.java b/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/config/BootstrapListenerHierarchyIntegrationTests.java new file mode 100644 index 00000000..f2ecf058 --- /dev/null +++ b/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/config/BootstrapListenerHierarchyIntegrationTests.java @@ -0,0 +1,100 @@ +/* + * Copyright 2013-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.bootstrap.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import org.junit.Test; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Integration tests for Bootstrap Listener's functionality of adding a bootstrap context + * as the root Application Context + * + * @author Biju Kunjummen + */ +public class BootstrapListenerHierarchyIntegrationTests { + + @Test + public void shouldAddInABootstrapContext() { + ConfigurableApplicationContext context = new SpringApplicationBuilder() + .sources(BasicConfiguration.class).web(false).run(); + + assertNotNull(context.getParent()); + } + + @Test + public void shouldAddInOneBootstrapForABasicParentChildHierarchy() { + ConfigurableApplicationContext context = new SpringApplicationBuilder() + .sources(RootConfiguration.class).web(false) + .child(BasicConfiguration.class).web(false).run(); + + // Should be RootConfiguration based context + ConfigurableApplicationContext parent = (ConfigurableApplicationContext) context + .getParent(); + assertEquals("rootBean", parent.getBean("rootBean", String.class)); + + // Parent should have the bootstrap context as parent + assertNotNull(parent.getParent()); + + ConfigurableApplicationContext bootstrapContext = (ConfigurableApplicationContext) parent + .getParent(); + + // Bootstrap should be the root, there should be no other parent + assertNull(bootstrapContext.getParent()); + } + + @Test + public void shouldAddInOneBootstrapForSiblingsBasedHierarchy() { + ConfigurableApplicationContext context = new SpringApplicationBuilder() + .sources(RootConfiguration.class).web(false) + .child(BasicConfiguration.class).web(false) + .sibling(BasicConfiguration.class).web(false).run(); + + // Should be RootConfiguration based context + ConfigurableApplicationContext parent = (ConfigurableApplicationContext) context + .getParent(); + assertEquals("rootBean", parent.getBean("rootBean", String.class)); + + // Parent should have the bootstrap context as parent + assertNotNull(parent.getParent()); + + ConfigurableApplicationContext bootstrapContext = (ConfigurableApplicationContext) parent + .getParent(); + + // Bootstrap should be the root, there should be no other parent + assertNull(bootstrapContext.getParent()); + } + + @Configuration + static class BasicConfiguration { + } + + @Configuration + static class RootConfiguration { + + @Bean + public String rootBean() { + return "rootBean"; + } + } +} \ No newline at end of file