Return Specific HTTP Response Status in Spring

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

Overview

When a client sends HTTP request to a server, the server returns back a HTTP Response Status. This HTTP response status is an indication of the state of the client request. Based on the response status client knows if the request was successful, failed, rejected, or etc. by the server.

While working with a Spring REST or MVC Controllers, depending upon the request outcome Spring sends one of the standard HTTP Statuses by default. For example 200, 500, or 404. In this tutorial we will learn How to send specific or custom HTTP Response Status from Spring Controller in a Spring or Spring Boot application.

What is HTTP Response Status Code?

As status earlier HTTP Status is a status code the server issues to let the client know the status of its request. The 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 a successful completion of 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: Request is valid but the server cannot be fulfilled it because of a problem in server.

A Controller in Spring Application can return a few default status codes. For example it returns 200 when a request is complete without any exceptions. Or, Spring sends status code of 404, if a requested resource is not present. Also, it sends 500 when an exception is thrown out of controller and there is no handler associated with the exception.

These standard status codes are correct and they serve their purpose however, sometimes it is not enough for a client to just know these high level status codes. A client may expect a more specific type of status codes so that it can take appropriate action or show a detailed error or success message to the user. Thus, we may want server to send more specific HTTP status codes.

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 in other words a more specific status codes from the server.

The very basic way of sending response status is to use ResponseEntity object, which is returned by a controller. 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 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. With this response entity instance we can also send a specific HTTP Response Status Code.

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 a HTTP POST request on the above controller, that returns an instance of Student object, we get 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 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 a HTTP POST endpoint, the controller now returns a more specific response status of 201. HTTP Response Status Code 201 denotes an entity is created on 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 that is the most flexible way of returning a specific response status. Also, we can specify reason that lead to the status. The reason is useful when the server returns unsuccessful statuses.

The @ResponseStatus annotation can be used on any method that returns back a response to the client. Thus we can use it on controllers or on 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({MyCustomE.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 controller returning a specific status code as part of ResponseEntity.

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

Next is an example of a Controller with void return type 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 gets ability to treat each exception differently and set a different response status for them.

Summary

This tutorial practically explained a different ways of returning custom HTTP Response Status Codes from Spring controller. We started by sending status code by returning ResponseEntity with a custom status code. Then we used @ResponseStatus annotations on controller, @ExceptionHandler methods, and on 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.