Mastering Unified Exception Handling in Spring: Clean Code, Enums, and Assertions
This article explains how to replace repetitive try‑catch blocks in Java Spring applications with a unified exception handling strategy that leverages @ControllerAdvice, custom enums, and assertion utilities, providing clean, maintainable code, internationalized error messages, and consistent response structures for both business and system errors.
Core Concepts
BaseException : custom runtime exception carrying a IResponseEnum (code and message) and optional arguments.
ResponseEnum : enum defining error codes and default messages, e.g. BAD_LICENCE_TYPE(7001, "Bad licence type.").
Assert interface : default‑method interface providing assertNotNull etc., which creates a BaseException when a condition fails.
UnifiedExceptionHandler : a @ControllerAdvice class that catches Spring MVC exceptions (404, method not supported, binding errors) and custom BusinessException / BaseException, converting them into a uniform JSON error response.
Implementation Highlights
Define the exception hierarchy:
public class BaseException extends RuntimeException {
private final IResponseEnum responseEnum;
private final Object[] args;
public BaseException(IResponseEnum responseEnum, Object... args) {
super(responseEnum.getMessage());
this.responseEnum = responseEnum;
this.args = args;
}
public IResponseEnum getResponseEnum() { return responseEnum; }
public Object[] getArgs() { return args; }
}
public interface IResponseEnum {
int getCode();
String getMessage();
}
public enum ResponseEnum implements IResponseEnum {
BAD_LICENCE_TYPE(7001, "Bad licence type."),
LICENCE_NOT_FOUND(7002, "Licence not found.");
private final int code;
private final String message;
ResponseEnum(int code, String message) { this.code = code; this.message = message; }
public int getCode() { return code; }
public String getMessage() { return message; }
public void assertNotNull(Object obj) {
if (obj == null) {
throw new BusinessException(this);
}
}
}
public class BusinessException extends BaseException {
public BusinessException(IResponseEnum responseEnum, Object... args) {
super(responseEnum, args);
}
}Unified exception handler (simplified):
@Slf4j
@RestControllerAdvice
public class UnifiedExceptionHandler {
@ExceptionHandler(BusinessException.class)
public ErrorResponse handleBusinessException(BusinessException e) {
log.error(e.getMessage(), e);
return new ErrorResponse(e.getResponseEnum().getCode(), e.getMessage());
}
@ExceptionHandler(NoHandlerFoundException.class)
public ErrorResponse handleNotFound(NoHandlerFoundException e) {
log.error(e.getMessage(), e);
return new ErrorResponse(CommonResponseEnum.SERVER_ERROR.getCode(),
"Resource not found");
}
@ExceptionHandler(Exception.class)
public ErrorResponse handleException(Exception e) {
log.error(e.getMessage(), e);
return new ErrorResponse(CommonResponseEnum.SERVER_ERROR.getCode(),
"Internal server error");
}
}Configuration to make Spring throw NoHandlerFoundException for 404:
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=falseUsage in Service Layer
Instead of explicit if (obj == null) throw new IllegalArgumentException(...), use the enum‑based assertion:
public LicenceDTO queryDetail(Long licenceId) {
Licence licence = this.getById(licenceId);
ResponseEnum.LICENCE_NOT_FOUND.assertNotNull(licence);
// business logic …
}All controllers can rely on the global handler to translate any thrown BusinessException or Spring MVC exception into a consistent JSON payload containing code, message (and optional data).
Result
The approach removes duplicated try‑catch code, centralises error‑code definitions, supports internationalised messages, and provides a uniform response format { "code":…, "message":…, "data":… }. It works for both business‑level errors (e.g., licence not found) and system‑level errors (404, method not supported), and can hide technical details in production environments.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
