Closed markusdemetz closed 4 years ago
+1 Without handling it properly, generated Open API clients are useless for complex requests including file upload.
there are 2 separated issues:
If I further annotate the file-parameter InputStream of my bean, the upload will not occur and InputStream is null.
this is unrelated to swagger-core integration but caused by any annotation alongside @FormDataParam
(defined under @FormDataParam
); see #3009 and #2567, and root cause in jersey: https://github.com/jersey/jersey/issues/3458
Workaround is switching the annotations like:
@Schema(name="picture", type="string", format="binary")
@FormDataParam("picture")
private InputStream upload;
Up to 2.1.2 the best solution for your scenario is annotating the response with:
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
@RequestBody(content = @Content(schema = @Schema(implementation = UploadRequest.class)))
public Response uploadWithBean(@BeanParam UploadRequest personData) {
and the bean with:
@Schema(name = "UploadRequest", title="Schema for Upload")
public class UploadRequest {
@FormDataParam("name")
private String name;
@Schema(name="picture", type="string", format="binary")
@FormDataParam("picture")
private InputStream upload;
@Hidden
@FormDataParam("picture")
private FormDataContentDisposition disposition;
hidden
annotations with @BeanParam
, therefore the @RequestBody
annotation on the resource method will not be needed.Please close ticket if this answers your question
That solves the issue. Thank You!!
3580 (available in next release 2.1.3) fixes the handling of
hidden
annotations with@BeanParam
, therefore the@RequestBody
annotation on the resource method will not be needed.
The @RequestBody
is still needed to work properly (using 2.1.4).
When the mapping ist annotated, it produces the following JSON:
Without annotation, I get:
The former is correct, but the "upload"-schema is useless, or am I wrong? Provided example is attached.
I also see that @RequestBody
is still needed (and I am on the current latest stable at 2.1.5)
Specifically, I've been driven crazy by this comment in DefaultParameterExtension
: // Re-process all Bean fields and let the default swagger-jaxrs/swagger-jersey-jaxrs processors do their thing
because it suggests there should be some additional parameter extension to do that processing, yet I only had the Default one installed. I went down that hole and installed swagger-jeresy-jaxrs:1.6.2 but that too didn't work. So I'm left wondering - is there some parameter extension that I am missing? And if so, where is it? I have the latest swagger core and swagger jaxrs installed. Any help/suggestions would be great!
I am not sure about the specific issue here, maybe worth fully describing along with test case in new ticket; since 2.1.3
@RequestBody
is not needed any more, and example attached to above comment seems to demonstrate that, output being:
{
"openapi":"3.0.1",
"info":{
"title":"Test",
"version":"v1"
},
"paths":{
"/api/v1/upload":{
"post":{
"operationId":"uploadWithBean",
"requestBody":{
"content":{
"multipart/form-data":{
"schema":{
"type":"object",
"properties":{
"name":{
"type":"string"
},
"upload":{
"$ref":"#/components/schemas/upload"
}
}
}
}
}
},
"responses":{
"default":{
"description":"default response",
"content":{
"application/json":{
}
}
}
}
}
},
"components":{
"schemas":{
"upload":{
"type":"object",
"format":"binary"
}
}
}
}
applying @RequestBody
still works (but is not needed), but as mentioned has a side effect of keeping around an unused component/schemas/upload
model which is not used (could be addressed in separate ticket).
about // Re-process all Bean fields and let the default swagger-jaxrs/swagger-jersey-jaxrs processors do their thing
this is indeed rather obscure, and due do historical reasons, but it doesn't imply any other processor. Again I am not sure what the current issue is, if still experiencing issues please open a new ticket with test case and reference this ticket.
Turns out that the issue was that we were using private fields with an underscore at the end, and so some part of Jackson/Swagger core wasn't able to apply the annotations (pathparam, queryparam, etc...) to the interpreted field from the public getter/setter like so:
public class MyClass {
@PathParam
private String privateField_;
private String getPrivateField() {
return privateField_;
}
}
So in this example, Swagger core didn't see that privateField was an accessible PathParam. I'm fine with this limitation, and I see there is no simple, robust way for Swagger core to correlate the field with the method, but I'm still a little confused because the beanParam resolution does happen correctly on the server - ie, Spring is able to properly inject the BeanParam, so why can't Swagger core use the logic that Spring uses?
I try to put the form parameters of a multipart request into a bean like this:
In this case, the JSON produced ist the following:
instead of (without the
@BeanParam
annotation).If I leave the
@BeanParam
annotation, i would get a 415 response code, so this seems to be the right way.If I further annotate the file-parameter
InputStream
of my bean, the upload will not occur andInputStream
is null.See the provided example to test. swagger-test-upload.zip