Remove @ControllerAdvice from BasicErrorController

Update the BasicErrorController so that it no longer needs to implement
@ControllerAdvice or have an @ExceptionHandler method.

A new ErrorAttributes interface is now used to obtain error details,
the DefaultErrorAttributes implementation uses a
HandlerExceptionResolver to obtain root exception details if the
`javax.servlet.error.*` attributes are missing.

This change also removes the need for the extract(...) method on
ErrorController as classes such as WebRequestTraceFilter can
now use the ErrorAttributes interface directly.

See gh-839, gh-538
Fixes gh-843
This commit is contained in:
Phillip Webb
2014-05-12 17:19:51 +01:00
parent 5dd77a725c
commit 30ac768cbf
15 changed files with 573 additions and 217 deletions

View File

@@ -34,7 +34,7 @@ import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoints;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.autoconfigure.web.ErrorController;
import org.springframework.boot.autoconfigure.web.ErrorAttributes;
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
@@ -125,12 +125,11 @@ public class EndpointWebMvcChildContextConfiguration {
/*
* The error controller is present but not mapped as an endpoint in this context
* because of the DispatcherServlet having had it's HandlerMapping explicitly
* disabled. So this tiny shim exposes the same feature but only for machine
* endpoints.
* disabled. So we expose the same feature but only for machine endpoints.
*/
@Bean
public ManagementErrorEndpoint errorEndpoint(final ErrorController controller) {
return new ManagementErrorEndpoint(this.errorPath, controller);
public ManagementErrorEndpoint errorEndpoint(final ErrorAttributes errorAttributes) {
return new ManagementErrorEndpoint(this.errorPath, errorAttributes);
}
@Configuration

View File

@@ -27,7 +27,7 @@ import org.springframework.boot.actuate.trace.WebRequestTraceFilter;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.web.BasicErrorController;
import org.springframework.boot.autoconfigure.web.ErrorAttributes;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.DispatcherServlet;
@@ -45,7 +45,7 @@ public class TraceWebFilterAutoConfiguration {
private TraceRepository traceRepository;
@Autowired(required = false)
private BasicErrorController errorController;
private ErrorAttributes errorAttributes;
@Value("${management.dump_requests:false}")
private boolean dumpRequests;
@@ -54,8 +54,8 @@ public class TraceWebFilterAutoConfiguration {
public WebRequestTraceFilter webRequestLoggingFilter(BeanFactory beanFactory) {
WebRequestTraceFilter filter = new WebRequestTraceFilter(this.traceRepository);
filter.setDumpRequests(this.dumpRequests);
if (this.errorController != null) {
filter.setErrorController(this.errorController);
if (this.errorAttributes != null) {
filter.setErrorAttributes(this.errorAttributes);
}
return filter;
}

View File

@@ -19,12 +19,12 @@ package org.springframework.boot.actuate.endpoint.mvc;
import java.util.Map;
import org.springframework.boot.actuate.endpoint.Endpoint;
import org.springframework.boot.autoconfigure.web.ErrorAttributes;
import org.springframework.boot.autoconfigure.web.ErrorController;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
/**
@@ -37,21 +37,21 @@ import org.springframework.web.context.request.RequestContextHolder;
@ConfigurationProperties(prefix = "error")
public class ManagementErrorEndpoint implements MvcEndpoint {
private final ErrorController controller;
private final ErrorAttributes errorAttributes;
private final String path;
public ManagementErrorEndpoint(String path, ErrorController controller) {
Assert.notNull(controller, "Controller must not be null");
public ManagementErrorEndpoint(String path, ErrorAttributes errorAttributes) {
Assert.notNull(errorAttributes, "ErrorAttributes must not be null");
this.path = path;
this.controller = controller;
this.errorAttributes = errorAttributes;
}
@RequestMapping
@ResponseBody
public Map<String, Object> invoke() {
RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
return this.controller.extract(attributes, false, true);
return this.errorAttributes.getErrorAttributes(
RequestContextHolder.currentRequestAttributes(), false);
}
@Override

View File

@@ -34,8 +34,9 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.autoconfigure.web.BasicErrorController;
import org.springframework.boot.autoconfigure.web.ErrorAttributes;
import org.springframework.core.Ordered;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -58,7 +59,7 @@ public class WebRequestTraceFilter implements Filter, Ordered {
private final ObjectMapper objectMapper = new ObjectMapper();
private BasicErrorController errorController;
private ErrorAttributes errorAttributes;
/**
* @param traceRepository
@@ -156,13 +157,13 @@ public class WebRequestTraceFilter implements Filter, Ordered {
trace.put("method", request.getMethod());
trace.put("path", request.getRequestURI());
trace.put("headers", allHeaders);
Throwable error = (Throwable) request
Throwable exception = (Throwable) request
.getAttribute("javax.servlet.error.exception");
if (error != null) {
if (this.errorController != null) {
trace.put("error", this.errorController.extract(
new ServletRequestAttributes(request), true, false));
}
if (exception != null && this.errorAttributes != null) {
RequestAttributes requestAttributes = new ServletRequestAttributes(request);
Map<String, Object> error = this.errorAttributes.getErrorAttributes(
requestAttributes, true);
trace.put("error", error);
}
return trace;
}
@@ -175,8 +176,8 @@ public class WebRequestTraceFilter implements Filter, Ordered {
public void destroy() {
}
public void setErrorController(BasicErrorController errorController) {
this.errorController = errorController;
public void setErrorAttributes(ErrorAttributes errorAttributes) {
this.errorAttributes = errorAttributes;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2013 the original author or authors.
* 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.
@@ -19,7 +19,7 @@ package org.springframework.boot.actuate.trace;
import java.util.Map;
import org.junit.Test;
import org.springframework.boot.autoconfigure.web.BasicErrorController;
import org.springframework.boot.autoconfigure.web.DefaulErrorAttributes;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
@@ -76,7 +76,7 @@ public class WebRequestTraceFilterTests {
@Test
public void filterHasError() {
this.filter.setErrorController(new BasicErrorController());
this.filter.setErrorAttributes(new DefaulErrorAttributes());
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
MockHttpServletResponse response = new MockHttpServletResponse();
response.setStatus(500);