diff --git a/SPR-12031/pom.xml b/SPR-12031/pom.xml new file mode 100644 index 00000000..b95b702e --- /dev/null +++ b/SPR-12031/pom.xml @@ -0,0 +1,121 @@ + + + 4.0.0 + + org.test + demo + 0.0.1-SNAPSHOT + jar + + eureka-client + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 1.3.0.BUILD-SNAPSHOT + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-devtools + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.cloud + spring-cloud-starter-config + + + org.springframework.cloud + spring-cloud-starter-feign + + + org.springframework.cloud + spring-cloud-starter-eureka + + + org.springframework.cloud + spring-cloud-starter-ribbon + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.cloud + spring-cloud-starter-parent + Brixton.BUILD-SNAPSHOT + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + + diff --git a/SPR-12031/src/main/resources/application.properties b/SPR-12031/src/main/resources/application.properties new file mode 100644 index 00000000..afa5de84 --- /dev/null +++ b/SPR-12031/src/main/resources/application.properties @@ -0,0 +1,3 @@ +spring.devtools.remote.secret=dlkfjhd +eureka.instance.secure-virtual-host-name=${spring.application.name:unknown} +ribbon.IsSecure=true \ No newline at end of file diff --git a/SPR-12031/src/main/resources/bootstrap.properties b/SPR-12031/src/main/resources/bootstrap.properties new file mode 100644 index 00000000..52278187 --- /dev/null +++ b/SPR-12031/src/main/resources/bootstrap.properties @@ -0,0 +1,5 @@ +# eureka.client.serviceUrl.defaultZone: https://GkW7hXnMKlMS:FV85Yz5pSaUX@eureka-533e6a77-b50a-49a0-a678-426294b0e48d.cfapps.pez.pivotal.io/eureka/ +spring.application.name: eureka-client +spring.cloud.config.uri: ${vcap.services.configservice.credentials.uri:http://localhost:8888} +# spring.cloud.config.failFast: true +logging.level.com.netflix.discovery: OFF \ No newline at end of file diff --git a/SPR-12031/src/test/java/demo/ApplicationTests.java b/SPR-12031/src/test/java/demo/ApplicationTests.java new file mode 100644 index 00000000..c294bac2 --- /dev/null +++ b/SPR-12031/src/test/java/demo/ApplicationTests.java @@ -0,0 +1,78 @@ +package demo; + +import static org.junit.Assert.assertEquals; + +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.IntegrationTest; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.BootstrapWith; +import org.springframework.test.context.junit4.rules.SpringClassRule; + +import demo.ApplicationTests.Application; + +@SpringApplicationConfiguration(classes = Application.class) +@BootstrapWith(ChildContextBootstrapper.class) +@IntegrationTest("logging.level.org.springframework.web=DEBUG") +public class ApplicationTests { + + @ClassRule + public static final SpringClassRule springClass = new SpringClassRule(); + + @Rule + public final ChildMethodRule springMethod = new ChildMethodRule(); + + @Autowired + private String foo; + + @Test + public void contextLoads() { + assertEquals("foo", this.foo); + } + + @Test + @ChildSpringApplication(Child.class) + public void contextLoadsChild() { + assertEquals("bar", this.foo); + } + + @Test + @ChildSpringApplication(ChildWithValue.class) + @ChildTestProperties("foo=spam") + public void contextLoadsChildWithProperties() { + assertEquals("spam", this.foo); + } + + @Configuration + public static class Application { + @Bean + public String foo() { + return "foo"; + } + } + + @Configuration + public static class Child { + @Bean + public String foo() { + return "bar"; + } + } + + @Configuration + public static class ChildWithValue { + @Value("${foo}") + private String foo; + + @Bean + public String foo() { + return this.foo; + } + } + +} diff --git a/SPR-12031/src/test/java/demo/ChildContextBootstrapper.java b/SPR-12031/src/test/java/demo/ChildContextBootstrapper.java new file mode 100644 index 00000000..29e37a4d --- /dev/null +++ b/SPR-12031/src/test/java/demo/ChildContextBootstrapper.java @@ -0,0 +1,42 @@ +/* + * Copyright 2015 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 demo; + +import org.springframework.test.context.ContextLoader; +import org.springframework.test.context.TestContext; +import org.springframework.test.context.support.AbstractTestContextBootstrapper; +import org.springframework.test.context.support.DelegatingSmartContextLoader; + +/** + * @author Dave Syer + * + */ +public class ChildContextBootstrapper extends AbstractTestContextBootstrapper { + + @Override + protected Class getDefaultContextLoaderClass( + Class testClass) { + return DelegatingSmartContextLoader.class; + } + + @Override + public TestContext buildTestContext() { + return new ChildTestContext(getBootstrapContext().getTestClass(), buildMergedContextConfiguration(), + getCacheAwareContextLoaderDelegate()); + } + +} diff --git a/SPR-12031/src/test/java/demo/ChildMethodRule.java b/SPR-12031/src/test/java/demo/ChildMethodRule.java new file mode 100644 index 00000000..697001a7 --- /dev/null +++ b/SPR-12031/src/test/java/demo/ChildMethodRule.java @@ -0,0 +1,76 @@ +/* + * Copyright 2015 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 demo; + +import java.lang.reflect.Method; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.Statement; +import org.springframework.test.context.TestContext; +import org.springframework.test.context.TestContextManager; +import org.springframework.test.context.junit4.rules.SpringClassRule; +import org.springframework.test.context.junit4.rules.SpringMethodRule; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.util.ReflectionUtils; + +/** + * @author Dave Syer + * + */ +public class ChildMethodRule extends SpringMethodRule { + + private static final Log logger = LogFactory.getLog(ChildMethodRule.class); + + @Override + public Statement apply(Statement base, FrameworkMethod frameworkMethod, Object testInstance) { + Class testClass = testInstance.getClass(); + Method method = ReflectionUtils.findMethod(SpringClassRule.class, "getTestContextManager", Class.class); + ReflectionUtils.makeAccessible(method); + TestContextManager testContextManager = (TestContextManager) ReflectionUtils.invokeMethod(method, null, testClass); + TestContext testContext = (TestContext) ReflectionTestUtils.getField(testContextManager, "testContext"); + + if (logger.isDebugEnabled()) { + logger.debug("Applying ChildMethodRule to test method [" + frameworkMethod.getMethod() + "]."); + } + return new Statement() { + + @Override + public void evaluate() throws Throwable { + delegate(base, frameworkMethod, testInstance, testContext); + } + + }; + } + + public void delegate(Statement base, FrameworkMethod frameworkMethod, Object testInstance, TestContext testContext) throws Throwable { + ChildTestContext child = null; + if (testContext instanceof ChildTestContext) { + child = (ChildTestContext) testContext; + } + if (child!=null) { + child.setTestMethod(frameworkMethod.getMethod()); + } + super.apply(base, frameworkMethod, testInstance).evaluate(); + if (child!=null) { + // Clean up the child context if there is one + child.close(); + } + } + +} diff --git a/SPR-12031/src/test/java/demo/ChildSpringApplication.java b/SPR-12031/src/test/java/demo/ChildSpringApplication.java new file mode 100644 index 00000000..92cfa010 --- /dev/null +++ b/SPR-12031/src/test/java/demo/ChildSpringApplication.java @@ -0,0 +1,41 @@ +/* + * Copyright 2012-2015 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 demo; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.core.annotation.AliasFor; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration +@Documented +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ChildSpringApplication { + + @AliasFor("classes") + Class[] value() default {}; + + @AliasFor("value") + Class[] classes() default {}; +} diff --git a/SPR-12031/src/test/java/demo/ChildTestContext.java b/SPR-12031/src/test/java/demo/ChildTestContext.java new file mode 100644 index 00000000..02d8770b --- /dev/null +++ b/SPR-12031/src/test/java/demo/ChildTestContext.java @@ -0,0 +1,101 @@ +/* + * Copyright 2015 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 demo; + +import java.lang.reflect.Method; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.boot.Banner.Mode; +import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.annotation.AnnotatedElementUtils; +import org.springframework.test.context.CacheAwareContextLoaderDelegate; +import org.springframework.test.context.MergedContextConfiguration; +import org.springframework.test.context.support.DefaultTestContext; + +/** + * @author Dave Syer + * + */ +public class ChildTestContext extends DefaultTestContext { + + private static final Log logger = LogFactory.getLog(ChildMethodRule.class); + private Method method; + private ConfigurableApplicationContext closeable; + + public ChildTestContext(Class testClass, + MergedContextConfiguration mergedContextConfiguration, + CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate) { + super(testClass, mergedContextConfiguration, cacheAwareContextLoaderDelegate); + } + + @Override + public ApplicationContext getApplicationContext() { + ApplicationContext parent = super.getApplicationContext(); + ApplicationContext context = parent; + if (this.method != null) { + SpringApplicationBuilder builder = null; + ChildSpringApplication annotation = AnnotatedElementUtils + .getMergedAnnotation(this.method, ChildSpringApplication.class); + if (annotation != null) { + if (annotation.classes().length > 0) { + builder = new SpringApplicationBuilder(); + for (Class source : annotation.classes()) { + builder.sources(source); + } + } + } + ChildTestProperties properties = AnnotatedElementUtils + .getMergedAnnotation(this.method, ChildTestProperties.class); + if (properties != null) { + if (properties.value().length > 0) { + if (builder == null) { + builder = new SpringApplicationBuilder(); + } + for (String source : properties.value()) { + builder.properties(source); + } + } + } + if (builder != null) { + this.closeable = builder + .sources(PropertyPlaceholderAutoConfiguration.class) + .bannerMode(Mode.OFF).web(false) + .parent((ConfigurableApplicationContext) parent).run(); + context = this.closeable; + } + } + return context; + } + + public void close() { + if (logger.isDebugEnabled()) { + logger.debug("Closing child context."); + } + if (this.closeable != null && this.closeable.isActive()) { + this.closeable.close(); + } + } + + public void setTestMethod(Method method) { + this.method = method; + } + +} diff --git a/SPR-12031/src/test/java/demo/ChildTestProperties.java b/SPR-12031/src/test/java/demo/ChildTestProperties.java new file mode 100644 index 00000000..9e950072 --- /dev/null +++ b/SPR-12031/src/test/java/demo/ChildTestProperties.java @@ -0,0 +1,34 @@ +/* + * Copyright 2012-2015 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 demo; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Documented +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ChildTestProperties { + + String[] value() default {}; + +}