Swagger and Springfox Changing the example response for different status codes - java

I have a specific DTO I'm using to return as an example for Swagger documentation. How can I change the example in case I have a success 201 code?
Example responses in swagger:
I use the annotations "#ApiModelProperty" to describe my objects, but finding no way on how to change the example for different response codes. In my code, I don't want to show the Errors list, as it's an optional property and it will just be available when non 201 codes are going to be produced.
Ideas?

You can do this with a couple of annotations as follows:
import io.swagger.v3.oas.annotations.media.ExampleObject;
#Operation(summary = "Your summary")
#ApiResponses(value = {
#ApiResponse(responseCode = "200", description = "Your description",
content = { #Content(mediaType = "application/json",
schema = #Schema(implementation = YourModel.class),
examples = [#ExampleObject(value = "{\"timestamp\": 1581552186590, \"status\": 404, \"error\": \"Not Found\", \"message\": \"Error message\", \"requestId\": \"62bcf95d\"}")]) })})

Related

How can I control tag name on API in OpenAPI Spring generator?

I have an openapi spec with multiple endpoints. I have included two in this example:
openapi: 3.0.1
info:
...
servers:
...
tags:
- name: academic degrees
description: academic degrees description here
paths:
/education/academicdegrees:
get:
tags:
- academic degrees
summary: Returns all the academic degrees
operationId: getAcademicDegrees
responses:
...
/education/academicdegrees/{id}:
get:
tags:
- academic degrees
summary: Returns the academic degree with the requested id
operationId: getAcademicDegree
parameters:
...
responses:
200:
...
I use the Openapi generator maven plugin to generate api classes. The generator is "spring" with these config options:
<configOptions>
<verbose>true</verbose>
<templateDirectory>templates</templateDirectory>
<delegatePattern>true</delegatePattern>
<documentationProvider>springdoc</documentationProvider>
<useSpringBoot3>true</useSpringBoot3>
<useTags>true</useTags>
</configOptions>
This results in this Api file called AcademicDegreesApi. I have omitted the second endpoint.
Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2023-02-02T11:47:50.034894501+01:00[Europe/Copenhagen]")
#Validated
#Tag(name = "AcademicDegrees", description = "academic degrees description here")
public interface AcademicDegreesApi {
...
#Operation(
operationId = "getAcademicDegree",
summary = "Returns the academic degree with the requested id",
tags = { "academic degrees" },
responses = {
#ApiResponse(responseCode = "200", description = "successful operation", content = {
#Content(mediaType = "application/json", schema = #Schema(implementation = AcademicDegreeDTO.class))
})
},
security = {
#SecurityRequirement(name = "ApiKeyAuth")
}
)
#RequestMapping(
method = RequestMethod.GET,
value = "/uddbase/academicdegrees/{id}",
produces = { "application/json" }
)
default ResponseEntity<AcademicDegreeDTO> getAcademicDegree(
#Parameter(name = "id", description = "UUID of an academic degree", required = true) #PathVariable("id") UUID id
) {
return getDelegate().getAcademicDegree(id);
}
...
}
The class has the decorator Tag with name = "AcademicDegrees" while the individual endpoints are tagged with "academic degrees" as in the spec file. This causes the swagger UI to display duplicate endpoints:
I would like to have both the api tag name and the controller tag name to be "academic degrees"
How can I avoid these duplicates and how can I control the tag name defined in the api decorator?
I have tried to remove the tags from the spec and this causes no tags on the individual endpoints but only on the api. The api class then takes the name "EducationApi" from the paths defined.
I want to avoid this because I have many endpoints in this spec and want to group them with tags in order to have the swagger-ui nice and neat.
Rather than using the multi-word tag "academic degrees" use a single word everywhere, eg "AcademicDegrees" or "academic_decrees".

How to add parameter example from Java class in Swagger

I have the following Swagger configuration
#Bean
#RouterOperation(path = PEOPLE_SEARCH_URL, produces = {MediaType.APPLICATION_JSON_VALUE},
beanClass = PersonSearchHandler.class, method = RequestMethod.GET, beanMethod = "getSearchResponse",
operation = #Operation(operationId = "getSearchResponse", security = {#SecurityRequirement(name = "Bearer Authentication")},
responses = {
#ApiResponse(responseCode = "200", description = "Successful operation",
content = #Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = #Schema(implementation = SearchResponse.class))
)},
parameters = {#Parameter(in = ParameterIn.QUERY, name = "request",
description = "SearchRequest object in JSON format converted to base64",
schema = #Schema(implementation = SearchRequest.class))}
))
My endpoint receives serialised SearchRequest object, which is encoded with Base64.
On swagger-ui I put encoded string , not Json object
The problem is - when I try to pass request param encoded with Base64 from Swagger UI, it validates this string against schema implementation = SearchRequest.class. But just remove #Schema is not an option, since I need to have request example and possibility to pass base64 encoded string.
So , I looking for work around and find some options:
Remove #Schema and just add 'example' to #Parameter. But SearchRequest consists a lot fields, so it is expanded to a lot of lines and look very bad.
In some way, if it possible, disable validation against schema , so I can just put encoded string in request param.
I will be very grateful for any workarounds and advices.

Swagger annotations for fixed set of Strings for input

Currently I have API which have something like below
#GetMapping("/list/{type}")
#ApiOperation(nickname = "reportUnits", httpMethod = "GET", produces = "application/json", responseContainer = "List", response = ReportFormatDTO.class, value = "Returns all available report Units", notes = "Returns all available report Units", consumes = "text")
#ApiResponses({ #ApiResponse(code = 404, message = "No data found"),
#ApiResponse(code = 500, message = "Error getting Report Units"), })
Flux<ReportFormatDTO> getList(#PathVariable("type") String type);
I need to tell swagger about fixed set of String to be passed in the Path variable.

What is the correct swagger-annotation for this requestBody?

We try using swagger 2.0 (OAS3) for the documentation of a Restful API, implemented in Java and based on Apache CXF (jaxrs).
For a handful API-Calls yet implemented, the documentation with swagger works fine, but the following Post-Request makes me struggling:
#POST
#Path("/documents")
#Consumes("multipart/mixed")
Response createDocument(
#RequestBody(description = "RestDocumentParams (required), InputStream and RelationshipParams",
content = { #Content(mediaType = "multipart/mixed", schema = #Schema(implementation = RestDocumentParams.class)),
#Content(mediaType = "application/octet-stream", schema = #Schema(type = "string", format = "binary")),
#Content(mediaType = "application/json", schema = #Schema(implementation = RelationshipParams.class)) })
#Multipart(value = "doc", type = MediaType.APPLICATION_JSON)
RestDocumentParams documentParams,
#Multipart(value = "file", type = MediaType.APPLICATION_OCTET_STREAM, required = false)
InputStream inputStream,
#Multipart(value = "rela", type = MediaType.APPLICATION_JSON, required = false)
RelationshipParams relationshipParams)
This method should create a new Document using at least the data given in RestDocumentParams. Optionaly a file object (InputStream) and additional
MetaData (RelationshipParams) can be provided. All this payload has to be provided in the RequestBody.
Using this method in a testframework (e.g. restassured) works fine.
My problem is, how I have to annotate this method correct with swagger-annotation, to use it in Swagger-UI.
Using the RequestBody-Annotation like above, seems not being the right way!
In Swagger-UI appears a combo-box within the description of the RequestBody and let me choose the three different media types.
But if I want to try out this method and edited one of the input parameters (e.g. entering a file name) and choose the next media type, the last editing is lost.
Comparing the json-Strukture of the requestBody for this method with the OAS3 definition for "multipart content" differ.
Regarding to the OAS3 definition, the requestBody should have look like this:
requestBody:
description: 'RestDocumentParams (required), InputStream and RelationshipParams'
content:
multipart/form-data:
schema:
properties:
docParams:
$ref: '#/components/schemas/RestDocumentParams'
relaParams:
$ref: '#/components/schemas/RelationshipParams'
fileName:
type: string
format: binary
But I don't know how I have to specify the requestBody (using swagger annotoations) to achive a structure which looks like this.

Python requests POST to java REST interface MultipartFile parameter is not present

I've searched around here as well as elsewhere online and can't seem to find the answer for what I think is a simple error on my part. Basically I want to transfer a file from one machine to another by issuing a Python requests.POST request to a Java REST interface on the remote machine. The Java side looks like this:
#ApiOperation(value = "Binary file transfer", nickname = "Binary file transfer")
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Success", response = HttpMessageInformationReturnDataBean.class),
#ApiResponse(code = 404, message = "Not Found")})
#RequestMapping(value = "/vm/{version}/uploadbinfile", method = RequestMethod.POST)
public String handleFileUpload(#RequestParam("binaryFile") MultipartFile file) {
if (!file.isEmpty())
{
try
{ ... the code that handles the transfer
On the Python side, the method looks like this:
def xfer_trm_binaries(self):
params = {"file": ('binaryFile',os.path.basename('TRMServer.jar')),
"folder": os.path.dirname(self.dest_temp_path),
"submit": "Submit"}
url = self.form_url("/vm/v1/uploadbinfile", self.trm_server_ip_address, self.vrm_server_port)
header=self.form_header(self.vrm_key)
header['Content-Type'] = 'multipart/file-data; boundary=randomboundarysequence'
header['enctype'] = "multipart/file-data"
print 'Send :' + url
binfile = self.local_jar_path+'TRMServer.jar'
with open(binfile, 'rb') as mfile:
try:
result = requests.post(url, headers=header,
data=params, files={'file': mfile}, verify=False)
except Exception:
The header that gets assembled there looks like this:
{'Content-Type': 'multipart/file-data; boundary=randomboundarysequence', 'Accept': 'application/json', 'Authorization': u'Bearer 8b2b6e53-9008-44b7-9d34-b5ecb9659250', 'enctype': 'multipart/file-data'}
The request is sent, however the response is always a 400 error, because it complains the MultipartFile parameter 'binaryFile' is missing:
'{"timestamp":1488597880207,"status":400,"error":"Bad Request","exception":"org.springframework.web.bind.MissingServletRequestParameterException","message":"Required MultipartFile parameter \\'binaryFile\\' is not present","path":"/vm/v1/uploadbinfile"}'
I've tried adding a 'name' value to both the params and headers of the request but it always comes back with the 400 code. Does anyone out there know what I might be doing wrong?
Actually I eventually figured this out - basically I had a method that formed the header to include the oauth bearer token, along with the ContentType and AcceptType...I then overwrote those with the multipart file info. THAT was what the receiving REST interface didn't like. When I just eliminated those header attributes altogether, it seemed to figure it out on its own.

Categories