openapi-generator icon indicating copy to clipboard operation
openapi-generator copied to clipboard

[BUG][SPRING] Spring generator not creating query parameter objects with @ParameterObject annotation

Open hnitzsche opened this issue 3 years ago • 1 comments

Bug Report Checklist

  • [x] Have you provided a full/minimal spec to reproduce the issue?
  • [x] Have you validated the input using an OpenAPI validator (example)?
  • [x] Have you tested with the latest master to confirm the issue still exists?
  • [x] Have you searched for related issues/PRs?
  • [x] What's the actual output vs expected output?
  • [ ] [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

If I generate spring code with springoc annotation provider from an OpenAPI spec where an operation is defined that contains an object as query parameter I expect this object being annotated with @ParameterObject or have a possibility to do so.

openapi-generator version
  • openapi-generator-maven-plugin 6.0.0
  • tried also with openapi-generator latest master and 7.0.x branch
OpenAPI declaration file content or url
openapi: 3.0.0
info:
  title: Query object as @ParameterObject
  version: '1.0'
servers:
  - url: http://localhost:8080
tags:
  - name: "Book"

paths:
  /books:
    get:
      tags:
        - "Book"
      summary: Get all Books
      operationId: getAllBooks
      x-spring-paginated: true
      parameters:
        - name: BookFilter
          in: query
          schema:
            type: object
            properties:
              name:
                type: string
              author:
                type: string
      responses:
        '200':
          description: A list of Books
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Book"
components:
  schemas:
    Book:
      type: object
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
        author:
          type: string
Generation Details

java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate \ -i above_file.yaml \ -g spring \ -o /generated-output

Steps to reproduce
  • run generation with the command stated above

Output is:


/**
     * GET /books : Get all Books
     *
     * @param bookFilter  (optional)
     * @return A list of Books (status code 200)
     */
    @Operation(
        operationId = "getAllBooks",
        summary = "Get all Books",
        tags = { "Book" },
        responses = {
            @ApiResponse(responseCode = "200", description = "A list of Books", content = {
                @Content(mediaType = "application/json", schema = @Schema(implementation = Book.class))
            })
        }
    )
    @RequestMapping(
        method = RequestMethod.GET,
        value = "/books",
        produces = { "application/json" }
    )
    default ResponseEntity<List<Book>> getAllBooks(
        @Parameter(name = "BookFilter", description = "") @Valid GetAllBooksBookFilterParameter bookFilter,
        @ParameterObject final Pageable pageable
    ) {
        getRequest().ifPresent(request -> {
            for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
                if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
                    String exampleString = "{ \"author\" : \"author\", \"name\" : \"name\", \"id\" : 0 }";
                    ApiUtil.setExampleResponse(request, "application/json", exampleString);
                    break;
                }
            }
        });
        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);

    }

Related issues/PRs
Suggest a fix

I suggest annotating the request parameter object with ParameterObject instead of Parameter like this:


/**
     * GET /books : Get all Books
     *
     * @param bookFilter  (optional)
     * @return A list of Books (status code 200)
     */
    @Operation(
        operationId = "getAllBooks",
        summary = "Get all Books",
        tags = { "Book" },
        responses = {
            @ApiResponse(responseCode = "200", description = "A list of Books", content = {
                @Content(mediaType = "application/json", schema = @Schema(implementation = Book.class))
            })
        }
    )
    @RequestMapping(
        method = RequestMethod.GET,
        value = "/books",
        produces = { "application/json" }
    )
    default ResponseEntity<List<Book>> getAllBooks(
        @ParameterObject @Valid GetAllBooksBookFilterParameter bookFilter,
        @ParameterObject final Pageable pageable
    ) {
        getRequest().ifPresent(request -> {
            for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
                if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
                    String exampleString = "{ \"author\" : \"author\", \"name\" : \"name\", \"id\" : 0 }";
                    ApiUtil.setExampleResponse(request, "application/json", exampleString);
                    break;
                }
            }
        });
        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);

    }

Would appreciate if someone could make a suggestion to make this possible or comment with any concerns about this.

hnitzsche avatar Jun 27 '22 08:06 hnitzsche

Workaround: annotate the method parameter in implementation

@Overrride
public ResponseEntity<List<Book>> getAllBooks(@ParameterObject GetAllBooksBookFilterParameter bookFilter, @ParameterObject Pageable pageable) {

drndos avatar Jun 26 '24 22:06 drndos