GlobalExceptionHandler.java
package com.github.can019.global.handler;
import com.github.can019.global.exception.ApplicationException;
import com.github.can019.global.exception.UnknownException;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.ThreadContext;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.*;
import org.springframework.lang.Nullable;
import org.springframework.web.ErrorResponse;
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;
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(RuntimeException.class)
public ResponseEntity handleRuntimeException(RuntimeException ex, WebRequest webRequest) {
HttpHeaders headers = new HttpHeaders();
return handleExceptionInternal(ex, null, headers, HttpStatus.INTERNAL_SERVER_ERROR, webRequest);
}
@Override
protected ResponseEntity<Object> handleExceptionInternal(
Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatusCode statusCode, WebRequest request) {
if (request instanceof ServletWebRequest servletWebRequest) {
HttpServletResponse response = servletWebRequest.getResponse();
if (response != null && response.isCommitted()) {
log.warn("Response already committed. Ignoring: {}", ex);
return null;
}
}
if (statusCode.equals(HttpStatus.INTERNAL_SERVER_ERROR) && body == null && !(ex instanceof ErrorResponse)) {
// 때에 따라 github or slack에 publish?
// log.error("Fatal error occurred {}", ex.getCause());
ex = new UnknownException(ex);
}
if (body == null && ex instanceof ErrorResponse errorResponse) {
if(ex instanceof ServletException){
errorResponse.getBody().setProperty("code", ExceptionCode.SERVLET_WEB_REQUEST_ERROR_CODE.getExceptionCode());
} else if(ex instanceof ApplicationException){
errorResponse.getBody().setProperty("code", ExceptionCode.APPLICATION_ERROR_CODE.getExceptionCode());
} else{
log.error("[FATAL] {} {}", ex.getMessage(), ex.getStackTrace()[0]);
errorResponse.getBody().setProperty("code", ExceptionCode.FATAL_ERROR_CODE.getExceptionCode());
}
errorResponse.getBody().setProperty("uuid", ThreadContext.get("id"));
body = errorResponse.updateAndGetBody(getMessageSource(), LocaleContextHolder.getLocale());
}
return createResponseEntity(body, headers, statusCode, request);
}
private enum ExceptionCode {
SERVLET_WEB_REQUEST_ERROR_CODE("EX1"),
APPLICATION_ERROR_CODE("EX2"),
FATAL_ERROR_CODE("EX3");
private String exceptionCode;
ExceptionCode(String exceptionCode){
this.exceptionCode = exceptionCode;
}
public String getExceptionCode(){
return exceptionCode;
}
}
}