Unified Exception Handling in Spring Boot with Custom Assertions and Enum‑Based Error Codes
This article explains how to implement a comprehensive unified exception handling mechanism in Spring Boot by using @ControllerAdvice, custom BaseException/BusinessException classes, enum‑based error codes, assertion utilities, and standardized response objects to simplify error management across controller and service layers.
The article introduces the problem of scattered try‑catch blocks in Java services and proposes a unified exception handling solution for Spring Boot applications.
It starts by describing the @ControllerAdvice annotation introduced in Spring 3.2 and how it can be combined with @ExceptionHandler to intercept exceptions thrown from any controller, eliminating the need for repetitive error handling code in each controller class.
A set of custom exception classes is defined: BaseException as the root, BusinessException for business‑level errors, and specific enums such as ResponseEnum that implement BusinessExceptionAssert . Each enum constant carries an error code and message , allowing developers to throw meaningful exceptions with a single line like ResponseEnum.LICENCE_NOT_FOUND.assertNotNull(licence) .
The core handler class UnifiedExceptionHandler is annotated with @ControllerAdvice , @Component , and conditional annotations to ensure it only loads in a web environment. It defines several @ExceptionHandler methods:
handleBusinessException and handleBaseException process custom business exceptions and return an ErrorResponse containing the enum‑defined code and localized message.
handleServletException catches a wide range of Spring MVC exceptions (e.g., NoHandlerFoundException , HttpRequestMethodNotSupportedException , MissingServletRequestParameterException ) and maps them to a generic server‑error code in production environments.
handleBindException and handleValidException aggregate validation errors into a single readable message.
handleException serves as a fallback for any unknown exception, returning a generic server‑error response in production.
The article also shows how to configure Spring to throw an exception for 404 errors by setting spring.mvc.throw-exception-if-no-handler-found=true and disabling static resource mappings.
Standard response structures are presented: BaseResponse with code and message , CommonResponse (adds data ), and QueryDataResponse (adds pagination fields). Convenience wrappers R and QR are introduced for concise API returns.
Finally, the article demonstrates the usage of the unified handling in a sample service LicenceService , showing how to validate inputs with enum assertions, retrieve data, and automatically get consistent error responses for missing entities, invalid parameters, or database failures.
@Slf4j
@Component
@ControllerAdvice
@ConditionalOnWebApplication
@ConditionalOnMissingBean(UnifiedExceptionHandler.class)
public class UnifiedExceptionHandler {
private static final String ENV_PROD = "prod";
@Autowired
private UnifiedMessageSource unifiedMessageSource;
@Value("${spring.profiles.active}")
private String profile;
// ... handler methods as described above ...
} public enum ResponseEnum implements BusinessExceptionAssert {
BAD_LICENCE_TYPE(7001, "Bad licence type."),
LICENCE_NOT_FOUND(7002, "Licence not found.");
private int code;
private String message;
// ... default methods for newException ...
}By centralizing exception handling, developers can focus on business logic, reduce boilerplate, and provide clear, localized error information to clients.
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.