Home/Learn/Spring Boot/ResponseEntity

ResponseEntity

Intermediate
Web / REST

Wraps the response body, HTTP status code, and headers in a single return type, giving full control over every aspect of the HTTP response.

Overview

ResponseEntity<T> is a Spring wrapper that bundles the HTTP response body, status code, and headers into a single return type from a controller method. By default @RestController returns 200 OK with the method's return value as the body — when you need to customise the status code, add response headers (Location, ETag, Cache-Control), or return empty bodies (204 No Content), you use ResponseEntity. Common patterns: return 201 Created with a Location header after creating a resource, return 204 No Content for deletes, return 404 Not Found when a resource is absent. ResponseEntity integrates naturally with Optional and reactive types.

Common response patterns

ResponseEntity.ok(body) is shorthand for 200 OK. Use ResponseEntity.created(uri) for 201, ResponseEntity.noContent() for 204, ResponseEntity.notFound() for 404. The builder API (ResponseEntity.status(status).header(...).body(...)) gives full control for more complex responses.

Java — GET (200/404), POST (201 + Location), DELETE (204) patterns
@RestController
@RequestMapping("/orders")
public class OrderController {

    private final OrderService orderService;

    // 200 OK with body
    @GetMapping("/{id}")
    public ResponseEntity<Order> getOrder(@PathVariable Long id) {
        return orderService.findById(id)
            .map(ResponseEntity::ok)               // 200 OK
            .orElse(ResponseEntity.notFound().build()); // 404 Not Found, no body
    }

    // 201 Created with Location header
    @PostMapping
    public ResponseEntity<Order> createOrder(@RequestBody @Valid OrderRequest req) {
        Order created = orderService.create(req);
        URI location = ServletUriComponentsBuilder
            .fromCurrentRequest()
            .path("/{id}")
            .buildAndExpand(created.getId())
            .toUri();
        return ResponseEntity.created(location).body(created);
        // Response: 201 Created, Location: /orders/42, body: {"id":42,...}
    }

    // 204 No Content — update/delete returns nothing
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteOrder(@PathVariable Long id) {
        orderService.delete(id);
        return ResponseEntity.noContent().build();  // 204, no body
    }
}

Adding response headers

Use ResponseEntity.ok().header(name, value) or HttpHeaders to add custom headers. Common headers: Location (after create), ETag (for conditional requests), Cache-Control (for caching), and custom correlation headers. Return HttpHeaders via BodyBuilder for multi-header responses.

Java — ETag, Cache-Control, and custom response headers
// Custom headers on response
@GetMapping("/{id}")
public ResponseEntity<Order> getOrderWithCaching(@PathVariable Long id) {
    Order order = orderService.findById(id).orElseThrow(NotFoundException::new);
    String etag = '"' + Integer.toHexString(order.hashCode()) + '"';

    return ResponseEntity.ok()
        .header(HttpHeaders.ETAG, etag)
        .header(HttpHeaders.CACHE_CONTROL, "max-age=60, must-revalidate")
        .header("X-Request-Id", MDC.get("requestId"))
        .body(order);
}

// Using HttpHeaders object for multiple headers
@PostMapping("/orders")
public ResponseEntity<Order> createWithHeaders(@RequestBody OrderRequest req) {
    Order created = orderService.create(req);

    HttpHeaders headers = new HttpHeaders();
    headers.setLocation(URI.create("/orders/" + created.getId()));
    headers.set("X-Order-Number", created.getOrderNumber());
    headers.set("X-Rate-Limit-Remaining", "99");

    return new ResponseEntity<>(created, headers, HttpStatus.CREATED);
}

Error responses and @ExceptionHandler

Rather than returning ResponseEntity<Object> with error details from every method, use @ExceptionHandler or @ControllerAdvice to centralise error mapping. @ControllerAdvice catches exceptions thrown from any controller and maps them to structured error ResponseEntity responses. Spring Boot's ProblemDetail (RFC 7807) provides a standardised error response structure.

Java — @ControllerAdvice with ProblemDetail (RFC 7807) error responses
// Centralised error handling — cleaner than try/catch in every controller
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(OrderNotFoundException.class)
    public ResponseEntity<ProblemDetail> handleNotFound(OrderNotFoundException ex,
                                                         HttpServletRequest req) {
        ProblemDetail problem = ProblemDetail.forStatusAndDetail(
            HttpStatus.NOT_FOUND, ex.getMessage());
        problem.setTitle("Order Not Found");
        problem.setInstance(URI.create(req.getRequestURI()));
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(problem);
        // {"type":"about:blank","title":"Order Not Found","status":404,
        //  "detail":"Order 42 not found","instance":"/orders/42"}
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ProblemDetail> handleValidation(
            MethodArgumentNotValidException ex) {
        ProblemDetail problem = ProblemDetail.forStatus(HttpStatus.BAD_REQUEST);
        problem.setTitle("Validation Failed");
        Map<String, String> errors = ex.getBindingResult()
            .getFieldErrors().stream()
            .collect(toMap(FieldError::getField, FieldError::getDefaultMessage));
        problem.setProperty("errors", errors);
        return ResponseEntity.badRequest().body(problem);
    }
}

Key Points to Remember

  • 1ResponseEntity.ok(body) = 200, .created(uri) = 201 + Location, .noContent() = 204, .notFound() = 404
  • 2Always return 201 Created with a Location header pointing to the new resource URI after POST
  • 3ResponseEntity.status(code).header(name, value).body(obj) provides full control over every response aspect
  • 4@ControllerAdvice + @ExceptionHandler centralises error-to-ResponseEntity mapping across all controllers
  • 5ProblemDetail (Spring Boot 3 / RFC 7807) provides a standardised JSON error structure with type, title, status, detail
  • 6Return ResponseEntity<Void> for 204 No Content — avoids Jackson trying to serialise a null body

Interview Questions

Sign in to ask Aria
1

Why would you use ResponseEntity<Order> instead of just returning Order from a @RestController method?

EasyInfosys
2

How do you return a 201 Created response with a Location header in Spring Boot?

EasyWipro
3

What is ProblemDetail and how does it standardise error responses?

MediumThoughtworks
4

How does @ControllerAdvice improve error handling compared to try-catch in every controller?

MediumAmazon
5

How would you implement ETag-based conditional GET responses with ResponseEntity?

HardGoogle

Ask Aria about ResponseEntity

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…