Unified Exception Handling in Spring Boot Using @ControllerAdvice, Assert, and Enum‑Based Error Codes
The article explains how to replace repetitive try‑catch blocks with a unified exception handling mechanism in Spring Boot by leveraging @ControllerAdvice, custom BaseException, enum‑driven error codes, Assert utilities, and standardized response objects to improve code readability and maintainability.
In Java backend projects a large amount of try‑catch code makes the source noisy and hard to read; the article starts by showing the contrast between ugly try‑catch blocks and a clean controller style.
Unified Exception Handling
Spring 3.2 introduced @ControllerAdvice and @ExceptionHandler , which allow developers to define exception‑handling methods that are applied to all controllers, eliminating the need to repeat the same handling logic in each controller class.
Custom BaseException and Enum‑Based Errors
A BaseException class holds an error code and message . An interface IResponseEnum defines getCode() and getMessage() . By letting an enum implement BusinessExceptionAssert (which extends IResponseEnum and Assert ) each enum constant can create a specific BusinessException with its own code and message.
public interface BusinessExceptionAssert extends IResponseEnum, Assert {
default BaseException newException(Object... args) {
String msg = MessageFormat.format(this.getMessage(), args);
return new BusinessException(this, args, msg);
}
// similar method with Throwable
}Typical enum constants are BAD_LICENCE_TYPE(7001, "Bad licence type.") and LICENCE_NOT_FOUND(7002, "Licence not found.") . Using ResponseEnum.LICENCE_NOT_FOUND.assertNotNull(licence) replaces explicit null checks.
UnifiedExceptionHandler
The class annotated with @ControllerAdvice defines several @ExceptionHandler methods:
handleBusinessException – processes BusinessException .
handleBaseException – processes any other BaseException .
handleServletException – catches framework exceptions such as NoHandlerFoundException , HttpRequestMethodNotSupportedException , etc., maps them to a common response code, and hides internal details in production.
handleBindException / handleValidException – collect validation errors and return a combined message.
handleException – a fallback for unknown exceptions.
All handlers return an ErrorResponse containing code and message . In production the message is replaced by a generic one to avoid exposing internal details.
Making 404 Throw an Exception
By adding the following properties, Spring will throw NoHandlerFoundException for unmapped URLs instead of forwarding to the default Whitelabel error page:
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=falseStandardised Response Objects
All API responses inherit from BaseResponse (fields code and message ). CommonResponse adds a data field, while QueryDataResponse adds pagination fields. For brevity the project defines shortcut classes R<T> and QR<T> that wrap the data automatically.
Validation Example
A sample LicenceService demonstrates how to use the enum‑based asserts for null checks and licence‑type validation, how to call external services, and how the unified handler returns consistent error objects for missing licences, illegal licence types, validation failures, 404, method‑not‑allowed, and unexpected database errors.
The article concludes that combining Assert utilities, enum‑driven error definitions, and a global @ControllerAdvice covers the majority of exception scenarios in a Spring‑based backend, while leaving room for additional handling of security, gateway, and remote‑call errors.
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.