From 79b5dd3ae701649f4a926827db84a6b6c7d9ffc0 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 14 Nov 2018 15:50:53 -0800 Subject: [PATCH 1/3] Protect against NPE when collecting annotations Update `AnnotationsPropertySource` to ensure that `null` results from `findMergedAnnotation` are not added to the annotation list. Prior to this commit, if `findMergedAnnotation` returned `null` then `AnnotationsPropertySource.collectProperties` would throw an NPE. Although `findMergedAnnotation` should never return `null`, we're best off being defensive so that bugs such as SPR-17495 won't cause problems. Closes gh-15175 --- .../properties/AnnotationsPropertySource.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySource.java b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySource.java index 0cef66a3430..697f6082fc0 100644 --- a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySource.java +++ b/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); + } } } } From f2d649054819d07ed65acae44723c9d8dab77381 Mon Sep 17 00:00:00 2001 From: Ryan Scheidter Date: Wed, 14 Nov 2018 11:39:19 -0600 Subject: [PATCH 2/3] Fixed typo in maven site documentation Closes gh-15176 --- .../src/site/apt/examples/custom-layout.apt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/custom-layout.apt b/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/custom-layout.apt index 8ed1d734cc6..eb557747b42 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/custom-layout.apt +++ b/spring-boot-tools/spring-boot-maven-plugin/src/site/apt/examples/custom-layout.apt @@ -34,7 +34,7 @@ - com.example + com.example custom-layout 0.0.1.BUILD-SNAPSHOT From b60da5f85d9e0c06f33e76dae2eb9d9d8e66e9ef Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 14 Nov 2018 18:15:21 -0800 Subject: [PATCH 3/3] Allow early ServletRequest Autowiring Update `EmbeddedWebApplicationContext` so that Servlet related resolvable dependencies are registered in `postProcessBeanFactory`. This allows a `ServletReqest` to be autowired into an early initialized bean and brings parity with WAR based deployments. Closes gh-14990 --- .../EmbeddedWebApplicationContext.java | 20 +++++---- .../EmbeddedWebApplicationContextTests.java | 43 ++++++++++++++++++- 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContext.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContext.java index 436f3fc60eb..1611428d824 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContext.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContext.java @@ -114,6 +114,7 @@ public class EmbeddedWebApplicationContext extends GenericWebApplicationContext beanFactory.addBeanPostProcessor( new WebApplicationContextServletContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(ServletContextAware.class); + registerWebApplicationScopes(null); } @Override @@ -217,19 +218,22 @@ public class EmbeddedWebApplicationContext extends GenericWebApplicationContext private void selfInitialize(ServletContext servletContext) throws ServletException { prepareEmbeddedWebApplicationContext(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 * Servlet context. By default this method will first attempt to find diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContextTests.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContextTests.java index b40475407bd..5fa0bc259fb 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContextTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/EmbeddedWebApplicationContextTests.java @@ -41,12 +41,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.servlet.DelegatingFilterProxyRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean; @@ -466,7 +469,8 @@ public class EmbeddedWebApplicationContextTests { } @Test - public void doesNotReplaceExistingScopes() throws Exception { // gh-2082 + public void doesNotReplaceExistingScopes() throws Exception { + // gh-2082 Scope scope = mock(Scope.class); ConfigurableListableBeanFactory factory = this.context.getBeanFactory(); factory.registerScope(WebApplicationContext.SCOPE_REQUEST, scope); @@ -482,6 +486,29 @@ public class EmbeddedWebApplicationContextTests { .isSameAs(scope); } + @Test + public void servletRequestCanBeInjectedEarly() throws Exception { + // gh-14990 + addEmbeddedServletContainerFactoryBean(); + 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 addEmbeddedServletContainerFactoryBean() { this.context.registerBeanDefinition("embeddedServletContainerFactory", new RootBeanDefinition(MockEmbeddedServletContainerFactory.class)); @@ -534,4 +561,18 @@ public class EmbeddedWebApplicationContextTests { } + protected static class WithAutowiredServletRequest { + + private final ServletRequest request; + + public WithAutowiredServletRequest(ServletRequest request) { + this.request = request; + } + + public ServletRequest getRequest() { + return this.request; + } + + } + }