Hi Jean,
JPU> When looking at the classes MultipartProvider and JAXRSUtils (cxf v3.5.9)
JPU> then it shows that only object for which a 'Content-Disposition' header
will
JPU> be written is a File Object. The problem is that my application is
JPU> generating the file content on the fly, so I have it either as a byte[] or
JPU> InputStream.
I believe the 'Content-Disposition' will be written for File and Attachment.
Respectively,
it is going to be read for these multipart content parts as well. This is why
the
@Multipart annotation has no 'Content-Disposition' or alike (I think).
> JPU> Even passing a List<Attachment> doesn't work as the MultiPartProvider
> will
JPU> loop through the list and try to create a DataHandler for an Attachment
JPU> object which is also not supported (throws an exception).
This is surprising, I will take a look shortly why it does not work. What kind
of
exception are you getting?
Thank you.
Best Regards,
Andriy Redko
JPU> Hi Andriy,
JPU> When looking at the classes MultipartProvider and JAXRSUtils (cxf v3.5.9)
JPU> then it shows that only object for which a 'Content-Disposition' header
will
JPU> be written is a File Object. The problem is that my application is
JPU> generating the file content on the fly, so I have it either as a byte[] or
JPU> InputStream.
JPU> This surprises me as according to
JPU>
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition:
JPU> "a multipart/form-data body requires a Content-Disposition header to
provide
JPU> information about each subpart of the form (e.g., for every form field and
JPU> any files that are part of field data)".
JPU> Also the Multipart annotation class only allows to specify Content-Type,
JPU> Content-ID so there is no way for me to provide 'Content-Disposition'
JPU> information on objects like byte[] or InputStream.
JPU> Even passing a List<Attachment> doesn't work as the MultiPartProvider will
JPU> loop through the list and try to create a DataHandler for an Attachment
JPU> object which is also not supported (throws an exception).
JPU> The only way I see to pass it is to construct Attachment objects for each
JPU> multipart part, with 'Content-Disposition' set, and add them all to a
JPU> MultipartBody object and pass this as input parameter to my method
JPU> signature. But then I loose all swager information for input objects that
JPU> are not byte[] or InputStream.
JPU> Am I missing something?
JPU> Regards,
JPU> J.P.
JPU> -----Oorspronkelijk bericht-----
JPU> Van: Andriy Redko <[email protected]>
JPU> Verzonden: vrijdag 4 oktober 2024 2:52
JPU> Aan: Jean Pierre URKENS <[email protected]>;
JPU> [email protected]
JPU> Onderwerp: Re: CXF JAX-RS: working with multipart form-data
JPU> Hi Jean,
JPU> Yeah, I think the @Multipart + Attachment may not work, but you could
accept
JPU> the List<Attachment> instead, right? (since you send many).
JPU> The logging configuration does not seem right: you use interceptors AND
JPU> feature (as per snippet below).
JPU> factory.getOutInterceptors().add(new
JPU> LoggingOutInterceptor());
JPU> factory.getInInterceptors().add(new
JPU> LoggingInInterceptor());
JPU> LoggingFeature feature = new LoggingFeature();
JPU> feature.setLogMultipart(true);
JPU> feature.setLogBinary(true);
JPU> ...
JPU> You only need one of those, either interceptors (please configure
JPU> setLogBinary & setLogMultipart for them):
JPU> factory.getOutInterceptors().add(new
JPU> LoggingOutInterceptor());
JPU> factory.getInInterceptors().add(new
JPU> LoggingInInterceptor());
JPU> Or feature:
JPU> LoggingFeature feature = new LoggingFeature();
JPU> feature.setLogMultipart(true);
JPU> feature.setLogBinary(true);
JPU> ...
JPU> Hope it helps, thanks!
JPU> Best Regards,
JPU> Andriy Redko
JPU>> Hi Andriy,
JPU>> Thanks for the swift response, but I could still use some
JPU> clarifications on:
JPU>> 1) You mention that passing an Attachment object as service method
JPU>> parameter should work.
JPU>> My initial test setup did pass an Attachment object as input
JPU>> parameter
as shown in ">>> 1)API interface declaration" in my mail. However when the
JPU>> client (see code below) tries to send a request with this
JPU>> signature, the
JPU>> JAXRSUtils.writeMessageBody(...) method that is called by the CXF
JPU>> stack throws an exception on the Attachment parameter saying:
JPU>> okt 03, 2024 9:46:54 AM
JPU>> org.apache.cxf.jaxrs.provider.MultipartProvider
JPU>> getHandlerForObject SEVERE: No message body writer found for class
JPU>> : class org.apache.cxf.jaxrs.ext.multipart.Attachment.
JPU>> okt 03, 2024 9:47:05 AM
JPU>> org.apache.cxf.jaxrs.utils.JAXRSUtils
JPU>> logMessageHandlerProblem SEVERE: Problem with writing the data,
JPU>> class java.util.ArrayList, ContentType: multipart/form-data
JPU>> okt 03, 2024 9:47:14 AM
JPU>> org.apache.cxf.phase.PhaseInterceptorChain
JPU>> doDefaultLogging WARNING: Interceptor for
JPU>> {http://api.documenten.magda.common.aeo.dvtm.be/}MessagesApi has
JPU>> thrown exception, unwinding now
JPU>> org.apache.cxf.interceptor.Fault: Problem with
JPU>> writing the data, class java.util.ArrayList, ContentType:
JPU> multipart/form-data
JPU>> at
JPU>>
JPU>
org.apache.cxf.jaxrs.client.ClientProxyImpl$BodyWriter.doWriteBody(ClientProxyImpl.java:1142)
JPU>> at
JPU>> org.apache.cxf.jaxrs.client.AbstractClient$AbstractBodyWriter.handl
JPU>> eMessage(AbstractClient.java:1223)
JPU>> The JAXRSUtils.writeMessageBody(...) method takes an 'entity'
JPU>> Object that is a List<Attachment>. The first Attachment in the list
JPU>> contains an object of type MessageToSend, while the second one
JPU>> contains an object of type Attachment for which 'no message body
JPU> writer' could be found.
JPU>> The stack creates itself an Attachment object for each parameter of
JPU>> the multipart body, that is why I though that I can not pass it as
JPU>> a parameter to my service method. I guess I am not allowed to annotate
JPU> an 'Attachment'
JPU>> parameter with @Multipart annotation as currently done in the
JPU>> method
JPU>> signature:
JPU>> @FormDataParam(value="upfile1") @Parameter(schema =
JPU>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>> "upfile1", type="application/pdf", required = false) Attachment
JPU>> upfile1Detail
JPU>> However leaving the @Multipart annotation for the Attachment
JPU>> parameter away leads to the error:
JPU>> javax.ws.rs.ProcessingException: Resource method
JPU>> be.dvtm.aeo.common.magda.documenten.api.MessagesApi.createMessage2
JPU>> has more than one parameter representing a request body
JPU>> I.e. now it is no longer clear that the Attachment parameter is
JPU>> part of the 'multipart'. That's why I switched to using an
JPU>> InputStream as parameter with @Multipart annotation but then I loose
JPU> the Content-Disposition information.
JPU>> The @Multipart annotation doesn't allow to specify
JPU>> Content-Disposition information. Is there an alternative here?
JPU>> 2) Logging of Binary Data. I create my client with:
JPU>> private static MessagesApi getThreadsafeProxy(String
JPU> baseAddress) {
JPU>> JacksonJsonProvider jjProvider = new
JPU>> JacksonJsonProvider(new CustomObjectMapper());
JPU>> List<Object> providers = Arrays.asList(new
JPU>> MultipartProvider(), jjProvider);
JPU>> final JAXRSClientFactoryBean factory = new
JPU> JAXRSClientFactoryBean();
JPU>> factory.setAddress(baseAddress);
JPU>> factory.setServiceClass(MessagesApi.class);
JPU>> factory.setProviders(providers);
JPU>> factory.getOutInterceptors().add(new
JPU> LoggingOutInterceptor());
JPU>> factory.getInInterceptors().add(new
JPU> LoggingInInterceptor());
JPU>> factory.setThreadSafe(true);
JPU>> LoggingFeature feature = new LoggingFeature();
JPU>> feature.setLogMultipart(true);
JPU>> feature.setLogBinary(true);
JPU>>
JPU> feature.addBinaryContentMediaTypes(MediaType.APPLICATION_OCTET_STREAM);
JPU>> feature.addBinaryContentMediaTypes("application/pdf");
JPU>> factory.setFeatures(Arrays.asList(feature));
JPU>> MessagesApi api = factory.create(MessagesApi.class);
JPU>> ClientConfiguration config = WebClient.getConfig(api);
JPU>> addTLSClientParameters(config.getHttpConduit());
JPU>> return api;
JPU>> }
JPU>> Here I do activate the logging for multipart and binary and also
JPU>> added some mediatypes (although couldn't find what it actually
JPU>> does). So I was expecting to see the whole message (attachments are
JPU>> rather small as it is a test).
JPU>> Well I used wireshark to get the full message and it doesn't show
JPU>> any Content-Disposition headers for the multipart elements.
JPU>> Regards,
JPU>> J.P. Urkens
JPU>> -----Original Message-----
JPU>> From: Andriy Redko <[email protected]>
JPU>> Sent: donderdag 3 oktober 2024 1:01
JPU>> To: Jean Pierre URKENS <[email protected]>;
JPU>> [email protected]
JPU>> Subject: Re: CXF JAX-RS: working with multipart form-data
JPU>> Hi Jean,
JPU>>> What is the correct way to annotate a file attachment as part of a
JPU>>> mutlipart/form-data content body?
JPU>> We have many examples in our test suites over here [1], it really
JPU>> depends on the problem at hand.
JPU>>> -> Question-01: Is this the appropriate way to pass files
JPU>>> (PDF documents) as attachment in a mutlipart/form-data request, or
JPU>>> are
JPU>> there better ways?
JPU>> You would probably better of with "multipart/mixed" [2] as in you
JPU>> case, you are sending different data types. But
JPU>> "multipart/form-data" should be fine as well. The right answer
JPU>> answer depends on how large the files are. In many cases you are
JPU>> better off using chunked transfer (no need to read the whole file in
JPU> memory), like you do with InputStream.
JPU>>> -> Question-02: When I activate logging, I can't see
JPU>>> anything about the file attachment, not is content, nor the
JPU>>> appropriate Content-Disposition settings? I get '--Content
JPU>> suppressed--', e.g.:
JPU>> Correct, by default the logging interceptors do not log binary
JPU>> data, you could checks the docs here [3].
JPU>>> -> Question-03: Don't I need to set anything regarding the
JPU>>> Content-Disposition header? The example here is simplified in a
JPU>>> sense that I used a test setup with just one file attachment. In
JPU>>> the real interface up to
JPU>>> 20 attachments can be passed. Somehow I need to know which part
JPU>>> relates
JPU>> to
JPU>>> which attachment or not?
JPU>> This is probably caused by the fact you are sending the InputStream
JPU>> and not an Attachment, if my understanding is correct. I am pretty
JPU>> sure passing the Attachment (as you did initially) should work.
JPU>>> -> Question-04: At the server implemtation side, since
JPU>>> upfile1Detail is passed as a method parameter, who is going to
JPU>>> close this InputStream at the server side?
JPU>> The stream should be closed by the service implementation (since
JPU>> the stream is expected to be consumed). The Apache CXF runtime will
JPU>> try to close the stream in most cases as well but sometimes it may not
JPU> be able to.
JPU>> Hope it answers your questions. Thanks!
JPU>> [1]
JPU>> https://github.com/apache/cxf/blob/main/systests/jaxrs/src/test/jav
JPU>> a/org/apache/cxf/systest/jaxrs/MultipartStore.java
JPU>> [2]
JPU>> https://learn.microsoft.com/en-us/exchange/troubleshoot/administrat
JPU>> ion/multipart-mixed-mime-message-format
JPU>> [3] https://cxf.apache.org/docs/message-logging.html
JPU>> Best Regards,
JPU>> Andriy Redko
JPU>>> Hi Andriy,
JPU>>> What is the correct way to annotate a file attachment as part of a
JPU>>> mutlipart/form-data content body?
JPU>>> I currently have the following (only the relevant parts):
JPU>>> 1)API interface declaration
JPU>>> ======================
JPU>>> @POST
JPU>>> @Path("/messages1")
JPU>>> @Consumes("multipart/form-data")
JPU>>> @Produces({ "application/json" })
JPU>>> @Operation(...)
JPU>>> @ApiResponses(...)
JPU>>> Response createMessage1(
JPU>>> @HeaderParam("x-correlation-id") @NotNull
JPU>>> @Size(min = 10, max = 36) @Parameter(description="ID of the
JPU>>> transaction. Use this ID for log tracing and incident handling.")
JPU>> String xCorrelationId,
JPU>>> @HeaderParam("Idempotency-Key") @NotNull
JPU>>> @Size(min = 10, max = 36) @Parameter(description="When retrying a
JPU>>> failed call, the retry call should have the same Idempotency
JPU>>> Key.")
JPU>> String idempotencyKey,
JPU>>> @FormDataParam(value="messageToSend")
JPU>>> @Parameter(required=true,schema =
JPU>>> @Schema(implementation=MessageToSend.class)) @Multipart(value =
JPU>>> "messageToSend", type="application/json", required= true)
JPU>>> MessageToSend messageToSend,
JPU>>> @FormDataParam(value="upfile1")
JPU>>> @Parameter(schema = @Schema(type = "string", format = "binary"))
JPU>>> @Multipart(value = "upfile1", type="application/octet-stream",
JPU>>> required = false) Attachment upfile1Detail);
JPU>>> So I pass the file to upload as an Attachment object.
JPU>>> 2)API client test code
JPU>>> =================
JPU>>> String xCorrelationId = UUID.randomUUID().toString();
JPU>>> String idempotencyKey =
JPU>>> UUID.randomUUID().toString();
JPU>>> //01. Get the attachment to include
JPU>>> String fileName = "test.pdf";
JPU>>> try (InputStream is =
JPU>>> this.getClass().getClassLoader().getResourceAsStream(fileName);
JPU>>> BufferedReader reader = new
JPU>>> BufferedReader(new InputStreamReader(is))) {
JPU>>> if (is == null) {
JPU>>> Assert.fail("Couldn't load
JPU>>> test.pdf
JPU>> from classpath!");
JPU>>> }
JPU>>> DataHandler dataHandler = new
JPU>>> DataHandler(is,
JPU>> "application/pdf");
JPU>>> ContentDisposition cd = new
JPU>>> ContentDisposition("attachment;name=upfile1;filename="+fileName);
JPU>>> Attachment upfile1Detail = new
JPU>> AttachmentBuilder()
JPU>>> .id("upfile1")
JPU>>> .dataHandler(dataHandler)
JPU>>> .contentDisposition(cd)
JPU>>> .mediaType("application/pdf")
JPU>>> .build();
JPU>>> //02. create the message to send
JPU>>> MessageToSend mts = new MessageToSend();
JPU>>> //03. Call the server
JPU>>> Response resp =
JPU>>> apiClient.createMessage1(xCorrelationId, idempotencyKey, mts,
JPU>>> upfile1Detail);
JPU>>> When running the API client test code and getting at '03.' The method:
JPU>>> JAXRSUtils.writeMessageBody(List<WriterInterceptor>
JPU>>> writers,Object entity,Class<?> type, Type genericType,Annotation[]
JPU>>> annotations,MediaType mediaType,MultivaluedMap<String, Object>
JPU>>> httpHeaders,Message message)
JPU>>> is called. The 'entity' object is a list of Attachment objects where:
JPU>>> - the first Attachment object contains an object of type
JPU>>> MessageToSend
JPU>>> - the second Attachment object contains an object of type
JPU>>> Attachment
JPU>>> This second object leads to a fatal error within the
JPU>>> JAXRSUtils.writeMessageBody(...) method:
JPU>>> okt 02, 2024 1:36:02 PM
JPU>>> org.apache.cxf.jaxrs.provider.MultipartProvider
JPU>>> getHandlerForObject
JPU>>> SEVERE: No message body writer found for class : class
JPU>>> org.apache.cxf.jaxrs.ext.multipart.Attachment.
JPU>>> okt 02, 2024 1:36:02 PM
JPU>>> org.apache.cxf.jaxrs.utils.JAXRSUtils
JPU>>> logMessageHandlerProblem
JPU>>> SEVERE: Problem with writing the data, class
JPU>>> java.util.ArrayList,
JPU>>> ContentType: multipart/form-data
JPU>>> I modified the interface and implementation classes to use
JPU>>> 'InputStream upfile1Detail' as type for the input parameter of the
JPU>>> service method. And in this case my 'dummy' server implementation
JPU>>> can read the file and save it to disk.
JPU>>> -> Question-01: Is this the appropriate way to pass files
JPU>>> (PDF documents) as attachment in a mutlipart/form-data request, or
JPU>>> are
JPU>> there better ways?
JPU>>> -> Question-02: When I activate logging, I can't see
JPU>>> anything about the file attachment, not is content, nor the
JPU>>> appropriate Content-Disposition settings? I get '--Content
JPU>> suppressed--', e.g.:
JPU>>> [MAGDADOC] 2024-10-02 14:29:08,911 [main] INFO
JPU>>> $--$
JPU>>> (org.apache.cxf.ext.logging.slf4j.Slf4jEventSender:84) - REQ_OUT
JPU>>> Address:
JPU>>> http://localhost:8091/services/magdadoc/api/v1/messages/messages1
JPU>>> HttpMethod: POST
JPU>>> Content-Type: multipart/form-data;
JPU>>> boundary="uuid:3c3fa9c0-8470-4655-b026-3ed09f79e862"
JPU>>> ExchangeId: a583a695-d881-4fa7-b65a-8961cdbbd412
JPU>>> Headers: {Authorization=Bearer
JPU>>> f4262ccf-3250-4bcf-a1bc-7ee1bf9a56cf,
JPU>>> Accept=application/json,
JPU>>> Idempotency-Key=bd06c05d-9fe2-4b60-b8db-5ad1121b74dc,
JPU>>> x-correlation-id=511c51ba-95fe-4f69-9443-f05c377cffab}
JPU>>> Payload:
JPU>>> --uuid:3c3fa9c0-8470-4655-b026-3ed09f79e862
JPU>>> Content-Type: application/json
JPU>>> Content-Transfer-Encoding: binary
JPU>>> Content-ID: <messageToSend>
JPU>>> {
JPU>>> "delivery" : "AUTOMATIC",
JPU>>> "eboxDeliveryData" : { /* all fine */},
JPU>>> "paperDeliveryData" : {/* all fine */},
JPU>>> "emailDeliveryData" : null,
JPU>>> "businessData" : [ ]
JPU>>> }
JPU>>> --uuid:3c3fa9c0-8470-4655-b026-3ed09f79e862
JPU>>> --- Content suppressed ---
JPU>>> -> Question-03: Don't I need to set anything regarding the
JPU>>> Content-Disposition header? The example here is simplified in a
JPU>>> sense that I used a test setup with just one file attachment. In
JPU>>> the real interface up to
JPU>>> 20 attachments can be passed. Somehow I need to know which part
JPU>>> relates
JPU>> to
JPU>>> which attachment or not?
JPU>>> -> Question-04: At the server implemtation side, since
JPU>>> upfile1Detail is passed as a method parameter, who is going to
JPU>>> close this InputStream at the server side?
JPU>>> Regards,
JPU>>> J.P. Urkens
JPU>>> P.S.: Is there a migration document describing upgrading CXF-3.5.6
JPU>>> (my current version) to CXF-3.5.8 (latest JDK8 version). I'd like
JPU>>> to know whether upgrading can happen without too much burden.
JPU>>> -----Original Message-----
JPU>>> From: Jean Pierre URKENS <[email protected]>
JPU>>> Sent: vrijdag 5 juli 2024 13:04
JPU>>> To: 'Andriy Redko' <[email protected]>; '[email protected]'
JPU>>> <[email protected]>
JPU>>> Subject: RE: CXF JAX-RS: working with multipart form-data
JPU>>> Hi Andriy,
JPU>>> When searching the net I came along this Jersey annotation but
JPU>>> since I was not depending on 'Jersey' components I skipped it. So
JPU>>> apparently swagger-core has processing for externally defined
JPU>>> annotations (like this FormDataParam in Jersey), indeed inside
JPU>> know-how.
JPU>>> I included it in my project as
JPU>>> io.swagger.v3.oas.annotations.FormDataParam,
JPU>>> since it should somehow be included in the supported swagger
JPU>>> annotations (maybe we should submit a request for it to the
JPU>>> swagger-core team) and this indeed generates an appropriate
JPU>> openapi.json spec.
JPU>>> Thanks alot,
JPU>>> J.P. Urkens
JPU>>> -----Original Message-----
JPU>>> From: Andriy Redko <[email protected]>
JPU>>> Sent: vrijdag 5 juli 2024 2:16
JPU>>> To: Jean Pierre URKENS <[email protected]>;
JPU>>> [email protected]
JPU>>> Subject: Re: CXF JAX-RS: working with multipart form-data
JPU>>> Hi Jean,
JPU>>> Here is how you could make it work (there is some magic knowledge
JPU>>> involved sadly). First of all, define such annotation anywhere in
JPU>>> your codebase (where it dims appropriate):
JPU>>> import java.lang.annotation.ElementType; import
JPU>>> java.lang.annotation.Retention; import
JPU>>> java.lang.annotation.RetentionPolicy;
JPU>>> import java.lang.annotation.Target;
JPU>>> @Target({ElementType.PARAMETER, ElementType.METHOD,
JPU>>> ElementType.FIELD})
JPU>>> @Retention(RetentionPolicy.RUNTIME)
JPU>>> public @interface FormDataParam {
JPU>>> String value();
JPU>>> }
JPU>>> Use this annotation on each Attachment parameter:
JPU>>> /* Skipping other annotations as those are not important here */
JPU>>> public Response createMessage(
JPU>>> @HeaderParam("x-correlation-id") @NotNull @Size(min = 10,
JPU>>> max = 36) @Parameter(description="ID of the transaction. Use this
JPU>>> ID for log tracing and incident handling.") String xCorrelationId,
JPU>>> @HeaderParam("Idempotency-Key") @Size(min = 10, max = 36)
JPU>>> @Parameter(description="When retrying a failed call, the retry
JPU>>> call should have the same Idempotency Key.") String idempotencyKey,
JPU>>> @FormDataParam("upfile1") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile1", type="application/octet-stream", required = false)
JPU>>> InputStream upfile1Detail,
JPU>>> @FormDataParam("upfile2") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile2", type="application/octet-stream", required = false)
JPU>>> InputStream upfile2Detail,
JPU>>> @FormDataParam("upfile3") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile3", type="application/octet-stream", required = false)
JPU>>> Attachment
JPU>> upfile3Detail,
JPU>>> @FormDataParam("upfile4") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile4", type="application/octet-stream", required = false)
JPU>>> Attachment
JPU>> upfile4Detail,
JPU>>> @FormDataParam("upfile5") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile5", type="application/octet-stream", required = false)
JPU>>> Attachment
JPU>> upfile5Detail,
JPU>>> @FormDataParam("upfile6") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile6", type="application/octet-stream", required = false)
JPU>>> Attachment
JPU>> upfile6Detail,
JPU>>> @FormDataParam("upfile7") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile7", type="application/octet-stream", required = false)
JPU>>> Attachment
JPU>> upfile7Detail,
JPU>>> @FormDataParam("upfile8") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile8", type="application/octet-stream", required = false)
JPU>>> Attachment
JPU>> upfile8Detail,
JPU>>> @FormDataParam("upfile9") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile9", type="application/octet-stream", required = false)
JPU>>> Attachment
JPU>> upfile9Detail,
JPU>>> @FormDataParam("upfile10") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile10", type="application/octet-stream", required = false)
JPU>>> Attachment upfile10Detail,
JPU>>> @FormDataParam("upfile11") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile11", type="application/octet-stream", required = false)
JPU>>> Attachment upfile11Detail,
JPU>>> @FormDataParam("upfile12") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile12", type="application/octet-stream", required = false)
JPU>>> Attachment upfile12Detail,
JPU>>> @FormDataParam("upfile13") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile13", type="application/octet-stream", required = false)
JPU>>> Attachment upfile13Detail,
JPU>>> @FormDataParam("upfile14") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile14", type="application/octet-stream", required = false)
JPU>>> Attachment upfile14Detail,
JPU>>> @FormDataParam("upfile15") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile15", type="application/octet-stream", required = false)
JPU>>> Attachment upfile15Detail,
JPU>>> @FormDataParam("upfile16") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile16", type="application/octet-stream", required = false)
JPU>>> Attachment upfile16Detail,
JPU>>> @FormDataParam("upfile17") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile17", type="application/octet-stream", required = false)
JPU>>> Attachment upfile17Detail,
JPU>>> @FormDataParam("upfile18") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile18", type="application/octet-stream", required = false)
JPU>>> Attachment upfile18Detail,
JPU>>> @FormDataParam("upfile19") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile19", type="application/octet-stream", required = false)
JPU>>> Attachment upfile19Detail,
JPU>>> @FormDataParam("upfile20") @Parameter(schema =
JPU>>> @Schema(type = "string", format = "binary")) @Multipart(value =
JPU>>> "upfile20", type="application/octet-stream", required = false)
JPU>>> Attachment upfile20Detail,
JPU>>> @FormDataParam("qrfile") @Parameter(schema = @Schema(type
JPU>>> = "string", format = "binary")) @Multipart(value = "qrfile",
JPU>>> type="application/octet-stream", required = false) Attachment
JPU>> qrfileDetail
JPU>>> ) {
JPU>>> ....
JPU>>> }
JPU>>> With that, you will get a nice request body schema (publishing a
JPU>>> bit large YAML snippet to preserve the context):
JPU>>> paths:
JPU>>> /sample/messages:
JPU>>> post:
JPU>>> tags:
JPU>>> - messages
JPU>>> summary: "Send a message, using a channel (email, paper
JPU>>> mail,
JPU>>> ebox) and delivery\
JPU>>> \ method (registered or normal) of your choice. More than
JPU>>> 6 upfiles only supported\
JPU>>> \ for PAPER delivery."
JPU>>> operationId: createMessage
JPU>>> parameters:
JPU>>> - name: x-correlation-id
JPU>>> in: header
JPU>>> description: ID of the transaction. Use this ID for log
JPU>>> tracing and incident
JPU>>> handling.
JPU>>> required: true
JPU>>> schema:
JPU>>> maxLength: 36
JPU>>> minLength: 10
JPU>>> type: string
JPU>>> - name: Idempotency-Key
JPU>>> in: header
JPU>>> description: "When retrying a failed call, the retry call
JPU>>> should have the\
JPU>>> \ same Idempotency Key."
JPU>>> schema:
JPU>>> maxLength: 36
JPU>>> minLength: 10
JPU>>> type: string
JPU>>> requestBody:
JPU>>> content:
JPU>>> multipart/form-data:
JPU>>> schema:
JPU>>> type: object
JPU>>> properties:
JPU>>> upfile1:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile2:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile3:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile4:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile5:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile6:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile7:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile8:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile9:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile10:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile11:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile12:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile13:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile14:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile15:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile16:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile17:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile18:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile19:
JPU>>> type: string
JPU>>> format: binary
JPU>>> upfile20:
JPU>>> type: string
JPU>>> format: binary
JPU>>> qrfile:
JPU>>> type: string
JPU>>> format: binary
JPU>>> The key here is @FormDataParam annotation which (originally) comes
JPU>>> from Jersey but has special treatment in Swagger Core (but,
JPU>>> likely, no attribution to Jersey).
JPU>>> Hope it helps!
JPU>>> Thank you.
JPU>>> Best Regards,
JPU>>> Andriy Redko
>>>> V2.2.22 (15/05/2024) is the latest version of io.swagger.core.v3
>>>> libraries.
>>>> I upgrade to this version to make sure I had the latest swagger
>>>> implementation.
>>>> -----Original Message-----
>>>> From: Andriy Redko <[email protected]>
>>>> Sent: donderdag 4 juli 2024 4:44
>>>> To: Jean Pierre URKENS <[email protected]>;
>>>> [email protected]
>>>> Subject: Re: CXF JAX-RS: working with multipart form-data
>>>> 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/multip
>>>> a
>>>> r
>>>> t-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(sc
>>>>> h e m a=@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(implem
>>>>> e
>>>>> n
>>>>> t
>>>>> ation=ErrorMessage.class))),
>>>>> @ApiResponse(
>>>>> responseCode = "401",
>>>>> description = "Invalid authorization", content =
>>>>> @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implem
>>>>> e
>>>>> n
>>>>> t
>>>>> ation=ErrorMessage.class))),
>>>>> @ApiResponse(
>>>>> responseCode = "500",
>>>>> description = "Unexpected Server Error", content =
>>>>> @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implem
>>>>> e
>>>>> n
>>>>> t
>>>>> ation=ErrorMessage.class))),
>>>>> @ApiResponse(
>>>>> responseCode = "502",
>>>>> description = "Bad Gateway",
>>>>> content =
>>>>> @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implem
>>>>> e
>>>>> n
>>>>> t
>>>>> ation=ErrorMessage.class))),
>>>>> @ApiResponse(
>>>>> responseCode = "503",
>>>>> description = "Service unavailable", content =
>>>>> @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implem
>>>>> e
>>>>> n
>>>>> t
>>>>> ation=ErrorMessage.class))),
>>>>> @ApiResponse(
>>>>> responseCode = "504",
>>>>> description = "Gateway Timeout",
>>>>> content =
>>>>> @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(implem
>>>>> e
>>>>> n
>>>>> t
>>>>> ation=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(s
>>>>>> c h em a=@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(imple
>>>>>> m
>>>>>> e
>>>>>> nt
>>>>>> ation=ErrorMessage.class))),
>>>>>> @ApiResponse(
>>>>>>
>>>>>> responseCode = "401",
>>>>>>
>>>>>> description = "Invalid authorization",
>>>>>> content =
>>>>>> @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(imple
>>>>>> m
>>>>>> e
>>>>>> nt
>>>>>> ation=ErrorMessage.class))),
>>>>>> @ApiResponse(
>>>>>>
>>>>>> responseCode = "500",
>>>>>>
>>>>>> description = "Unexpected Server Error",
>>>>>> content =
>>>>>> @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(imple
>>>>>> m
>>>>>> e
>>>>>> nt
>>>>>> ation=ErrorMessage.class))),
>>>>>> @ApiResponse(
>>>>>>
>>>>>> responseCode = "502",
>>>>>>
>>>>>> description = "Bad Gateway",
>>>>>> content =
>>>>>> @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(imple
>>>>>> m
>>>>>> e
>>>>>> nt
>>>>>> ation=ErrorMessage.class))),
>>>>>> @ApiResponse(
>>>>>>
>>>>>> responseCode = "503",
>>>>>>
>>>>>> description = "Service unavailable",
>>>>>> content =
>>>>>> @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(imple
>>>>>> m
>>>>>> e
>>>>>> nt
>>>>>> ation=ErrorMessage.class))),
>>>>>> @ApiResponse(
>>>>>>
>>>>>> responseCode = "504",
>>>>>>
>>>>>> description = "Gateway Timeout",
>>>>>> content =
>>>>>> @Content(mediaType=MediaType.APPLICATION_JSON,schema=@Schema(imple
>>>>>> m
>>>>>> e
>>>>>> nt
>>>>>> ation=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.