diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySource.java b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySource.java index 40a04d0c86e..c28af2b6bbd 100644 --- a/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySource.java +++ b/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySource.java @@ -90,8 +90,11 @@ public class AnnotationsPropertySource extends EnumerablePropertySource if (annotations != null) { for (Annotation annotation : annotations) { if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation)) { - mergedAnnotations - .add(findMergedAnnotation(root, annotation.annotationType())); + Annotation mergedAnnotation = findMergedAnnotation(root, + annotation.annotationType()); + if (mergedAnnotation != null) { + mergedAnnotations.add(mergedAnnotation); + } } } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/custom-layout.apt b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/custom-layout.apt index 5d18f8000bc..2cffd8f0295 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/custom-layout.apt +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/custom-layout.apt @@ -35,7 +35,7 @@ - com.example + com.example custom-layout 0.0.1.BUILD-SNAPSHOT diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/context/ServletWebServerApplicationContext.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/context/ServletWebServerApplicationContext.java index cdcd6666bac..0e0456618ed 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/context/ServletWebServerApplicationContext.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/context/ServletWebServerApplicationContext.java @@ -132,6 +132,7 @@ public class ServletWebServerApplicationContext extends GenericWebApplicationCon beanFactory.addBeanPostProcessor( new WebApplicationContextServletContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(ServletContextAware.class); + registerWebApplicationScopes(null); } @Override @@ -226,19 +227,22 @@ public class ServletWebServerApplicationContext extends GenericWebApplicationCon private void selfInitialize(ServletContext servletContext) throws ServletException { prepareWebApplicationContext(servletContext); - ConfigurableListableBeanFactory beanFactory = getBeanFactory(); - ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes( - beanFactory); - WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, - getServletContext()); - existingScopes.restore(); - WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, - getServletContext()); + registerWebApplicationScopes(servletContext); + WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), + servletContext); for (ServletContextInitializer beans : getServletContextInitializerBeans()) { beans.onStartup(servletContext); } } + private void registerWebApplicationScopes(ServletContext servletContext) { + ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes( + getBeanFactory()); + WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory(), + servletContext); + existingScopes.restore(); + } + /** * Returns {@link ServletContextInitializer}s that should be used with the embedded * web server. By default this method will first attempt to find diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/ServletWebServerApplicationContextTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/ServletWebServerApplicationContextTests.java index 0887236ec97..237d1874836 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/ServletWebServerApplicationContextTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/context/ServletWebServerApplicationContextTests.java @@ -37,12 +37,15 @@ import org.mockito.Captor; import org.mockito.InOrder; import org.mockito.MockitoAnnotations; +import org.springframework.beans.BeansException; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.beans.factory.config.Scope; +import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer; import org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean; @@ -443,7 +446,8 @@ public class ServletWebServerApplicationContextTests { } @Test - public void doesNotReplaceExistingScopes() { // gh-2082 + public void doesNotReplaceExistingScopes() { + // gh-2082 Scope scope = mock(Scope.class); ConfigurableListableBeanFactory factory = this.context.getBeanFactory(); factory.registerScope(WebApplicationContext.SCOPE_REQUEST, scope); @@ -456,6 +460,29 @@ public class ServletWebServerApplicationContextTests { .isSameAs(scope); } + @Test + public void servletRequestCanBeInjectedEarly() throws Exception { + // gh-14990 + addWebServerFactoryBean(); + RootBeanDefinition beanDefinition = new RootBeanDefinition( + WithAutowiredServletRequest.class); + beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR); + this.context.registerBeanDefinition("withAutowiredServletRequest", + beanDefinition); + this.context.addBeanFactoryPostProcessor(new BeanFactoryPostProcessor() { + + @Override + public void postProcessBeanFactory( + ConfigurableListableBeanFactory beanFactory) throws BeansException { + WithAutowiredServletRequest bean = beanFactory + .getBean(WithAutowiredServletRequest.class); + assertThat(bean.getRequest()).isNotNull(); + } + + }); + this.context.refresh(); + } + private void addWebServerFactoryBean() { this.context.registerBeanDefinition("webServerFactory", new RootBeanDefinition(MockServletWebServerFactory.class)); @@ -508,4 +535,18 @@ public class ServletWebServerApplicationContextTests { } + protected static class WithAutowiredServletRequest { + + private final ServletRequest request; + + public WithAutowiredServletRequest(ServletRequest request) { + this.request = request; + } + + public ServletRequest getRequest() { + return this.request; + } + + } + }