user13778743
user13778743

Reputation:

Customizing HTTP response message during an error spring boot rest api

I would like to have a customized message for the HTTP response i.e.

{
    "timestamp": "2020-06-30T00:40:58.558+00:00",
    "status": 417,
    "error": "Expectation Failed",
    "message": "",
    "path": "/test/v1/tests/4ae767e1-ae83-66dd-9180-81160f766d90"
}

Instead of the above message, I want a customized "message":

{
    "timestamp": "2020-06-30T00:40:58.558+00:00",
    "status": 417,
    "error": "Expectation Failed",
    "message": "#/test: 8.0 is not higher or equal to 100",
    "path": "/test/v1/tests/4ae767e1-ae83-66dd-9180-81160f766d90"
}

Here is my exception class:

@ResponseStatus(value = HttpStatus.EXPECTATION_FAILED)
public class ThrowError extends Exception {

    private static final long serialVersionUID = 1L;
    
    public ThrowErrorMessage(String message){

        super(message);
    }

Here is the catch block of a function in the controller:

catch(Exception e) 
        {   
  //basically I want e.getMessage() to be the value of the "Message" key
            throw new ThrowErrorMessage(e.getMessage()); 
            
        }
        

Upvotes: 0

Views: 2220

Answers (3)

Grigory Kislin
Grigory Kislin

Reputation: 18030

Customize error response, based on Exception can be done, using ExceptionHandler. You can also reuse DefaultErrorAttributes and ResponseEntityExceptionHandler like this: https://stackoverflow.com/a/64866190/548473

See also Using ErrorAttributes in our custom ErrorController

Upvotes: 0

jumping_monkey
jumping_monkey

Reputation: 7847

In your controller, do not do a try-catch. Instead, directly do a throws on the method, like so:

@RestController
@RequestMapping(value = "/api", 
    consumes = { MediaType.APPLICATION_JSON_VALUE }, 
    produces = { MediaType.APPLICATION_JSON_VALUE })
public class YourClassController {
    @GetMapping(value = "/{id}")
    public ResponseEntity<ResponseDto> getSomething(
            @PathVariable("id") String id
    ) throws ThrowError {
        
        //your code, for example:
        HttpStatus httpStatus = HttpStatus.OK;
        ResponseDto responseDto = new ResponseDto;
        responseDto.timestamp(LocalDateTime.now())
            .status(status);

        //maybe some more code

        return new ResponseEntity<>(responseDto, httpStatus);
    }
}

@JsonPropertyOrder({"timestamp", "status", ...})
public class ResponseDto implements Serializable {

    private static final long serialVersionUID = -7377277424125144224L;
    
    //The fields that you want to return if there is no error, example
    @JsonProperty("timestamp")
    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
    private LocalDateTime timeStamp;

    private Integer status;
    
    //more fields

    //getter, setters and so on.
}

And if there is an error, you will get what you wish, i.e

{
    "timestamp": "2020-06-30T00:40:58.558+00:00",
    "status": 417,
    "error": "Expectation Failed",
    "message": "#/test: 8.0 is not higher or equal to 100",
    "path": "/test/v1/tests/4ae767e1-ae83-66dd-9180-81160f766d90"
}

If you want to further customize the error response, you can do this:

@Component
public class CustomErrorAttributes extends DefaultErrorAttributes {

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions options) {
     
        Map<String, Object> map = super.getErrorAttributes(webRequest, options);

        //customize the values of the map here i.e timestamp, status, error, message, path

        return map;
    }
}

Upvotes: 2

Kumar V
Kumar V

Reputation: 1660

If you are using Spring boot 2.3, then setting the below property in application.properties will add your custom message in the response.

server.error.include-message=always

Upvotes: 5

Related Questions