Merge branch '1.3.x'
This commit is contained in:
commit
ae249f7568
|
|
@ -30,11 +30,14 @@ import org.apache.commons.logging.LogFactory;
|
|||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.ManagementServletContext;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
|
|
@ -55,6 +58,7 @@ import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfigurat
|
|||
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
|
@ -104,6 +108,8 @@ public class EndpointWebMvcAutoConfiguration
|
|||
private static final Log logger = LogFactory
|
||||
.getLog(EndpointWebMvcAutoConfiguration.class);
|
||||
|
||||
private static final ConfigurableListableBeanFactory BeanDefinitionRegistry = null;
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
|
@ -164,7 +170,7 @@ public class EndpointWebMvcAutoConfiguration
|
|||
}
|
||||
|
||||
private void createChildManagementContext() {
|
||||
final AnnotationConfigEmbeddedWebApplicationContext childContext = new AnnotationConfigEmbeddedWebApplicationContext();
|
||||
AnnotationConfigEmbeddedWebApplicationContext childContext = new AnnotationConfigEmbeddedWebApplicationContext();
|
||||
childContext.setParent(this.applicationContext);
|
||||
childContext.setNamespace("management");
|
||||
childContext.setId(this.applicationContext.getId() + ":management");
|
||||
|
|
@ -172,12 +178,30 @@ public class EndpointWebMvcAutoConfiguration
|
|||
PropertyPlaceholderAutoConfiguration.class,
|
||||
EmbeddedServletContainerAutoConfiguration.class,
|
||||
DispatcherServletAutoConfiguration.class);
|
||||
registerEmbeddedServletContainerFactory(childContext);
|
||||
CloseEventPropagationListener.addIfPossible(this.applicationContext,
|
||||
childContext);
|
||||
childContext.refresh();
|
||||
managementContextResolver().setApplicationContext(childContext);
|
||||
}
|
||||
|
||||
private void registerEmbeddedServletContainerFactory(
|
||||
AnnotationConfigEmbeddedWebApplicationContext childContext) {
|
||||
try {
|
||||
EmbeddedServletContainerFactory servletContainerFactory = this.applicationContext
|
||||
.getBean(EmbeddedServletContainerFactory.class);
|
||||
ConfigurableListableBeanFactory beanFactory = childContext.getBeanFactory();
|
||||
if (beanFactory instanceof BeanDefinitionRegistry) {
|
||||
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
|
||||
registry.registerBeanDefinition("embeddedServletContainerFactory",
|
||||
new RootBeanDefinition(servletContainerFactory.getClass()));
|
||||
}
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// Ignore and assume auto-configuration
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an alias for 'local.management.port' that actually resolves using
|
||||
* 'local.server.port'.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
* Copyright 2012-2016 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.
|
||||
|
|
@ -41,6 +41,7 @@ import org.springframework.messaging.MessageChannel;
|
|||
public class MetricsChannelAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ExportMetricWriter
|
||||
@ConditionalOnMissingBean
|
||||
public MessageChannelMetricWriter messageChannelMetricWriter(
|
||||
@Qualifier("metricsChannel") MessageChannel channel) {
|
||||
|
|
|
|||
|
|
@ -58,7 +58,9 @@ import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebAppl
|
|||
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerException;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer;
|
||||
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||
import org.springframework.boot.testutil.Matched;
|
||||
|
|
@ -176,6 +178,35 @@ public class EndpointWebMvcAutoConfigurationTests {
|
|||
assertAllClosed();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDifferentPortWithSpecificContainer() throws Exception {
|
||||
this.applicationContext.register(SpecificContainerConfig.class, RootConfig.class,
|
||||
DifferentPortConfig.class, EndpointConfig.class, BaseConfiguration.class,
|
||||
EndpointWebMvcAutoConfiguration.class, ErrorMvcAutoConfiguration.class);
|
||||
this.applicationContext.refresh();
|
||||
assertContent("/controller", ports.get().server, "controlleroutput");
|
||||
assertContent("/endpoint", ports.get().server, null);
|
||||
assertContent("/controller", ports.get().management, null);
|
||||
assertContent("/endpoint", ports.get().management, "endpointoutput");
|
||||
assertContent("/error", ports.get().management, startsWith("{"));
|
||||
ApplicationContext managementContext = this.applicationContext
|
||||
.getBean(ManagementContextResolver.class).getApplicationContext();
|
||||
List<?> interceptors = (List<?>) ReflectionTestUtils.getField(
|
||||
managementContext.getBean(EndpointHandlerMapping.class), "interceptors");
|
||||
assertThat(interceptors).hasSize(1);
|
||||
EmbeddedServletContainerFactory parentContainerFactory = this.applicationContext
|
||||
.getBean(EmbeddedServletContainerFactory.class);
|
||||
EmbeddedServletContainerFactory managementContainerFactory = managementContext
|
||||
.getBean(EmbeddedServletContainerFactory.class);
|
||||
assertThat(parentContainerFactory)
|
||||
.isInstanceOf(SpecificEmbeddedServletContainerFactory.class);
|
||||
assertThat(managementContainerFactory)
|
||||
.isInstanceOf(SpecificEmbeddedServletContainerFactory.class);
|
||||
assertThat(managementContainerFactory).isNotSameAs(parentContainerFactory);
|
||||
this.applicationContext.close();
|
||||
assertAllClosed();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDifferentPortAndContext() throws Exception {
|
||||
this.applicationContext.register(RootConfig.class, EndpointConfig.class,
|
||||
|
|
@ -609,6 +640,16 @@ public class EndpointWebMvcAutoConfigurationTests {
|
|||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class SpecificContainerConfig {
|
||||
|
||||
@Bean
|
||||
public SpecificEmbeddedServletContainerFactory embeddedServletContainerFactory() {
|
||||
return new SpecificEmbeddedServletContainerFactory();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(ServerPortConfig.class)
|
||||
public static class DifferentPortConfig {
|
||||
|
|
@ -636,6 +677,7 @@ public class EndpointWebMvcAutoConfigurationTests {
|
|||
}
|
||||
|
||||
protected static class TestInterceptor extends HandlerInterceptorAdapter {
|
||||
|
||||
private int count = 0;
|
||||
|
||||
@Override
|
||||
|
|
@ -648,6 +690,7 @@ public class EndpointWebMvcAutoConfigurationTests {
|
|||
public int getCount() {
|
||||
return this.count;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -728,4 +771,9 @@ public class EndpointWebMvcAutoConfigurationTests {
|
|||
|
||||
}
|
||||
|
||||
private static class SpecificEmbeddedServletContainerFactory
|
||||
extends TomcatEmbeddedServletContainerFactory {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ public class MetricExportAutoConfigurationTests {
|
|||
PropertyPlaceholderAutoConfiguration.class);
|
||||
MetricExporters exporter = this.context.getBean(MetricExporters.class);
|
||||
assertThat(exporter).isNotNull();
|
||||
assertThat(exporter.getExporters()).containsKey("messageChannelMetricWriter");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -961,14 +961,30 @@ public class ServerProperties
|
|||
|
||||
void customizeUndertow(ServerProperties serverProperties,
|
||||
UndertowEmbeddedServletContainerFactory factory) {
|
||||
factory.setBufferSize(this.bufferSize);
|
||||
factory.setBuffersPerRegion(this.buffersPerRegion);
|
||||
factory.setIoThreads(this.ioThreads);
|
||||
factory.setWorkerThreads(this.workerThreads);
|
||||
factory.setDirectBuffers(this.directBuffers);
|
||||
factory.setAccessLogDirectory(this.accesslog.dir);
|
||||
factory.setAccessLogPattern(this.accesslog.pattern);
|
||||
factory.setAccessLogEnabled(this.accesslog.enabled);
|
||||
if (this.bufferSize != null) {
|
||||
factory.setBufferSize(this.bufferSize);
|
||||
}
|
||||
if (this.buffersPerRegion != null) {
|
||||
factory.setBuffersPerRegion(this.buffersPerRegion);
|
||||
}
|
||||
if (this.ioThreads != null) {
|
||||
factory.setIoThreads(this.ioThreads);
|
||||
}
|
||||
if (this.workerThreads != null) {
|
||||
factory.setWorkerThreads(this.workerThreads);
|
||||
}
|
||||
if (this.directBuffers != null) {
|
||||
factory.setDirectBuffers(this.directBuffers);
|
||||
}
|
||||
if (this.accesslog.dir != null) {
|
||||
factory.setAccessLogDirectory(this.accesslog.dir);
|
||||
}
|
||||
if (this.accesslog.pattern != null) {
|
||||
factory.setAccessLogPattern(this.accesslog.pattern);
|
||||
}
|
||||
if (this.accesslog.enabled != null) {
|
||||
factory.setAccessLogEnabled(this.accesslog.enabled);
|
||||
}
|
||||
factory.setUseForwardHeaders(serverProperties.getOrDeduceUseForwardHeaders());
|
||||
}
|
||||
|
||||
|
|
@ -977,7 +993,7 @@ public class ServerProperties
|
|||
/**
|
||||
* Enable access log.
|
||||
*/
|
||||
private boolean enabled = false;
|
||||
private Boolean enabled;
|
||||
|
||||
/**
|
||||
* Format pattern for access logs.
|
||||
|
|
@ -989,11 +1005,11 @@ public class ServerProperties
|
|||
*/
|
||||
private File dir = new File("logs");
|
||||
|
||||
public boolean isEnabled() {
|
||||
public Boolean getEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ import org.springframework.mock.env.MockEnvironment;
|
|||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
|
|
@ -418,6 +419,14 @@ public class ServerPropertiesTests {
|
|||
verify(container).setSessionStoreDir(new File("myfolder"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void skipNullElementsForUndertow() throws Exception {
|
||||
UndertowEmbeddedServletContainerFactory container = mock(
|
||||
UndertowEmbeddedServletContainerFactory.class);
|
||||
this.properties.customize(container);
|
||||
verify(container, never()).setAccessLogEnabled(anyBoolean());
|
||||
}
|
||||
|
||||
private void bindProperties(Map<String, String> map) {
|
||||
new RelaxedDataBinder(this.properties, "server")
|
||||
.bind(new MutablePropertyValues(map));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright 2012-2016 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.jetty;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.handler.ErrorHandler;
|
||||
|
||||
/**
|
||||
* Variation of Jetty's {@link ErrorHandler} that supports all {@link HttpMethod
|
||||
* HttpMethods} rather than just {@code GET}, {@code POST} and {@code HEAD}. Jetty
|
||||
* <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=446039">intentionally only
|
||||
* supports a limited set of HTTP methods</a> for error pages, however, Spring Boot
|
||||
* prefers Tomcat, Jetty and Undertow to all behave in the same way.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class JettyEmbeddedErrorHandler extends ErrorHandler {
|
||||
|
||||
private final ErrorHandler delegate;
|
||||
|
||||
JettyEmbeddedErrorHandler(ErrorHandler delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request,
|
||||
HttpServletResponse response) throws IOException {
|
||||
String method = request.getMethod();
|
||||
if (!HttpMethod.GET.is(method) && !HttpMethod.POST.is(method)
|
||||
&& !HttpMethod.HEAD.is(method)) {
|
||||
request = new ErrorHttpServletRequest(request);
|
||||
}
|
||||
this.delegate.handle(target, baseRequest, request, response);
|
||||
}
|
||||
|
||||
private static class ErrorHttpServletRequest extends HttpServletRequestWrapper {
|
||||
|
||||
private boolean simulateGetMethod = true;
|
||||
|
||||
ErrorHttpServletRequest(HttpServletRequest request) {
|
||||
super(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod() {
|
||||
return (this.simulateGetMethod ? HttpMethod.GET.toString()
|
||||
: super.getMethod());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletContext getServletContext() {
|
||||
this.simulateGetMethod = false;
|
||||
return super.getServletContext();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -410,11 +410,14 @@ public class JettyEmbeddedServletContainerFactory
|
|||
*/
|
||||
private Configuration getErrorPageConfiguration() {
|
||||
return new AbstractConfiguration() {
|
||||
|
||||
@Override
|
||||
public void configure(WebAppContext context) throws Exception {
|
||||
ErrorHandler errorHandler = context.getErrorHandler();
|
||||
context.setErrorHandler(new JettyEmbeddedErrorHandler(errorHandler));
|
||||
addJettyErrorPages(errorHandler, getErrorPages());
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -424,6 +427,7 @@ public class JettyEmbeddedServletContainerFactory
|
|||
*/
|
||||
private Configuration getMimeTypeConfiguration() {
|
||||
return new AbstractConfiguration() {
|
||||
|
||||
@Override
|
||||
public void configure(WebAppContext context) throws Exception {
|
||||
MimeTypes mimeTypes = context.getMimeTypes();
|
||||
|
|
@ -432,6 +436,7 @@ public class JettyEmbeddedServletContainerFactory
|
|||
mapping.getMimeType());
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -334,6 +334,19 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
|||
assertThat(getResponse(getLocalUrl("/bang"))).isEqualTo("Hello World");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void errorPageFromPutRequest() throws Exception {
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
factory.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/hello"));
|
||||
this.container = factory.getEmbeddedServletContainer(exampleServletRegistration(),
|
||||
errorServletRegistration());
|
||||
this.container.start();
|
||||
assertThat(getResponse(getLocalUrl("/hello"), HttpMethod.PUT),
|
||||
equalTo("Hello World"));
|
||||
assertThat(getResponse(getLocalUrl("/bang"), HttpMethod.PUT),
|
||||
equalTo("Hello World"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicSslFromClassPath() throws Exception {
|
||||
testBasicSslWithKeyStore("classpath:test.jks");
|
||||
|
|
@ -869,7 +882,12 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
|||
|
||||
protected String getResponse(String url, String... headers)
|
||||
throws IOException, URISyntaxException {
|
||||
ClientHttpResponse response = getClientResponse(url, headers);
|
||||
return getResponse(url, HttpMethod.GET, headers);
|
||||
}
|
||||
|
||||
protected String getResponse(String url, HttpMethod method, String... headers)
|
||||
throws IOException, URISyntaxException {
|
||||
ClientHttpResponse response = getClientResponse(url, method, headers);
|
||||
try {
|
||||
return StreamUtils.copyToString(response.getBody(), Charset.forName("UTF-8"));
|
||||
}
|
||||
|
|
@ -881,7 +899,14 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
|||
protected String getResponse(String url,
|
||||
HttpComponentsClientHttpRequestFactory requestFactory, String... headers)
|
||||
throws IOException, URISyntaxException {
|
||||
ClientHttpResponse response = getClientResponse(url, requestFactory, headers);
|
||||
return getResponse(url, HttpMethod.GET, requestFactory, headers);
|
||||
}
|
||||
|
||||
protected String getResponse(String url, HttpMethod method,
|
||||
HttpComponentsClientHttpRequestFactory requestFactory, String... headers)
|
||||
throws IOException, URISyntaxException {
|
||||
ClientHttpResponse response = getClientResponse(url, method, requestFactory,
|
||||
headers);
|
||||
try {
|
||||
return StreamUtils.copyToString(response.getBody(), Charset.forName("UTF-8"));
|
||||
}
|
||||
|
|
@ -892,21 +917,27 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
|||
|
||||
protected ClientHttpResponse getClientResponse(String url, String... headers)
|
||||
throws IOException, URISyntaxException {
|
||||
return getClientResponse(url, new HttpComponentsClientHttpRequestFactory() {
|
||||
|
||||
@Override
|
||||
protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
|
||||
return AbstractEmbeddedServletContainerFactoryTests.this.httpClientContext;
|
||||
}
|
||||
|
||||
}, headers);
|
||||
return getClientResponse(url, HttpMethod.GET, headers);
|
||||
}
|
||||
|
||||
protected ClientHttpResponse getClientResponse(String url,
|
||||
protected ClientHttpResponse getClientResponse(String url, HttpMethod method,
|
||||
String... headers) throws IOException, URISyntaxException {
|
||||
return getClientResponse(url, method,
|
||||
new HttpComponentsClientHttpRequestFactory() {
|
||||
|
||||
@Override
|
||||
protected HttpContext createHttpContext(HttpMethod httpMethod,
|
||||
URI uri) {
|
||||
return AbstractEmbeddedServletContainerFactoryTests.this.httpClientContext;
|
||||
}
|
||||
|
||||
}, headers);
|
||||
}
|
||||
|
||||
protected ClientHttpResponse getClientResponse(String url, HttpMethod method,
|
||||
HttpComponentsClientHttpRequestFactory requestFactory, String... headers)
|
||||
throws IOException, URISyntaxException {
|
||||
ClientHttpRequest request = requestFactory.createRequest(new URI(url),
|
||||
HttpMethod.GET);
|
||||
ClientHttpRequest request = requestFactory.createRequest(new URI(url), method);
|
||||
request.getHeaders().add("Cookie", "JSESSIONID=" + "123");
|
||||
for (String header : headers) {
|
||||
String[] parts = header.split(":");
|
||||
|
|
|
|||
Loading…
Reference in New Issue