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 <[email protected]>
> Sent: woensdag 3 juli 2024 5:57
> To: Jean Pierre URKENS <[email protected]>; [email protected]
> 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.
>