Search code examples
javaspringspring-bootopenapi

Is there a ready-made class in spring boot that represents the OpenApi Schema when I return an exception of type ResponseStatusException?


This is a method example that returns ResponseStatusException:

@Operation(summary = "Summary example", description = "Description example.")
@ApiResponses(value = {
   @ApiResponse(responseCode = "200", description = "Item found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = Item.class))),
   @ApiResponse(responseCode = "400", description = "Item not found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ?????????)))
})
@GetMapping(value = "/{id}")
public ResponseEntity<Item> getById(@PathVariable(name = "id") Long id) {
    Item item = itemService.findById(id)
                           .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Item not found"));
    return ResponseEntity.ok().body(item);
}

When I throw a ResponseStatusException Spring Boot returns a Json like this:

{
  "timestamp": "2024-09-05T16:56:53.047+00:00",
  "status": 404,
  "error": "Item not found",
  "exception": "org.springframework.web.server.ResponseStatusException",
  "message": "Item not found",
  "path": "/my-context/api/v1/item/1"
}

So my question is: which is the better way to represent this error response in OpenApi? Which is the correct schema implementation class? Do I need to create one or does it already exist?


Solution

  • The short answer

    Unfortunately you need to do it yourself.

    The long answer

    The error you are showing is done by spring boot, this class DefaultErrorAttributes

    This class can't be used directly to represent a return type.

    What I am doing personnaly is this

    @Data
    public class ErrorResponse {
    
      @NotNull private String error;
      @NotNull private Date timestamp;
    
      @NotNull private String path;
      @NotNull private int status;
      @NotNull private String message;
    
      @Nullable private String exception;
      @Nullable private List<FieldError> errors;
    }
    
    @ApiResponse(
                responseCode = "400",
                description = "Request Error",
                content = {
                  @Content(
                      mediaType = "application/json",
                      schema = @Schema(implementation = ErrorResponse.class))
                })
    
    

    If you are using Bean Validation, the last property allows you to describe the usual response you are getting for bad requests

    {
    ...
    "message": "Validation failed for object='model'. Error count: 1",
        "errors": [
            {
                "codes": [
                    "NotNull.model.type",
                    "NotNull.type",
                    "NotNull.java.lang.String",
                    "NotNull"
                ],
                "arguments": [
                    {
                        "codes": [
                            "model.type",
                            "type"
                        ],
                        "arguments": null,
                        "defaultMessage": "type",
                        "code": "type"
                    }
                ],
                "defaultMessage": "ne doit pas être nul",
                "objectName": "model",
                "field": "type",
                "rejectedValue": null,
                "bindingFailure": false,
                "code": "NotNull"
            }
        ],
    }