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.
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.
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.
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
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.
