Boost Spring Boot APIs with Graceful Response: Unified Error Handling & Response Wrapping

This article introduces Graceful Response, a Spring Boot component that provides one‑stop unified response wrapping, global exception handling, and custom error codes, showing how to integrate it via Maven, enable it with annotations, and simplify controller and service code while improving readability and reducing boilerplate.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Boost Spring Boot APIs with Graceful Response: Unified Error Handling & Response Wrapping

1 Introduction

Graceful Response is a component built on the Spring Boot stack that offers one‑stop unified response wrapping, global exception handling, and custom error‑code support. Using Graceful Response in web API development can save a lot of time, improve code quality, and make controller logic clearer.

Project source code: https://github.com/feiniaojin/graceful-response-example.git (choose the latest branch).

For Spring Boot 2.x use version 3.2.1-boot2; for Spring Boot 3.x use version 3.2.1-boot3. The Boot‑2 source is maintained in a separate repository https://github.com/feiniaojin/graceful-response-boot2. The Maven coordinates are the same for both versions.

2 Quick Start

2.1 Current Spring Boot Controller Issues

Typical controller code repeats response wrapping and error handling, leading to low efficiency, duplicated work, and poor readability.

@Controller
public class Controller {
    @GetMapping("/query")
    @ResponseBody
    public Response query(Map<String, Object> paramMap) {
        Response res = new Response();
        try {
            // 1. validate params
            if (illegal(paramMap)) {
                res.setCode(1);
                res.setMsg("error");
                return res;
            }
            // 2. call service
            Object data = service.query(params);
            // 3. set result
            res.setData(data);
            res.setCode(0);
            res.setMsg("ok");
            return res;
        } catch (Exception e) {
            // 4. handle exception
            res.setCode(1);
            res.setMsg("error");
            return res;
        }
    }
}

The problems are:

Efficiency : Most of the code only wraps the result.

Duplicated work : Every endpoint repeats the same boiler‑plate.

Readability : Core logic is hidden among repetitive code.

Graceful Response solves these issues.

2.2 Quick Integration

2.2.1 Add Maven Dependency

<dependency>
    <groupId>com.feiniaojin</groupId>
    <artifactId>graceful-response</artifactId>
    <version>{latest.version}</version>
</dependency>

Choose the version that matches your Spring Boot version (2.x → 3.2.1‑boot2, 3.x → 3.2.1‑boot3).

2.2.2 Enable Graceful Response

Add the annotation to the main class:

@EnableGracefulResponse
@SpringBootApplication
public class ExampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(ExampleApplication.class, args);
    }
}

2.2.3 Controller Layer

After enabling the component, controller methods can return the actual result directly; Graceful Response will wrap it automatically.

@Controller
@RequestMapping("/get")
@ResponseBody
public UserInfoView get(Long id) {
    log.info("id={}", id);
    return UserInfoView.builder().id(id).name("name" + id).build();
}

The response will be:

{
  "status": {"code": "0", "msg": "ok"},
  "payload": {"id": 1, "name": "name1"}
}

For command‑type endpoints that return void, the component also wraps a success response.

@RequestMapping("/command")
@ResponseBody
public void command() {
    // business logic
}
{
  "status": {"code": "200", "msg": "success"},
  "payload": {}
}

2.2.4 Service Layer

Instead of returning a custom Response object, service methods can return domain objects directly. Exceptions are mapped to error codes using @ExceptionMapper.

@ExceptionMapper(code = "1404", msg = "Object not found")
public class NotFoundException extends RuntimeException {}

Service interface:

public interface QueryService {
    UserInfoView queryOne(Query query);
}

Implementation example:

public class QueryServiceImpl implements QueryService {
    @Resource
    private UserInfoMapper mapper;

    public UserInfoView queryOne(Query query) {
        UserInfo userInfo = mapper.findOne(query.getId());
        if (Objects.isNull(userInfo)) {
            throw new NotFoundException();
        }
        // further business logic
    }
}

If NotFoundException is thrown, the response becomes:

{
  "status": {"code": "1404", "msg": "Object not found"},
  "payload": {}
}

2.2.5 Parameter Validation

Graceful Response enhances JSR‑303 validation. By annotating a parameter class with @ValidationStatusCode, validation failures return a unified error code.

public class UserInfoQuery {
    @NotNull(message = "userName is null !")
    @Length(min = 6, max = 12)
    @ValidationStatusCode(code = "520")
    private String userName;
}

If validation fails, the response is:

{
  "status": {"code": "520", "msg": "userName is null !"},
  "payload": {}
}

Method‑parameter validation can also use @ValidationStatusCode to set a custom error code.

@ValidationStatusCode(code = "1314")
public void validateMethodParam(@NotNull(message = "userId cannot be null") Long userId,
                               @NotNull(message = "userName cannot be null") Long userName) {
    // business logic
}
{
  "status": {"code": "1314", "msg": "userId cannot be null"},
  "payload": {}
}

2.2.6 Custom Response Formats

The component provides two built‑in response styles, configurable via graceful-response.response-style:

Style 0 (default): {"status": {"code": 1007, "msg": "..."}, "payload": {}} Style 1: {"code": "1404", "msg": "not found", "data": {}} If neither fits, developers can define their own response structure.

Advanced Features

Third‑party integrations (Swagger, executors, etc.)

Custom response bodies

Exception pass‑through

Exception aliasing

Common configuration items

The component has gained over 200 stars on GitHub; the repository is https://github.com/feiniaojin/graceful-response.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaException HandlingSpring BootAPIResponse wrapperGraceful Response
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

0 followers
Reader feedback

How this landed with the community

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.