Search code examples
spring-bootgradleopenapiopenapi-generator

How to get the message of the Bad request in API response with openAPI generated controllers in gradle spring


I have a Spring boot application (2.6.9) with gradle 7.6.

I'm using the open api generator gradle plugin to generate request controllers in my application, with the delegate pattern.

    id 'org.openapi.generator' version '6.3.0'

Here are my open api generate config options,

        "dateLibrary": "java8",
        "hideGenerationTimestamp": "true",
        "delegatePattern": "true",
        "library": "spring-boot",
        "serializableModel": "true",
        "useBeanValidation": "true",
        "useTags": "true",
        "implicitHeaders": "true",
        "openApiNullable": "false"

In the open API specification, I have an endpoint with a required parameter.

/resource/getByDate:
  get:
    tags:
      - resource
    summary: summary
    description: desc
    operationId: operation
    parameters:
      - name: fromDate
        in: query
        description: date
        required: true
        schema:
          type: string

Module compiles successfully and initializes as expected. Once a request is sent without the required 'fromDate' parameter the response is,

"timestamp": "2023-03-02T13:59:52.112+00:00",
"status": 400,
"error": "Bad Request",
"path": "/resource/getByDate"

In the application logs the following message is logged,

 Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter 'fromDate' for method parameter type String is not present

How to include this message in the response body with the code generator support?


Solution

  • As part of your responses, include a response for a 400 status. Something like this:

      /resource/getByDate:
        get:
          tags:
            - resource
          summary: summary
          description: desc
          operationId: operation
          parameters:
            - name: fromDate
              in: query
              description: date
              required: true
              schema:
                type: string
          responses:
            '400':
              description: Invalid Request
              headers:
                x-whatever:
                  description: If you want to include headers in your response
                  schema:
                    type: string
              content:
                application/json:
                  schema:
                    properties: 
                      title:
                        type: string
                      message:
                        type: string
                      statusCode:
                        type: string
                      method:
                        type: string
    

    This will generate a class that looks something similar to this:

    public class Operation400Response implements Serializable {
    
      private static final long serialVersionUID = 1L;
    
      @JsonProperty("title")
      private String title;
    
      @JsonProperty("message")
      private String message;
    
      @JsonProperty("statusCode")
      private String statusCode;
    
      @JsonProperty("method")
      private String method;
    

    Now you can create a ControllerAdvice class to handle the MissingServletRequestParameterException like this:

    @ControllerAdvice
    public class MyExceptionHandler extends ResponseEntityExceptionHandler
    {
      @Override
      public ResponseEntity<Operation400Response> handleMissingServletRequestParameter(MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatus status, WebRequest request)
      {
        var response = new Operation400Response().title("Missing required parameter").message(ex.getMessage()).statusCode(status);
        return new ResponseEntity(response, HttpStatus.BAD_REQUEST);
      }
    }