Return a Specific HTTP Response Status in Spring

Learn How to return a Specific HTTP Response Status Code from a Controller.

Overview

When a client sends an HTTP request to a server, the server returns an HTTP Response Status. This HTTP response status indicates the client’s request status. Using the response code, the client knows if the server failed, rejected or successfully processed the request.

In Spring-based applications, the underlying framework automatically adds appropriate HTTP Response status codes to every response the server returns. In addition, Spring also provides ways of Customising Spring Controller’s HTTP Response Statuses. In the following sections, we will have a quick overview of the HTTP Status codes and their meaning and learn different ways of returning specific HTTP Response Statuses in Spring.

What is HTTP Response Status Code?

As stated earlier, an HTTP Status is a special code server issues to let its client know the status of its request. These response status codes are three-digit numbers. Next is how these response statuses are categorised.

  • 1xx: All the status codes starting from 100 to 199 are informational.
  • 2xx: These status codes represent the successful completion of the request.
  • 3xx: Represent redirection. That means further action is needed to fulfil the request.
  • 4xx: Request unsuccessful because the request is invalid or cannot be completed
  • 5xx: The request is valid, but the server cannot be fulfilled it because of a problem in the server.

As discussed earlier, Spring Controllers automatically include appropriate status codes in each response. For example, they return 200 when request processing is completed without exception, 404 when the resource in the request is not found, or 500 when the server runs into an exception.

Although these default status codes are correct, they are very high-level. Sometimes, we may want to customise this behaviour or return a more specific status code that the client expects. Thankfully, Spring offers a few ways to customise the HTTP response status codes. Let’s learn those ways with examples.

Sending Specific Response Status Codes

As stated earlier, Spring can send one of the standard Response status codes from the Controller. However, Spring also provides flexible ways to send Custom HTTP Response Status codes or more specific status codes from the server.

The basic way of sending response status is to use the ResponseEntity object, which a controller returns. The Controller can set a specific response status in the Response.

Alternatively, we can use @ResponseStatus annotation to specify the desired status code. The controllers, exception handler methods, and exception classes can use this annotation.

Also, we can throw ResponseStatusException from a Controller to send back a specific HTTP error status code. We can throw this exception with a status code when the request results in an exception.

Send Status Code using ResponseEntity

We can return an instance of ResponseEntity from a Spring Controller, where the response entity object wraps the controller response. We can send a specific HTTP Response Status Code with this response entity instance.

Spring allows a controller to return an object from a controller method. Also, Spring automatically wraps the returned instance into a response along with a default status code.

@PostMapping("/students")
public Student postStudent(@RequestBody Student student) {
  log.info("Request to create student: {}", student);
  return service.addNewStudent(student);
}Code language: Java (java)

Thus, when we execute an HTTP POST request on the above Controller that returns an instance of the Student object, we get a response status of 200.

> curl -i --location --request POST 'localhost:8080/students' \
--header 'Content-Type: application/json' \
--data-raw '{
    "firstName" : "n",
    "lastName" : "b",
    "year" : 2011
}'
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Wed, 03 Mar 2021 21:52:50 GMT

{"studentId":18,"firstName":"n","lastName":"b","year":2011}%Code language: Bash (bash)

Next is an example of a Controller using ResponseEntity to return a Custom HTTP Response Status Code. Modify the same Controller to wrap the student instance in ResponseEntity.

@PostMapping("/students")
public ResponseEntity<Student> postStudent(
    @RequestBody Student student) {
    
  log.info("Request to create student: {}", student);
  Student newStudent = service.addNewStudent(student);
  return new ResponseEntity<>(student, HttpStatus.CREATED);
}Code language: Java (java)

Note that being an HTTP POST endpoint, the Controller returns a more specific response status of 201. HTTP Response Status Code 201 denotes an entity is created on the server.

When we execute the endpoint, we get the correct response status.

> curl -i --location --request POST 'localhost:8080/students' \
--header 'Content-Type: application/json' \
--data-raw '{
    "firstName" : "n",
    "lastName" : "b",
    "year" : 2011
}'
HTTP/1.1 201
Content-Type: application/json
Transfer-Encoding: chunked
Date: Wed, 03 Mar 2021 22:00:19 GMT

{"studentId":19,"firstName":"n","lastName":"b","year":2011}%Code language: Bash (bash)

Send Status Code using @ResponseStatus

Spring provides @ResponseStatus annotation, the most flexible way of returning a specific response status. Also, we can specify the reason that leads to the status. The reason is useful when the server returns unsuccessful statuses.

The @ResponseStatus annotation can be used on any method that returns a response to the client. Thus we can use it on controllers or exception handler methods. Moreover, we can also use this annotation on an exception class, and Spring will transform the exception to the specified status code.

Using @ResponseStatus on Exception Class

When we create custom exceptions in Spring or a Spring Boot application, we can associate the exception with a specific Response Status and an optional error message.

@ResponseStatus(
    value = HttpStatus.NOT_FOUND, 
    reason = "Requested student does not exist"
)
public class StudentNotFoundException 
    extends RuntimeException {
 
  public StudentNotFoundException(Throwable t) {
    super(t);
  }
}Code language: Java (java)

When StudentNotFoundException is thrown out of a controller, Spring will automatically return the specified HTTP Response Status Code.

@GetMapping("/students/{id}")
public Student getStudent(@PathVariable Long studentId) {
  
  Student student = service.getStudent(studentId);
  if (student == null) {
    throw new StudentNotFoundException(
        "Student not found, studentId: " + studentId);
  }

  return student;
}Code language: Java (java)

Using @ResponseStatus on @ExceptionHandler

We can also use @ResponseStatus annotation on a @ExceptionHandler method.

@ExceptionHandler({MyCustomException.class})
@ResponseStatus(
    value = HttpStatus.INTERNAL_SERVER_ERROR, 
    reason = "this is the reason"
)
public void handle() {
}Code language: Java (java)

Using @ResponseStatus on Controller

Alternatively, we can add @ResponseStatus on a controller endpoint method. We have seen the Controller returning a specific status code as part of ResponseEntity.

However, the @ResponseStatus annotation controller can send a specific status code without returning any response.

Next is an example of a Controller with a void return type that returns a custom status code.

@PostMapping("/students")
@ResponseStatus(HttpStatus.CREATED)
public void postStudent(@RequestBody Student student) {
  log.info("Request to create student: {}", student);
  service.addNewStudent(student);
}Code language: Java (java)

Send Status Code using ResponseStatusException

Spring provides ResponseStatusException that a controller can throw with a specific status code and error message.

@PostMapping("/students")
public void postStudent(@RequestBody Student student) {
  
  log.info("Request to create student: {}", student);
  try {
    repository.save(student);
  } catch (InvalidStudentException e) {
    throw  new ResponseStatusException(HttpStatus.BAD_REQUEST);
  } catch (StudentServiceException e){
    throw  new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR);
  }
}Code language: Java (java)

The Controller can treat each exception differently and set a different response status for them.

Summary

This tutorial explained different ways of returning custom HTTP Response Status Codes from the Spring controller. Firstly, we sent a status code by returning ResponseEntity with a custom status code. Then we used @ResponseStatus annotations on the Controller, @ExceptionHandler methods, and custom annotations. Finally, we learnt how to throw ResponseStatusException with a specific HTTP Response Status Code from a controller.

For more on Spring and Spring Boot, please visit Spring Tutorials.