[bs-144] Make EmbedddedContainerConfiguration an import selector

Previously EmbedddedContainerConfiguration cannot be imported directly.
This change ensures that the nested classes are not loaded automatically
so there can be no issues with the annotation parameters.

There might be a case for a change in Spring here since the framework
itself could just be more cautious when processing nested classes.

[Fixes #50880927]
This commit is contained in:
Dave Syer 2013-05-31 13:24:04 +01:00
parent 6c22e0ab6e
commit 990627b328
2 changed files with 106 additions and 5 deletions

View File

@ -0,0 +1,92 @@
package org.springframework.bootstrap.sample.tomcat;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.bootstrap.SpringApplication;
import org.springframework.bootstrap.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.bootstrap.autoconfigure.web.EmbeddedContainerConfiguration;
import org.springframework.bootstrap.autoconfigure.web.WebMvcAutoConfiguration;
import org.springframework.bootstrap.sample.tomcat.service.HelloWorldService;
import org.springframework.bootstrap.sample.tomcat.web.SampleController;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import static org.junit.Assert.assertEquals;
/**
* Basic integration tests for demo application.
*
* @author Dave Syer
*
*/
public class NonAutoConfigurationBootstrapApplicationTests {
private static ConfigurableApplicationContext context;
@Configuration
@Import({ EmbeddedContainerConfiguration.class, WebMvcAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class })
@ComponentScan(basePackageClasses = { SampleController.class, HelloWorldService.class })
public static class NonAutoConfigurationBootstrapApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(TomcatBootstrapApplication.class, args);
}
}
@BeforeClass
public static void start() throws Exception {
Future<ConfigurableApplicationContext> future = Executors
.newSingleThreadExecutor().submit(
new Callable<ConfigurableApplicationContext>() {
@Override
public ConfigurableApplicationContext call() throws Exception {
return (ConfigurableApplicationContext) SpringApplication
.run(NonAutoConfigurationBootstrapApplication.class);
}
});
context = future.get(10, TimeUnit.SECONDS);
}
@AfterClass
public static void stop() {
if (context != null) {
context.close();
}
}
@Test
public void testHome() throws Exception {
ResponseEntity<String> entity = getRestTemplate().getForEntity(
"http://localhost:8080", String.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertEquals("Hello World", entity.getBody());
}
private RestTemplate getRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
@Override
public void handleError(ClientHttpResponse response) throws IOException {
}
});
return restTemplate;
}
}

View File

@ -28,7 +28,8 @@ import org.springframework.bootstrap.context.embedded.jetty.JettyEmbeddedServlet
import org.springframework.bootstrap.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
/**
* {@link EnableAutoConfiguration Auto-configuration} for an embedded servlet container.
@ -37,13 +38,21 @@ import org.springframework.context.annotation.Import;
* @author Dave Syer
*
*/
@Import(ServerPropertiesConfiguration.class)
public class EmbeddedContainerConfiguration {
public class EmbeddedContainerConfiguration implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// Don't import the classes directly because that might trigger loading them - use
// an import selector and the class name instead
return new String[] { ServerPropertiesConfiguration.class.getName(),
EmbeddedJettyAutoConfiguration.class.getName(),
EmbeddedTomcatAutoConfiguration.class.getName() };
}
@Configuration
@ConditionalOnClass({ Servlet.class, Server.class, Loader.class })
@ConditionalOnMissingBean(EmbeddedServletContainerFactory.class)
protected static class EmbeddedJettyAutoConfiguration {
public static class EmbeddedJettyAutoConfiguration {
@Bean
public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
@ -55,7 +64,7 @@ public class EmbeddedContainerConfiguration {
@Configuration
@ConditionalOnClass({ Servlet.class, Tomcat.class })
@ConditionalOnMissingBean(EmbeddedServletContainerFactory.class)
protected static class EmbeddedTomcatAutoConfiguration {
public static class EmbeddedTomcatAutoConfiguration {
@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {