diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java index f8d5a0335c2..7fe8ced57ef 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java @@ -19,6 +19,8 @@ package org.springframework.boot.autoconfigure.web; import java.io.File; import java.net.InetAddress; import java.util.Collection; +import java.util.HashMap; +import java.util.Map; import javax.validation.constraints.NotNull; @@ -33,6 +35,7 @@ import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletCont import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; +import org.springframework.boot.context.embedded.InitParameterConfiguringServletContextInitializer; import org.springframework.boot.context.embedded.Ssl; import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer; import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer; @@ -69,6 +72,8 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer { private final Tomcat tomcat = new Tomcat(); + private final Map contextParameters = new HashMap(); + public Tomcat getTomcat() { return this.tomcat; } @@ -145,6 +150,10 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer { this.ssl = ssl; } + public Map getContextParameters() { + return this.contextParameters; + } + public void setLoader(String value) { // no op to support Tomcat running as a traditional container (not embedded) } @@ -170,6 +179,9 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer { getTomcat() .customizeTomcat((TomcatEmbeddedServletContainerFactory) container); } + + container.addInitializers(new InitParameterConfiguringServletContextInitializer( + getContextParameters())); } public String[] getPathsArray(Collection paths) { diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/EmbeddedServletContainerAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/EmbeddedServletContainerAutoConfigurationTests.java index 43998ba32ea..57a328dea24 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/EmbeddedServletContainerAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/EmbeddedServletContainerAutoConfigurationTests.java @@ -17,6 +17,7 @@ package org.springframework.boot.autoconfigure.web; import javax.servlet.Servlet; +import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -30,6 +31,7 @@ import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomi import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.MockEmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.ServletRegistrationBean; +import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @@ -112,6 +114,19 @@ public class EmbeddedServletContainerAutoConfigurationTests { assertEquals(9000, getContainerFactory().getPort()); } + @Test + public void initParametersAreConfiguredOnTheServletContext() { + this.context = new AnnotationConfigEmbeddedWebApplicationContext(); + EnvironmentTestUtils.addEnvironment(this.context, + "server.context_parameters.a:alpha", "server.context_parameters.b:bravo"); + this.context.register(BaseConfiguration.class); + this.context.refresh(); + + ServletContext servletContext = this.context.getServletContext(); + assertEquals("alpha", servletContext.getInitParameter("a")); + assertEquals("bravo", servletContext.getInitParameter("b")); + } + private void verifyContext() { MockEmbeddedServletContainerFactory containerFactory = getContainerFactory(); Servlet servlet = this.context.getBean( diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 60153b8ba8d..36c2dad22ca 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -54,6 +54,7 @@ content into your application; rather pick only the properties that you need. server.port=8080 server.address= # bind to a specific NIC server.session-timeout= # session timeout in seconds + server.context-parameters.*= # Servlet context init parameters, e.g. server.context-parameters.a=alpha server.context-path= # the context path, defaults to '/' server.servlet-path= # the servlet path, defaults to '/' server.ssl.client-auth= # want or need diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/InitParameterConfiguringServletContextInitializer.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/InitParameterConfiguringServletContextInitializer.java new file mode 100644 index 00000000000..617384209a9 --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/InitParameterConfiguringServletContextInitializer.java @@ -0,0 +1,50 @@ +/* + * Copyright 2012-2014 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.boot.context.embedded; + +import java.util.Map; +import java.util.Map.Entry; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +/** + * A {@code ServletContextInitializer} that configures init parameters on the + * {@code ServletContext}. + * + * @author Andy Wilkinson + * @since 1.2.0 + * @see ServletContext#setInitParameter(String, String) + */ +public class InitParameterConfiguringServletContextInitializer implements + ServletContextInitializer { + + private final Map parameters; + + public InitParameterConfiguringServletContextInitializer( + Map parameters) { + this.parameters = parameters; + } + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + for (Entry entry : this.parameters.entrySet()) { + servletContext.setInitParameter(entry.getKey(), entry.getValue()); + } + } + +} diff --git a/spring-boot/src/test/java/org/springframework/boot/context/embedded/MockEmbeddedServletContainerFactory.java b/spring-boot/src/test/java/org/springframework/boot/context/embedded/MockEmbeddedServletContainerFactory.java index 9101376a88e..dec57b25671 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/embedded/MockEmbeddedServletContainerFactory.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/embedded/MockEmbeddedServletContainerFactory.java @@ -17,8 +17,11 @@ package org.springframework.boot.context.embedded; import java.util.ArrayList; +import java.util.Collections; import java.util.Enumeration; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.NoSuchElementException; import javax.servlet.Filter; @@ -42,6 +45,7 @@ import static org.mockito.Mockito.spy; * Mock {@link EmbeddedServletContainerFactory}. * * @author Phillip Webb + * @author Andy Wilkinson */ public class MockEmbeddedServletContainerFactory extends AbstractEmbeddedServletContainerFactory { @@ -51,7 +55,8 @@ public class MockEmbeddedServletContainerFactory extends @Override public EmbeddedServletContainer getEmbeddedServletContainer( ServletContextInitializer... initializers) { - this.container = spy(new MockEmbeddedServletContainer(initializers, getPort())); + this.container = spy(new MockEmbeddedServletContainer( + mergeInitializers(initializers), getPort())); return this.container; } @@ -119,8 +124,30 @@ public class MockEmbeddedServletContainerFactory extends return registeredFilter.getRegistration(); } }); + final Map initParameters = new HashMap(); + given(this.servletContext.setInitParameter(anyString(), anyString())) + .will(new Answer() { + @Override + public Void answer(InvocationOnMock invocation) + throws Throwable { + initParameters.put( + invocation.getArgumentAt(0, String.class), + invocation.getArgumentAt(1, String.class)); + return null; + } + + }); given(this.servletContext.getInitParameterNames()).willReturn( - MockEmbeddedServletContainer. emptyEnumeration()); + Collections.enumeration(initParameters.keySet())); + given(this.servletContext.getInitParameter(anyString())).willAnswer( + new Answer() { + @Override + public String answer(InvocationOnMock invocation) + throws Throwable { + return initParameters.get(invocation.getArgumentAt(0, + String.class)); + } + }); given(this.servletContext.getAttributeNames()).willReturn( MockEmbeddedServletContainer. emptyEnumeration()); given(this.servletContext.getNamedDispatcher("default")).willReturn(