I tried to customize the response at the time of error with Spring Boot, so I will describe it here as a memorandum. This time, I would like to customize the body part of the response as follows.
Change before
{
"timestamp": "2019-03-14T15:07:50.631+0000",
"status": 500,
"error": "Internal Server Error",
"message": "MyException occurred",
"path": "/××××/××××"
}
After change
{
"timestamp": "2019-03-14T15:07:50.631+0000",
"status": 500,
"error": "Internal Server Error",
"message": "MyException occurred",
"path": "/××××/××××",
"errorDetail": {
"detailMessage": "××××××××××××"
}
}
The following four characters are roughly the characters this time.
--Controller class that accepts requests --Original exception class --Class for response body --Class to catch the unique exception that occurred
In addition, the general flow of the process to be implemented from now on is as follows.
throw
from the controller a uniquely defined exception at the same time as the requestthrow
ed exception with the handle classAfter that, we will implement the above processing. (Although the order is out of order ...)
Here we define the mapping class for the response body.
ErrorResponseBody.java
package com.example.demo.errorResponse;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Setter;
import java.time.ZonedDateTime;
@Setter
public class ErrorResponseBody {
@JsonProperty("timestamp")
private ZonedDateTime exceptionOccurrenceTime;
@JsonProperty("status")
private int status;
@JsonProperty("error")
private String error;
@JsonProperty("message")
private String message;
@JsonProperty("path")
private String path;
@JsonProperty("errorDetail")
private ErrorDetail errorDetail;
}
ErrorDetail.java
package com.example.demo.errorResponse;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Setter;
@Setter
public class ErrorDetail {
@JsonProperty("detailMessage")
String detailMessage;
}
MyException.java
package com.example.demo.errorResponse;
import lombok.Getter;
@Getter
public class MyException extends RuntimeException {
private ErrorDetail errorDetails;
public MyException(String message, ErrorDetail errorDetails) {
super(message);
this.errorDetails = errorDetails;
}
}
HelloController.java
package com.example.demo.errorResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/exceptionhandle")
public class HelloController {
@RequestMapping("/test")
public String get() {
ErrorDetail errorDetail = new ErrorDetail();
errorDetail.setDetailMessage("Detailed message");
throw new MyException("MyException occurred", errorDetail);
}
}
This is the most important part. There are four points.
@RestControllerAdvice
annotation to the handle classResponseEntityExceptionHandler
class@ExceptionHandler
and specify the uniquely defined exception class to be supplemented.super.handleExceptionInternal
method (as an aside, the arguments of this method are in the following order).--Target exception class --Response body
And finally it returns ResponseEntity
.
HelloExceptionHandler.java
package com.example.demo.errorResponse;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import java.time.ZonedDateTime;
@RestControllerAdvice
public class HelloExceptionHandler extends ResponseEntityExceptionHandler {
//Catch MyException thrown from Controller
@ExceptionHandler(MyException.class)
public ResponseEntity<Object> handleMyException(MyException exception, WebRequest request) {
HttpHeaders headers = new HttpHeaders();
return super.handleExceptionInternal(exception,
createErrorResponseBody(exception, request),
headers,
HttpStatus.BAD_REQUEST,
request);
}
//Create the body part of the response
private ErrorResponseBody createErrorResponseBody(MyException exception, WebRequest request) {
ErrorResponseBody errorResponseBody = new ErrorResponseBody();
int responseCode = HttpStatus.BAD_REQUEST.value();
String responseErrorMessage = HttpStatus.BAD_REQUEST.getReasonPhrase();
String uri = ((ServletWebRequest) request).getRequest().getRequestURI();
errorResponseBody.setExceptionOccurrenceTime(ZonedDateTime.now());
errorResponseBody.setStatus(responseCode);
errorResponseBody.setError(responseErrorMessage);
errorResponseBody.setMessage(exception.getMessage());
errorResponseBody.setPath(uri);
errorResponseBody.setErrorDetail(exception.getErrorDetails());
return errorResponseBody;
}
}
As an aside, the handleExceptionInternal
method of the parent class ResponseEntityExceptionHandler
class looks like this: Since the part that passes the instance for error response is @Nullable Object body
, the body part will not be displayed unless it is passed properly.
ResponseEntityExceptionHandler.java
/**
* A single place to customize the response body of all Exception types.
* <p>The default implementation sets the {@link WebUtils#ERROR_EXCEPTION_ATTRIBUTE}
* request attribute and creates a {@link ResponseEntity} from the given
* body, headers, and status.
* @param ex the exception
* @param body the body for the response
* @param headers the headers for the response
* @param status the response status
* @param request the current request
*/
protected ResponseEntity<Object> handleExceptionInternal(
Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST);
}
return new ResponseEntity<>(body, headers, status);
}
{
"timestamp": "2019-03-18T10:11:13.795+09:00",
"status": 400,
"error": "Bad Request",
"message": "MyException occurred",
"path": "/exceptionhandle/test",
"errorDetail": {
"detailMessage": "Detailed message"
}
}
Customize REST API error response with Spring Boot (Part 2)
This time, I referred to the following article when writing the article.
Customize the error response of REST API created by Spring Boot Error handling with Spring Boot Handling exceptions with @ RestController of Spring Boot
Recommended Posts