Backend Development 20 min read

Elegant Unified Exception Handling in Spring Using Assertions and Enums

This article explains how to replace repetitive try‑catch blocks in Spring applications with a clean, assertion‑based approach combined with @ControllerAdvice and enum‑driven error codes, providing a unified way to handle service‑layer, controller‑layer, and unknown exceptions while keeping responses consistent and internationalized.

Architecture Digest
Architecture Digest
Architecture Digest
Elegant Unified Exception Handling in Spring Using Assertions and Enums

In Java backend development, excessive try { ... } catch { ... } finally { ... } blocks hurt readability; the author advocates a more elegant style that moves exception handling out of business code.

The core idea is to use Spring's @ControllerAdvice together with custom @ExceptionHandler methods to centralize handling of all exceptions, and to replace explicit if (obj == null) throw new … checks with assertion utilities.

Spring 3.2 introduced @ControllerAdvice , which can apply an @ExceptionHandler to every controller. By defining a unified exception handler class annotated with @ControllerAdvice , the application can catch:

Servlet‑level errors (404, method not supported, media type errors, missing parameters, etc.)

Business exceptions derived from a custom BaseException

Unknown runtime exceptions

To avoid writing many custom exception classes, the article proposes an Assert interface with default methods that delegate to a newException factory. Implementations combine an enum (implementing IResponseEnum ) with the Assert interface, so each enum constant defines an error code and message. Example:

public interface Assert {
    BaseException newException(Object... args);
    BaseException newException(Throwable t, Object... args);
    default void assertNotNull(Object obj) {
        if (obj == null) {
            throw newException(obj);
        }
    }
    default void assertNotNull(Object obj, Object... args) {
        if (obj == null) {
            throw newException(args);
        }
    }
}

The enum implements both IResponseEnum and Assert :

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;
    @Override
    public BaseException newException(Object... args) {
        String msg = MessageFormat.format(this.getMessage(), args);
        return new BusinessException(this, args, msg);
    }
    @Override
    public BaseException newException(Throwable t, Object... args) {
        String msg = MessageFormat.format(this.getMessage(), args);
        return new BusinessException(this, args, msg, t);
    }
}

Using the enum in service code becomes concise:

private void checkNotNull(Licence licence) {
    ResponseEnum.LICENCE_NOT_FOUND.assertNotNull(licence);
}

The unified handler class ( UnifiedExceptionHandler ) defines methods such as:

@ExceptionHandler(BusinessException.class)
@ResponseBody
public ErrorResponse handleBusinessException(BaseException e) {
    log.error(e.getMessage(), e);
    return new ErrorResponse(e.getResponseEnum().getCode(), getMessage(e));
}

@ExceptionHandler({ NoHandlerFoundException.class, HttpRequestMethodNotSupportedException.class, ... })
@ResponseBody
public ErrorResponse handleServletException(Exception e) {
    // map exception class to enum, return appropriate code/message
}

For production environments the handler hides detailed stack traces and returns a generic "Network error" message.

The article also shows how to configure Spring to throw an exception for unmapped URLs ( spring.mvc.throw-exception-if-no-handler-found=true ) so that 404s are processed by the same handler.

Finally, a complete test scenario is presented: querying licences, adding licences, and triggering various errors (missing licence, invalid licence type, request method not supported, parameter validation failures, database schema mismatch). Screenshots demonstrate that each error is captured and returned as a JSON object containing code and message .

In summary, by combining assertions, enums, and a global @ControllerAdvice handler, most exception handling concerns become declarative, reducing boilerplate, improving readability, and providing a consistent, internationalized error response across the application.

BackendJavaException HandlingSpringenumsAssertionsControllerAdvice
Architecture Digest
Written by

Architecture Digest

Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.