I have seen many projects in SpringBoot has written with multiple Exception classes. This is a huge mistake, hence thus this leads to
***************************************************************************
import java.util.Date;
import java.util.List;
import org.springframework.http.HttpStatus;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
- accumulation of Exception classes
- and hence methods are being getting longer with so many exceptions at the end.
Another issue is some people has written error code inside the error message. This is mostly due to not understanding how to make custom error object.
Below will sample code explaining adding a global exception and a custom error object with error message, error code etc.
What we create in this example
1. Custom error object = ApiError.java
2. Custom exception class = CustomException
3. Handler class to handle the global exception = GlobalExceptionHandler
Important:
I'm using "Lombok" , so all getter, setter, builder code is being generated by Lombok.
Important:
I'm using "Lombok" , so all getter, setter, builder code is being generated by Lombok.
***************************************************************************
import java.util.Date;
import java.util.List;
import org.springframework.http.HttpStatus;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class ApiError{
private HttpStatus status;
private String code;
private String message;
private List errors;
private String path;
private Date timeStamp;
private String source;
}
-------------------------------------------------------------------------------------
public class CustomException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1581305064814093777L;
/**
* error code for the {@link CustomException}
*/
private String code;
public CustomException() {
super();
}
public CustomException(final String message) {
super(message);
}
public CustomException(final String errorCode, final String message) {
super(message);
this.code = errorCode;
}
public CustomException(final String message, final Throwable cause) {
super(message, cause);
}
public CustomException(final String code, final String message, final Throwable cause) {
super(message, cause);
this.code = code;
}
public CustomException(final Throwable cause) {
super(cause);
}
/**
* Custom error code for the REST project.Code consist of 10 digits. Below is
* the breakdown of the code description.
*
* @return error code for specific error.
*/
public String getCode() {
return code;
}
}
--------------------------------------------------------------------------------------------------------
import java.util.Arrays;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
/**
* Common exception handler for REST.
*
* @author AMAL PRASAD
* @version 1.0.0
* @since 1.0.0
*/
@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
private static final String REQUEST_PATH = "org.springframework.web.servlet.HandlerMapping.pathWithinHandlerMapping";
private static final String SOURCE = "REST";
/**
* Handle all the exceptions inside REST project.
*
* @param ex {@link Exception} occurs inside REST project
* @param request Incoming request to REST project.
* @param servReq Incoming request to REST project
* @return response of type {@link ResponseEntity}.
*/
@ExceptionHandler({ Exception.class })
public ResponseEntity
final HttpServletRequest servReq) {
logger.info(ex.getClass().getName());
logger.error("error", ex);
CustomException customException = null;
if (ex instanceof CustomException) {
customException = (CustomException) ex;
} else {
throw new IllegalStateException(HttpStatus.INTERNAL_SERVER_ERROR.name());
}
final ApiError apiError = ApiError.builder().status(HttpStatus.INTERNAL_SERVER_ERROR)
.code(customException.getCode()).message(ex.getLocalizedMessage())
.errors(Arrays.asList("error occurred")).path(servReq.getAttribute(REQUEST_PATH).toString())
.source(SOURCE).timeStamp(new Date()).build();
return new ResponseEntity
}
}
private HttpStatus status;
private String code;
private String message;
private List
private String path;
private Date timeStamp;
private String source;
}
-------------------------------------------------------------------------------------
public class CustomException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1581305064814093777L;
/**
* error code for the {@link CustomException}
*/
private String code;
public CustomException() {
super();
}
public CustomException(final String message) {
super(message);
}
public CustomException(final String errorCode, final String message) {
super(message);
this.code = errorCode;
}
public CustomException(final String message, final Throwable cause) {
super(message, cause);
}
public CustomException(final String code, final String message, final Throwable cause) {
super(message, cause);
this.code = code;
}
public CustomException(final Throwable cause) {
super(cause);
}
/**
* Custom error code for the REST project.Code consist of 10 digits. Below is
* the breakdown of the code description.
*
* @return error code for specific error.
*/
public String getCode() {
return code;
}
}
--------------------------------------------------------------------------------------------------------
import java.util.Arrays;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
/**
* Common exception handler for REST.
*
* @author AMAL PRASAD
* @version 1.0.0
* @since 1.0.0
*/
@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
private static final String REQUEST_PATH = "org.springframework.web.servlet.HandlerMapping.pathWithinHandlerMapping";
private static final String SOURCE = "REST";
/**
* Handle all the exceptions inside REST project.
*
* @param ex {@link Exception} occurs inside REST project
* @param request Incoming request to REST project.
* @param servReq Incoming request to REST project
* @return response of type {@link ResponseEntity}.
*/
@ExceptionHandler({ Exception.class })
public ResponseEntity
final HttpServletRequest servReq) {
logger.info(ex.getClass().getName());
logger.error("error", ex);
CustomException customException = null;
if (ex instanceof CustomException) {
customException = (CustomException) ex;
} else {
throw new IllegalStateException(HttpStatus.INTERNAL_SERVER_ERROR.name());
}
final ApiError apiError = ApiError.builder().status(HttpStatus.INTERNAL_SERVER_ERROR)
.code(customException.getCode()).message(ex.getLocalizedMessage())
.errors(Arrays.asList("error occurred")).path(servReq.getAttribute(REQUEST_PATH).toString())
.source(SOURCE).timeStamp(new Date()).build();
return new ResponseEntity
}
}