Reputation: 576
By default Spring Boot maps /error
to BasicErrorController
. I want to log the exception along with the request that causes the exception. How can I get the original request in BasicErrorController
or a new CustomErrorController
. It seems that Spring Boot will make a new request to /error
when an exception is thrown and the orginal request info is gone or no way to map the error with the original request.
Upvotes: 13
Views: 6378
Reputation: 602
@Override
@ResponseStatus(HttpStatus.BAD_REQUEST)
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException exception,
HttpHeaders headers,
HttpStatus status,
WebRequest request) {
OriginalRequestObject originalRequest = (OriginalRequestObject) exception.getBindingResult().getTarget();
ErrorResponse errorResponse = new ErrorResponse(
status.value(),
originalRequest.getId() + " " + exception.getMessage());
return ResponseEntity.status(status).body(myErrorResponse);
}
Upvotes: 0
Reputation: 1044
Here is a working example:
@RestController
public class MyErrorController implements ErrorController {
private static final Logger LOG = LoggerFactory.getLogger(MyErrorController.class);
private static final String PATH = "/error";
private final ErrorAttributes errorAttributes;
public MyErrorController(ErrorAttributes errorAttributes) {
this.errorAttributes = errorAttributes;
}
@RequestMapping(value = PATH)
public ErrorDTO error(WebRequest webRequest, HttpServletRequest httpServletRequest) {
// Appropriate HTTP response code (e.g. 404 or 500) is automatically set by Spring.
Map<String, Object> attrs = errorAttributes.getErrorAttributes(webRequest, ErrorAttributeOptions.defaults());
LOG.warn("Forwarded Error Request: {} ", attrs.get("path"), (Throwable)
httpServletRequest.getAttribute("javax.servlet.error.exception"));
ErrorDTO dto = new ErrorDTO();
dto.message = (String) attrs.get("error");
dto.path = (String) attrs.get("path");
dto.timestamp = attrs.get("timestamp").toString();
return dto;
}
}
Upvotes: 0
Reputation: 935
Get it by:
String url = (String) request.getAttribute(RequestDispatcher.ERROR_REQUEST_URI);
Upvotes: 12
Reputation: 3696
If you are using controller advice to handle your exceptions then method with @ExceptionHandler can inject request as parameter, something like :
@ControllerAdvice
public class YourExceptionHandler
{
@ExceptionHandler
public ResponseEntity handleExceptions(HttpServletRequest request, Exception exception)
{
// use request to populate error object with details like requestId
LOGGER.debug(String.valueOf(request));
LOGGER.error(exception.getMessage(), exception);
}
}
Upvotes: 0
Reputation: 576
To avoid any misleading information, Spring Boot DOES NOT make a new request to /error
endpoint. Instead, it wraps the exception in the original request and forwards it to /error
endpoint. The request will be processed by BasicErrorHandler
if you don't provide a custom error handler.
In this case, if you are using an interceptor
, the interceptor will be invoked twice - one for the original request and the other for the forwarded request.
To retrieve the original request information, please look into the forwarded request's attributes. Basically, you can get the error message from these attributes javax.servlet.error.message, javax.servlet.error.status_code, org.springframework.web.servlet.DispatcherServlet.EXCEPTION
.
And these are some resources that are related to error handling in Spring Boot:
Upvotes: 5