Hi Jean, Interesting, I was experimenting with different ways to express what you need, but no luck so far, I will try to spend a bit more time on that this week since OAS 3.x does support multipart [1] but we may indeed hit the limitation(s) of this particular Swagger Core version. Thank you. [1] https://swagger.io/docs/specification/describing-request-body/multipart-requests/ Best Regards, Andriy Redko
> 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. >