Using Spring ResponseEntity to Manipulate the HTTP Response

1. Introduction

Using Spring, we usually have many ways to achieve the same goal, including fine-tuning HTTP responses.

In this short tutorial, we’ll see how to set the body, status, and headers of an HTTP response using ResponseEntity.

2. ResponseEntity

ResponseEntity represents the whole HTTP response: status code, headers, and body. As a result, we can use it to fully configure the HTTP response.

If we want to use it, we have to return it from the endpoint; Spring takes care of the rest.

ResponseEntity is a generic type. Consequently, we can use any type as the response body:

@GetMapping("/hello")
ResponseEntity<String> hello() {
    return new ResponseEntity<>("Hello World!", HttpStatus.OK);
}

Since we specify the response status programmatically, we can return with different status codes for different scenarios:

@GetMapping("/age")
ResponseEntity<String> age(
  @RequestParam("yearOfBirth") int yearOfBirth) {
 
    if (isInFuture(yearOfBirth)) {
        return new ResponseEntity<>(
          "Year of birth cannot be in the future", 
          HttpStatus.BAD_REQUEST);
    }

    return new ResponseEntity<>(
      "Your age is " + calculateAge(yearOfBirth), 
      HttpStatus.OK);
}

Additionally, we can set HTTP headers:

@GetMapping("/customHeader")
ResponseEntity<String> customHeader() {
    HttpHeaders headers = new HttpHeaders();
    headers.add("Custom-Header", "foo");
        
    return new ResponseEntity<>(
      "Custom header set", headers, HttpStatus.OK);
}

Furthermore, ResponseEntity provides two nested builder interfacesHeadersBuilder and its subinterface, BodyBuilder. Therefore, we can access their capabilities through the static methods of ResponseEntity.

The simplest case is a response with a body and HTTP 200 response code:

@GetMapping("/hello")
ResponseEntity<String> hello() {
    return ResponseEntity.ok("Hello World!");
}

For the most popular HTTP status codes we get static methods:

BodyBuilder accepted();
BodyBuilder badRequest();
BodyBuilder created(java.net.URI location);
HeadersBuilder<?> noContent();
HeadersBuilder<?> notFound();
BodyBuilder ok();

In addition, we can use the BodyBuilder status(HttpStatus status) and the BodyBuilder status(int status) methods to set any HTTP status.

Finally, with ResponseEntity<T> BodyBuilder.body(T body) we can set the HTTP response body:

@GetMapping("/age")
ResponseEntity<String> age(@RequestParam("yearOfBirth") int yearOfBirth) {
    if (isInFuture(yearOfBirth)) {
        return ResponseEntity.badRequest()
            .body("Year of birth cannot be in the future");
    }

    return ResponseEntity.status(HttpStatus.OK)
        .body("Your age is " + calculateAge(yearOfBirth));
}

We can also set custom headers:

@GetMapping("/customHeader")
ResponseEntity<String> customHeader() {
    return ResponseEntity.ok()
        .header("Custom-Header", "foo")
        .body("Custom header set");
}

Since BodyBuilder.body() returns a ResponseEntity instead of BodyBuilder, it should be the last call.

Note that with HeaderBuilder we can’t set any properties of the response body.

While returning ResponseEntity<T> object from the controller, we might get an exception or error while processing the request and would like to return error-related information to the user represented as some other type, let’s say E.

Spring 3.2 brings support for a global @ExceptionHandler with the new @ControllerAdvice annotation, which handles these kinds of scenarios. For in-depth details, refer to our existing article here.

While ResponseEntity is very powerful, we shouldn’t overuse it. In simple cases, there are other options that satisfy our needs and they result in much cleaner code.

3. Alternatives

3.1. @ResponseBody

In classic Spring MVC applications, endpoints usually return rendered HTML pages. Sometimes we only need to return the actual data; for example, when we use the endpoint with AJAX.

In such cases, we can mark the request handler method with @ResponseBody, and Spring treats the result value of the method as the HTTP response body itself.

For more information, this article is a good place to start.

3.2. @ResponseStatus

When an endpoint returns successfully, Spring provides an HTTP 200 (OK) response. If the endpoint throws an exception, Spring looks for an exception handler that tells which HTTP status to use.

We can mark these methods with @ResponseStatus, and therefore, Spring returns with a custom HTTP status.

3.3. Manipulate the Response Directly

Spring also lets us access the javax.servlet.http.HttpServletResponse object directly; we only have to declare it as a method argument:

@GetMapping("/manual")
void manual(HttpServletResponse response) throws IOException {
    response.setHeader("Custom-Header", "foo");
    response.setStatus(200);
    response.getWriter().println("Hello World!");
}

Since Spring provides abstractions and additional capabilities above the underlying implementation, we shouldn’t manipulate the response this way.

4. Conclusion

In this article, we discussed multiple ways to manipulate the HTTP response in Spring, and examined their benefits and drawbacks.

As usual, the examples are available over on GitHub.

Related posts:

Custom JUnit 4 Test Runners
Java Program to Create a Minimal Set of All Edges Whose Addition will Convert it to a Strongly Conne...
Tạo số và chuỗi ngẫu nhiên trong Java
Java 8 Streams peek() API
Hướng dẫn Java Design Pattern – Composite
Java Program to Represent Linear Equations in Matrix Form
Guide to BufferedReader
Java Program to Check whether Directed Graph is Connected using BFS
Java Program to Construct K-D Tree for 2 Dimensional Data
Java Program to Find the Vertex Connectivity of a Graph
Java Program to Implement Floyd-Warshall Algorithm
ClassNotFoundException vs NoClassDefFoundError
Simplify the DAO with Spring and Java Generics
Java TreeMap vs HashMap
Hướng dẫn Java Design Pattern – Abstract Factory
Hướng dẫn Java Design Pattern – DAO
Java Program to Find the Shortest Path Between Two Vertices Using Dijkstra’s Algorithm
Java Program to find the maximum subarray sum using Binary Search approach
Java Program to Implement Extended Euclid Algorithm
Reversing a Linked List in Java
Java Program to Use Above Below Primitive to Test Whether Two Lines Intersect
Giới thiệu thư viện Apache Commons Chain
Comparing getPath(), getAbsolutePath(), and getCanonicalPath() in Java
Guava CharMatcher
Java Program to Implement Self Balancing Binary Search Tree
Java Program to Generate All Pairs of Subsets Whose Union Make the Set
Spring Security Registration – Resend Verification Email
Hướng dẫn Java Design Pattern – Flyweight
Jackson – Decide What Fields Get Serialized/Deserialized
Introduction to PCollections
Hướng dẫn sử dụng biểu thức chính quy (Regular Expression) trong Java
HashMap trong Java hoạt động như thế nào?