Hi Andriy,
I already tried this but it didn't work. E.g. for following API interface specification: /** * Send a message, using a channel (email, paper mail, ebox) and delivery method (registered or normal) of your choice. More than 6 upfiles only supported for PAPER delivery. * */ @POST @Path("/messages") @Consumes("multipart/form-data") @Produces({ "application/json" }) @Operation( summary = "Send a message, using a channel (email, paper mail, ebox) and delivery method (registered or normal) of your choice. More than 6 upfiles only supported for PAPER delivery.", tags = {"messages" }, operationId="createMessage", security=@SecurityRequirement(name="BearerAuthentication")) @ApiResponses({ @ApiResponse( responseCode = "201", description = "Created", content = @Content(mediaType=MediaType.APPLICATION_JSON,array=@ArraySchema( schema=@Schema(implementation=SendStatusMessage.class))), headers = {@Header( name="X-Magda-Exceptions", required=false, description="Only used in the context of EBOX delivery and if there was a problem with the consent of the receiver's ebox.", schema=@Schema(implementation=MagdaExceptionList.class)) }), @ApiResponse( responseCode = "400", description = "Invalid data supplied", content = @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implementation=ErrorMessage.class))), @ApiResponse( responseCode = "401", description = "Invalid authorization", content = @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implementation=ErrorMessage.class))), @ApiResponse( responseCode = "500", description = "Unexpected Server Error", content = @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implementation=ErrorMessage.class))), @ApiResponse( responseCode = "502", description = "Bad Gateway", content = @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implementation=ErrorMessage.class))), @ApiResponse( responseCode = "503", description = "Service unavailable", content = @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implementation=ErrorMessage.class))), @ApiResponse( responseCode = "504", description = "Gateway Timeout", content = @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implementation=ErrorMessage.class))) }) public Response createMessage( @HeaderParam("x-correlation-id") @NotNull @Size(min = 10, max = 36) @Parameter(description="ID of the transaction. Use this ID for log tracing and incident handling.") String xCorrelationId, @HeaderParam("Idempotency-Key") @Size(min = 10, max = 36) @Parameter(description="When retrying a failed call, the retry call should have the same Idempotency Key.") String idempotencyKey, @Parameter(required=true,schema = @Schema(implementation=MessageToSend.class)) @Multipart(value = "messageToSend", type="application/json", required= true) MessageToSend messageToSend, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile1", type="application/octet-stream", required = false) Attachment upfile1Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile2", type="application/octet-stream", required = false) Attachment upfile2Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile3", type="application/octet-stream", required = false) Attachment upfile3Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile4", type="application/octet-stream", required = false) Attachment upfile4Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile5", type="application/octet-stream", required = false) Attachment upfile5Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile6", type="application/octet-stream", required = false) Attachment upfile6Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile7", type="application/octet-stream", required = false) Attachment upfile7Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile8", type="application/octet-stream", required = false) Attachment upfile8Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile9", type="application/octet-stream", required = false) Attachment upfile9Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile10", type="application/octet-stream", required = false) Attachment upfile10Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile11", type="application/octet-stream", required = false) Attachment upfile11Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile12", type="application/octet-stream", required = false) Attachment upfile12Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile13", type="application/octet-stream", required = false) Attachment upfile13Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile14", type="application/octet-stream", required = false) Attachment upfile14Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile15", type="application/octet-stream", required = false) Attachment upfile15Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile16", type="application/octet-stream", required = false) Attachment upfile16Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile17", type="application/octet-stream", required = false) Attachment upfile17Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile18", type="application/octet-stream", required = false) Attachment upfile18Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile19", type="application/octet-stream", required = false) Attachment upfile19Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "upfile20", type="application/octet-stream", required = false) Attachment upfile20Detail, @Parameter(schema = @Schema(type = "string", format = "binary")) @Multipart(value = "qrfile", type="application/octet-stream", required = false) Attachment qrfileDetail); I’ve attached the generated openapi specification. It only contains the ‘messageToSend’ as part of the multipart/form-data requestBody content, all attachments are ignored. Below I’ve listed the libraries I’ve included in the project (cxf v3.5.8 and swagger v2.2.2). Which of these libraries is acutal responsible for generating the openapi.json specification from the interface description? - cxf-rt-rs-service-description-common-openapi:3.5.8 - cxf-rt-rs-service-description-openapi:3.5.8 - cxf-rt-rs-service-description-swagger-ui:3.5.8 - swagger-core:2.2.2 - swagger-annotations:2.2.2 - swagger-integration:2.2.2 - swagger-jaxrs2: 2.2.2 - swagger-model: 2.2.2 Note that I am still on JDK8, so I guess I can’t upgrade to a higher version (currently our projects use cxf-v3.5.6 and swagger 2.1.13). Regards, J.P. Urkens -----Original Message----- From: Andriy Redko <drr...@gmail.com> Sent: woensdag 3 juli 2024 5:57 To: Jean Pierre URKENS <jean-pierre.urk...@devoteam.com>; dev@cxf.apache.org Subject: Re: CXF JAX-RS: working with multipart form-data Hi Jean Pierre, I suspect the @Multipart annotation is coming from CXF (org.apache.cxf.jaxrs.ext.multipart.Multipart), right? If yes, this is not a part of JAX-RS specification but CXF specific extension. You may need to add Swagger API annotation to the parameters in question: @Parameter(schema = @Schema(type = "string", format = "binary")) Hope it helps. Thank you. Best Regards, Andriy Redko Monday, July 1, 2024, 12:09:17 PM, you wrote: > Hi all, > I am having problems to correctly annotate service methods which consumes multipart/form-data that contains attachments next to other model objects. > I’ve an openapi specification that contains following requestBody definition: > /messages: > post: > tags: > - "messages" > summary: "Send a message, using a channel (email, paper mail, ebox) and delivery method (registered or normal) of your choice. More than 6 upfiles only supported for PAPER delivery." > operationId: createMessage > parameters: > - $ref: '#/components/parameters/CorrelationId' > - $ref: '#/components/parameters/Idempotency-Key' > requestBody: > content: > multipart/form-data: > schema: > type: object > required: > - messageToSend > properties: > messageToSend: > $ref: '#/components/schemas/MessageToSend' > upfile1: > type: string > format: binary > nullable: true > upfile2: > type: string > format: binary > nullable: true > upfile3: > type: string > format: binary > nullable: true > upfile4: > type: string > format: binary > nullable: true > upfile5: > type: string > format: binary > nullable: true > upfile6: > type: string > format: binary > nullable: true > upfile7: > type: string > format: binary > nullable: true > upfile8: > type: string > format: binary > nullable: true > upfile9: > type: string > format: binary > nullable: true > upfile10: > type: string > format: binary > nullable: true > upfile11: > type: string > format: binary > nullable: true > upfile12: > type: string > format: binary > nullable: true > upfile13: > type: string > format: binary > nullable: true > upfile14: > type: string > format: binary > nullable: true > upfile15: > type: string > format: binary > nullable: true > upfile16: > type: string > format: binary > nullable: true > upfile17: > type: string > format: binary > nullable: true > upfile18: > type: string > format: binary > nullable: true > upfile19: > type: string > format: binary > nullable: true > upfile20: > type: string > format: binary > nullable: true > qrfile: > type: string > format: binary > nullable: true > required: true > When using the openapi-generator-maven-plugin v7.6.0 it generates following method signature: > @POST > @Path("/messages") > @Consumes("multipart/form-data") > @Produces({ "application/json" }) > @Operation( > summary = "Send a message, using a channel (email, paper mail, ebox) and delivery method (registered or normal) of your choice. More than 6 upfiles only supported for PAPER delivery.", > tags = {"messages" }, > operationId="createMessage", > security=@SecurityRequirement(name="BearerAuthentication"), > responses= { > @ApiResponse( > responseCode = "201", > description = "Created", > content = @Content(mediaType=MediaType.APPLICATION_JSON,array=@ArraySchema( schema=@Schema(implementation=SendStatusMessage.class))), > headers = {@Header( > name="X-Magda-Exceptions", > required=false, > description="Only used in the context of EBOX delivery and if there was a problem with the consent of the receiver's ebox.", > schema=@Schema(implementation=MagdaExceptionList.class)) > }), > @ApiResponse( > responseCode = "400", > description = "Invalid data supplied", > content = @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implementation=ErrorMessage.class))), > @ApiResponse( > responseCode = "401", > description = "Invalid authorization", > content = @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implementation=ErrorMessage.class))), > @ApiResponse( > responseCode = "500", > description = "Unexpected Server Error", > content = @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implementation=ErrorMessage.class))), > @ApiResponse( > responseCode = "502", > description = "Bad Gateway", > content = @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implementation=ErrorMessage.class))), > @ApiResponse( > responseCode = "503", > description = "Service unavailable", > content = @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implementation=ErrorMessage.class))), > @ApiResponse( > responseCode = "504", > description = "Gateway Timeout", > content = @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implementation=ErrorMessage.class))) > }) > public Response createMessage( > @HeaderParam("x-correlation-id") @NotNull @Size(min = 10, max = 36) @Parameter(description="ID of the transaction. Use this ID for log tracing and incident handling.") String xCorrelationId, > @HeaderParam("Idempotency-Key") @Size(min = 10, max = 36) @Parameter(description="When retrying a failed call, the retry call should have the same Idempotency Key.") String idempotencyKey, > @Multipart(value = "messageToSend”, required= true) MessageToSend messageToSend, > @Multipart(value = "upfile1", required = false) Attachment upfile1Detail, > @Multipart(value = "upfile2", required = false) Attachment upfile2Detail, > @Multipart(value = "upfile3", required = false) Attachment upfile3Detail, > @Multipart(value = "upfile4", required = false) Attachment upfile4Detail, > @Multipart(value = "upfile5", required = false) Attachment upfile5Detail, > @Multipart(value = "upfile6", required = false) Attachment upfile6Detail, > @Multipart(value = "upfile7", required = false) Attachment upfile7Detail, > @Multipart(value = "upfile8", required = false) Attachment upfile8Detail, > @Multipart(value = "upfile9", required = false) Attachment upfile9Detail, > @Multipart(value = "upfile10", required = false) Attachment upfile10Detail, > @Multipart(value = "upfile11", required = false) Attachment upfile11Detail, > @Multipart(value = "upfile12", required = false) Attachment upfile12Detail, > @Multipart(value = "upfile13", required = false) Attachment upfile13Detail, > @Multipart(value = "upfile14", required = false) Attachment upfile14Detail, > @Multipart(value = "upfile15", required = false) Attachment upfile15Detail, > @Multipart(value = "upfile16", required = false) Attachment upfile16Detail, > @Multipart(value = "upfile17", required = false) Attachment upfile17Detail, > @Multipart(value = "upfile18", required = false) Attachment upfile18Detail, > @Multipart(value = "upfile19", required = false) Attachment upfile19Detail, > @Multipart(value = "upfile20", required = false) Attachment upfile20Detail, > @Multipart(value = "qrfile", required = false) > Attachment qrfileDetail); If I now generate the swagger from this code (I modified the annotations in the generated code for using OAS v3 annotations through swagger-jaxrs2 v2.1.13 and I am using cxf-v3.5.6 having swagger-ui v4.18.2 generate the user interface) none of the upload files appears as request parameter, only the messageToSend is shown. > Is the above signature for the method createMessage(...) incorrect? > If I look at the generated openapi.json all the Attachment upFiles are missing from the specification? So is it a problem/short-coming(?) of the used software libraries, which then: > · cxf-rt-rs-service-description-common-openapi v3.5.6 -> this library references swagger-jaxrs2 v2.1.13 > · swagger-jaxrs2 v2.1.13 -> can I upgradethis to e.g. swagger-jaxrs2 v2.2.22 (latest) while retaining cxf v3.5.6? > · ...another? > Regards, > J.P.