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?
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.