Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring ResponseStatusException does not return reason

I have a very simple @RestController, and I'm trying to set a custom error message. But for some reason, the message for the error is not showing up.

This is my controller:

@RestController @RequestMapping("openPharmacy") public class OpenPharmacyController {       @PostMapping     public String findNumberOfSurgeries(@RequestBody String skuLockRequest) {         throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "This postcode is not valid");     }  } 

This is the response that I get:

{     "timestamp": "2020-06-24T17:44:20.194+00:00",     "status": 400,     "error": "Bad Request",     "message": "",     "path": "/openPharmacy/" } 

I'm passing a JSON, but I'm not validating anything, I'm just trying to set the custom message. If I change the status code, I see that on the response, but the message is always empty.

Why is this not working like expected? This is such a simple example that I can't see what may be missing. When I debug the code I can see that the error message has all the fields set. But for some reason, the message is never set on the response.

like image 698
cunhaf Avatar asked Jun 24 '20 17:06

cunhaf


People also ask

What is response status exception?

ResponseStatusException is a programmatic alternative to @ResponseStatus and is the base class for exceptions used for applying a status code to an HTTP response. It's a RuntimeException and hence not required to be explicitly added in a method signature.

How do you handle a spring boot exception?

Exception HandlerThe @ExceptionHandler is an annotation used to handle the specific exceptions and sending the custom responses to the client. Define a class that extends the RuntimeException class. You can define the @ExceptionHandler method to handle the exceptions as shown.

How do I return a spring boot error?

Return a Generic Error Message using @ResponseStatus The most basic way of returning an error message from a REST API is to use the @ResponseStatus annotation. We can add the error message in the annotation's reason field.

What is the use of ResponseEntityExceptionHandler?

Class ResponseEntityExceptionHandler. A convenient base class for @ControllerAdvice classes that wish to provide centralized exception handling across all @RequestMapping methods through @ExceptionHandler methods.


2 Answers

This answer was provided by user Hassan in the comments on the original question. I'm only posting it as an answer to give it better visibility.

Basically, all you need to do is add server.error.include-message=always to your application.properties file, and now your message field should be populated.

This behavior was changed in Spring Boot 2.3 which you can read about here: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes#changes-to-the-default-error-pages-content

like image 152
np_ Avatar answered Oct 01 '22 11:10

np_


I have the very same issue. If I use this construct

throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Error in update"); 

My message is not passed to client via JSON. For me, the only way to go around it was to create GlobalExceptionHandler class

package mypackage;  import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import java.util.Date;  @ControllerAdvice public class GlobalExceptionHandler {   @ExceptionHandler(NotFoundException.class)   public ResponseEntity<ErrorDTO> generateNotFoundException(NotFoundException ex) {     ErrorDTO errorDTO = new ErrorDTO();     errorDTO.setMessage(ex.getMessage());     errorDTO.setStatus(String.valueOf(ex.getStatus().value()));     errorDTO.setTime(new Date().toString());      return new ResponseEntity<ErrorDTO>(errorDTO, ex.getStatus());   } } 

I have also created my own Exception type

package mypackage;  import org.springframework.http.HttpStatus;  public class NotFoundException extends RuntimeException {    public NotFoundException(String message) {     super(message);   }    public HttpStatus getStatus() {     return HttpStatus.NOT_FOUND;   } } 

With this, I am able to throw exception from the controller and I am getting proper result in JSON - the message I want to see.

@PutMapping("/data/{id}") public DataEntity updateData(@RequestBody DataEntity data, @PathVariable int id) {   throw new NotFoundException("Element not found"); } 

I had to introduce ErrorDTO as well

package mypackage;  public class ErrorDTO {   public String status;   public String message;   public String time;    ...   ...   // getters and setters are here    ...   ... } 

Update

As mentioned by @Hassan and @cunhaf (in comments under original question), the solution with

server.error.include-message=always 

works perfectly fine with ResponseStatusException. Still, solution with GlobalExceptionHandler might be better in case someone wants to pass more info via Exception.

Source code

Samples can be found here: Global Exception Handler

like image 43
Oo.oO Avatar answered Oct 01 '22 12:10

Oo.oO