Commit 05cf6867 authored by Andy Wilkinson's avatar Andy Wilkinson

Allow servlet context parmeters to be configured via declaratively

Previously, configuration of a ServletContext init parameter required
the use of a ServletContextInitializer bean. This commmit adds
support for declarative configuration via the environment using
server.context_parameters.<name>=<value>.

Closes gh-1791
parent e0a0af43
...@@ -19,6 +19,8 @@ package org.springframework.boot.autoconfigure.web; ...@@ -19,6 +19,8 @@ package org.springframework.boot.autoconfigure.web;
import java.io.File; import java.io.File;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
...@@ -33,6 +35,7 @@ import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletCont ...@@ -33,6 +35,7 @@ import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletCont
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor; import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; 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.Ssl;
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer; import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer; import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
...@@ -69,6 +72,8 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer { ...@@ -69,6 +72,8 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
private final Tomcat tomcat = new Tomcat(); private final Tomcat tomcat = new Tomcat();
private final Map<String, String> contextParameters = new HashMap<String, String>();
public Tomcat getTomcat() { public Tomcat getTomcat() {
return this.tomcat; return this.tomcat;
} }
...@@ -145,6 +150,10 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer { ...@@ -145,6 +150,10 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
this.ssl = ssl; this.ssl = ssl;
} }
public Map<String, String> getContextParameters() {
return this.contextParameters;
}
public void setLoader(String value) { public void setLoader(String value) {
// no op to support Tomcat running as a traditional container (not embedded) // no op to support Tomcat running as a traditional container (not embedded)
} }
...@@ -170,6 +179,9 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer { ...@@ -170,6 +179,9 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
getTomcat() getTomcat()
.customizeTomcat((TomcatEmbeddedServletContainerFactory) container); .customizeTomcat((TomcatEmbeddedServletContainerFactory) container);
} }
container.addInitializers(new InitParameterConfiguringServletContextInitializer(
getContextParameters()));
} }
public String[] getPathsArray(Collection<String> paths) { public String[] getPathsArray(Collection<String> paths) {
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
package org.springframework.boot.autoconfigure.web; package org.springframework.boot.autoconfigure.web;
import javax.servlet.Servlet; import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
...@@ -30,6 +31,7 @@ import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomi ...@@ -30,6 +31,7 @@ import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomi
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.MockEmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.MockEmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
...@@ -112,6 +114,19 @@ public class EmbeddedServletContainerAutoConfigurationTests { ...@@ -112,6 +114,19 @@ public class EmbeddedServletContainerAutoConfigurationTests {
assertEquals(9000, getContainerFactory().getPort()); 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() { private void verifyContext() {
MockEmbeddedServletContainerFactory containerFactory = getContainerFactory(); MockEmbeddedServletContainerFactory containerFactory = getContainerFactory();
Servlet servlet = this.context.getBean( Servlet servlet = this.context.getBean(
......
...@@ -54,6 +54,7 @@ content into your application; rather pick only the properties that you need. ...@@ -54,6 +54,7 @@ content into your application; rather pick only the properties that you need.
server.port=8080 server.port=8080
server.address= # bind to a specific NIC server.address= # bind to a specific NIC
server.session-timeout= # session timeout in seconds 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.context-path= # the context path, defaults to '/'
server.servlet-path= # the servlet path, defaults to '/' server.servlet-path= # the servlet path, defaults to '/'
server.ssl.client-auth= # want or need server.ssl.client-auth= # want or need
......
/*
* 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<String, String> parameters;
public InitParameterConfiguringServletContextInitializer(
Map<String, String> parameters) {
this.parameters = parameters;
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
for (Entry<String, String> entry : this.parameters.entrySet()) {
servletContext.setInitParameter(entry.getKey(), entry.getValue());
}
}
}
...@@ -17,8 +17,11 @@ ...@@ -17,8 +17,11 @@
package org.springframework.boot.context.embedded; package org.springframework.boot.context.embedded;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import javax.servlet.Filter; import javax.servlet.Filter;
...@@ -42,6 +45,7 @@ import static org.mockito.Mockito.spy; ...@@ -42,6 +45,7 @@ import static org.mockito.Mockito.spy;
* Mock {@link EmbeddedServletContainerFactory}. * Mock {@link EmbeddedServletContainerFactory}.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Andy Wilkinson
*/ */
public class MockEmbeddedServletContainerFactory extends public class MockEmbeddedServletContainerFactory extends
AbstractEmbeddedServletContainerFactory { AbstractEmbeddedServletContainerFactory {
...@@ -51,7 +55,8 @@ public class MockEmbeddedServletContainerFactory extends ...@@ -51,7 +55,8 @@ public class MockEmbeddedServletContainerFactory extends
@Override @Override
public EmbeddedServletContainer getEmbeddedServletContainer( public EmbeddedServletContainer getEmbeddedServletContainer(
ServletContextInitializer... initializers) { ServletContextInitializer... initializers) {
this.container = spy(new MockEmbeddedServletContainer(initializers, getPort())); this.container = spy(new MockEmbeddedServletContainer(
mergeInitializers(initializers), getPort()));
return this.container; return this.container;
} }
...@@ -119,8 +124,30 @@ public class MockEmbeddedServletContainerFactory extends ...@@ -119,8 +124,30 @@ public class MockEmbeddedServletContainerFactory extends
return registeredFilter.getRegistration(); return registeredFilter.getRegistration();
} }
}); });
final Map<String, String> initParameters = new HashMap<String, String>();
given(this.servletContext.setInitParameter(anyString(), anyString()))
.will(new Answer<Void>() {
@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( given(this.servletContext.getInitParameterNames()).willReturn(
MockEmbeddedServletContainer.<String> emptyEnumeration()); Collections.enumeration(initParameters.keySet()));
given(this.servletContext.getInitParameter(anyString())).willAnswer(
new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation)
throws Throwable {
return initParameters.get(invocation.getArgumentAt(0,
String.class));
}
});
given(this.servletContext.getAttributeNames()).willReturn( given(this.servletContext.getAttributeNames()).willReturn(
MockEmbeddedServletContainer.<String> emptyEnumeration()); MockEmbeddedServletContainer.<String> emptyEnumeration());
given(this.servletContext.getNamedDispatcher("default")).willReturn( given(this.servletContext.getNamedDispatcher("default")).willReturn(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment