I am trying to use an OpenAPI spec from an existing Python demo to create a similar demo in Java, and have used the "spring" generator with openapi-generator-maven-plugin and the following configOptions:

                                <!-- generates single interface to implement -->
                                <useTags>true</useTags>

                                <withXml>true</withXml>
                                <title>${project.artifactId}</title>

                                <performBeanValidation>true</performBeanValidation>
                                <useBeanValidation>true</useBeanValidation>
                                <useOptional>true</useOptional>
                                <useSpringController>false</useSpringController>

                                <returnSuccessCode>false</returnSuccessCode>

                                <useAbstractionForFiles>true</useAbstractionForFiles>

                                <!-- Our own delegates can be autowired into the generated sources -->
                                <delegatePattern>true</delegatePattern>

and this YAML snippet:

post:
  description: Add products to shopping cart.
  operationId: api.cart.add_product

  requestBody:
    required: true
    content:
      'application/x-www-form-urlencoded':
        schema:
          type: object
          properties:
            quantity:
              type: integer
              example: 1
            product_code:
              type: string
              example: elephant
          required:
            - quantity
            - product_code
        examples:
          add_an_elephant:
            summary: How to add a single elephant to the shopping cart
            value:
              product_code: elephant
              quantity: 1
  
  responses:
    '204':
      description: Product added to cart.
    '400':
      description: Cannot add product to cart.
    '422':
      description: Unknown product code.

With a little extra glue to let Spring autowire the request variable this compiles and starts. Now my problem is that the swagger page generates a application/x-www-form-urlencoded request as said in the OpenAPI file, but Tomcat fails when trying to invoke:

    @RequestMapping(
        method = RequestMethod.POST,
        value = "/cart/add",
        consumes = { "application/x-www-form-urlencoded" }
    )
    default ResponseEntity<Void> apiCartAddProduct(
        @Parameter(name = "quantity", description = "", required = true, schema = @Schema(description = "")) @Valid @RequestPart(value = "quantity", required = true) Integer quantity,
        @Parameter(name = "product_code", description = "", required = true, schema = @Schema(description = "")) @Valid @RequestPart(value = "product_code", required = true) String productCode
    ) {
        return getDelegate().apiCartAddProduct(quantity, productCode);
    }

which then invokes

    @Override
    public ResponseEntity<Void> apiCartAddProduct(Integer quantity, String productCode) {
        var product = products.stream().filter(p -> p.getCode().equals(productCode)).findFirst().get();
        CartEntry price = new CartEntry().product(product).price(product.getPrice()).quantity(quantity).price(product.getPrice() * quantity);
        cart.add(price);
        return new ResponseEntity<Void>((Void) null, HttpStatus.OK);
    }

with this exception:


org.apache.tomcat.util.http.fileupload.impl.InvalidContentTypeException: the request doesn't contain a multipart/form-data or multipart/mixed stream, content type header is application/x-www-form-urlencoded
    at org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl.init(FileItemIteratorImpl.java:151) ~[tomcat-embed-core-9.0.56.jar:9.0.56]
    at org.apache.tomcat.util.http.fileupload.impl.FileItemIteratorImpl.getMultiPartStream(FileItemIteratorImpl.java:205) ~[tomcat-embed-core-9.0.56.jar:9.0.56]

My understanding is that OpenAPI generator should generate code that can accept the type stated in the YAML file, but there might be many reasons for it not to.

My problem is that I do not understand why this is a problem in the first place, and what causes it. What is wrong and how can I fix it? If it is at all possible to avoid changing the openapi yaml file I'd prefer that.


EDIT: It appears that experimentally changing @RequestPart to @RequestParam in the definition of apiCartAddProduct that Tomcat sees, makes it work. As this is changing automatically generated code I'm looking for a better solution. Suggestions?

1

There are 1 best solutions below

0
On

It appears that this was deliberately broken in https://github.com/OpenAPITools/openapi-generator/commit/a0eb149df5b722bfd43cf3587399c118850af76c (version 4.3), reported several times like in https://github.com/OpenAPITools/openapi-generator/issues/7794, and then fixed in https://github.com/OpenAPITools/openapi-generator/commit/33b89148e562fc2d5acf60a56719c46ec4f631e8 (2022-02-27)

This means that version 5.4.0 that I was using wasn't fixed, but 6.0.0-beta was.

An upgrade to the beta version fixed the problem.