Swagger examples are not shown on UI - swagger-ui

Unable to get example field values in swagger UI.
#ApiOperation(value = "Sample API to test swagger doc", response = SampleResponse.class)
#ApiImplicitParams({
#ApiImplicitParam(
name = "sampleResponse",
dataType = "SampleResponse",
examples = #io.swagger.annotations.Example(
value = {
#ExampleProperty(value = "{'code': '123', 'msg':'message'}", mediaType = "application/json")
}))
})
#ApiResponses(value = {
#ApiResponse(code = 200, response = SampleResponse.class, message = "Success", examples = #io.swagger.annotations.Example(
value = {
#ExampleProperty(value = "{'code': '123', 'message':'success'}", mediaType = "*/*")
})),
#ApiResponse(code = 401, message = "UnAuthorized"),
#ApiResponse(code = 400, message = "Invalid ID supplied", response = ApiResponse.class,
examples = #Example(value =
{
#ExampleProperty(mediaType = "application/json", value = "{\"code\" : \"42\", \"message\" : \"Invalid ID supplied\"}")
}
))
})
#PosMapping(value = "/test", produces = MediaType.APPLICATION_JSON_VALUE)
public SampleResponse get(#ApiParam(required = true) #RequestBody SampleResponse sampleResponse) {
pom.xml
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
Example defined with annotation #ExampleProperty are missing in UI.
In below image swagger UI example fields are shown with value as its default data type.

I couldn't find much in swagger2, but upgraded to openapi, where this can be achieved by using #io.swagger.v3.oas.annotations.parameters.RequestBody for defining request body and its examples and #io.swagger.v3.oas.annotations.responses.ApiResponse for response.

Related

Swagger #ApiResponse should show List of ErrorObject i.e List<MyErrorObject> ? How is this possible?

The swagger version I am using is as below and My question is related to the #ApiResponse annotation.
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
<scope>compile</scope>
</dependency>
When a user accesses my api and if the user provides invalid details/input, my application is returning a list of errors in the users input.
Each error is captured in a an error object
MyErrorObject
{
Date date;
String errorCode;
String errorMessage;
//getters //setters
}
-so my application response incase of invalid user input will look something like below -
[
{
"date": "2021-09-22",
"errorCode": "6548",
"errorMessage": "there are no booking available in selected city"
},
{
"date": "2021-09-22",
"errorCode": "2649",
"errorMessage": "your age does not allow you to travel to this location"
}
]
---Now back to my question - using swagger #ApiResponse annotation, I want the api users to know the response format. So, I tried below
#ApiResponse(code = HttpURLConnection.HTTP_BAD_REQUEST,
message = ErrorConstants.NotAllowed, response=List<MyErrorObject>.class)
But above did not work, I am seeing below compile time error -
Syntax error, insert "}" to complete MemberValueArrayInitializer
I tried - other combinations too like below but no luck -
#ApiResponse(code = HttpURLConnection.HTTP_BAD_REQUEST,
message = ErrorConstants.NotAllowed, response=List<MyErrorObject.class>)
So, what is the right way to represent a list of errors using #ApiResponse annotation??
So the error response on swagger doc looks something like below -
[
{
"date": "Date",
"errorCode": "string",
"errorMessage": "string"
}
]
From the definition of the ApiResponse.class, it's evident they have a responseContianer attribute that you can set to achieve the desired result.
#ApiResponse(
code = HttpURLConnection.HTTP_BAD_REQUEST,
message = ErrorConstants.NotAllowed,
response = MyErrorObject.class,
responseContainer = "List"
)

How to use annotations to create OpenAPI (Swagger) documentation on Grails 4

We are creating API documentation for an existing Grails 4 App. We are having difficulties in understanding how to use Swagger annotations.
Let's assume the following Controller:
class IntegratorController {
def maintenanceService
def saveMaintenance() {
def message = 'success'
def status = '200'
try {
def maintenanceJson = request.JSON.maintenances
def ret=maintenanceService.processMaintenanceJSON(maintenanceJson)
} catch (Exception e) {
log.error("Error to process restricions", e)
message = 'error : ${e.getMessage()}'
status = '500'
}
def result = ['message':message]
render(status: status, contentType: "application/json", text: result as JSON)
}
}
This controller expects you to send a request JSON like this example:
{ "job":42,
"maintenances": [
{"idPort":42, "idMaintenance":42, "shipName":"myship01", "obs":"asap"},
{"idPort":43, "idMaintenance":43, "shipName":"myship02", "obs":"asap"}]}
A basic annotation will be this:
#Controller("/")
class IntegratorController {
def maintenanceService
#Post(uri="/saveMaintenance", produces = MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
#Operation(summary = "Create one or more ship maintenance")
#ApiResponse(responseCode = "500", description = "If internal service throws an Exception")
def saveMaintenance() {
def message = 'success'
def status = '200'
try {
def maintenanceJson = request.JSON.maintenances
def savedMaintenances=maintenanceService.processMaintenanceJSON(maintenanceJson)
} catch (Exception e) {
log.error("Error to process restricions", e)
message = 'error : ${e.getMessage()}'
status = '500'
}
def result = ['message':message]
render(status: status, contentType: "application/json", text: result as JSON)
}
}
Where and how to annotate the request JSON sent in the post operation?
Thank you!
The request object is "scoped" by Grails. So you need to use #RequestBody annotation to declare what it is outside the method declaration. You also need to create classes to describe what it is because the JSON deserialization is loosely typed.
This is an example:
#Post(uri="/saveMaintenance", produces = MediaType.APPLICATION_JSON)
#Operation(summary = "Summary here",
description = "Description here",
requestBody = #RequestBody(description = "Inside Operation"), tags = ["IntegratorWebController"])
#RequestBody(description = "Description here", required = true,
content = #Content(schema = #Schema(implementation = YourRequestDAO.class, anyOf = [YourRequestDAO.class, YourRequestDAODependency.class])))
#ApiResponses(value=[
#ApiResponse(responseCode="200", description = "Return status=OK in success", content = #Content(mediaType = "application/json", schema = #Schema(implementation = YourResponseDAO.class))),
#ApiResponse(responseCode="404", description = "Return status=BAD_REQUEST if you mess up", content = #Content(mediaType = "application/json", schema = #Schema(implementation = YourResponseDAO.class)))])
def saveOrUpdateActivity(){
(...)
Well Swagger and OpenAPI are 'schemas' that are preloaded at runtime to build the call structure; GraphQL also has a schema as well to load its call structure.
I did a video on it here to help you understand how this works: https://youtu.be/AJJVnwULbbc
The way Grails did this prior to 4.0 was with plugins like the 'swagger plugin' or with BeAPI plugin (which I maintain).
I don't see a supported plugin in 4.0 so I don't see how they are doing this now.

Reusability of #ApiResponse Annotation in Swagger

I am using Swagger annotations to document API in non-spring context.
I find that response documentation for 400, 401 and 404 is reusable.
Since it takes around 8 lines to document each response code as shown below.
#Operation(
summary = "getDetails",
description = "someDescription",
responses = {
#ApiResponse(
responseCode = "200",
description = "Found",
content = #Content(mediaType = "application/json",
schema = #Schema(
name = "Response for success")
)
),
#ApiResponse(
responseCode = "400",
description = "Validation failure on inputs.",
content = #Content(
mediaType = "application/json",
schema = #Schema(
name = "Response For Bad Request")
)
),
#ApiResponse(
responseCode = "404",
description = "Not found",
content = #Content(
mediaType = "application/json",
schema = #Schema(
name = "Response For Not Found Request")
)
),
#ApiResponse(
responseCode = "401",
description = "Unauthorized",
content = #Content(
mediaType = "application/json",
schema = #Schema(
name = "Response For Unauthorized")
)
)
}
)
I intend to prevent bloating the lines for each reusable API response.
I would prefer something like below
#Operation(
summary = "getDetails",
description = "someDescription",
responses = {
#ApiResponse(
responseCode = "200",
description = "Found",
content = #Content(mediaType = "application/json",
schema = #Schema(
name = "Response for success")
)
),
SomeStaticClass.getBadResponseDesc(),
SomeStaticClass.getUnauthorizedResponseDesc()
}
Is there any way to achieve this in java 8?
Yes, use globalResponseMessage on the Docket object. See point 22 on the springfox documentation for an example of their use. I used this approach to remove a lot of #ApiResponse annotations from my code.

swagger ApiResponse example

I am trying to document an api error response with a example of the json body. I couldn't find an example or a fitting annotation. Playing around with the swagger editor I could at least get something that looks like the result I want to achieve.
responses:
'200' :
description: Request completed with no errors
examples:
application/json: {"result" : { "id": "blue" }}
libraries being is swagger-core 1.6.0
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-core</artifactId>
<scope>compile</scope>
<version>1.6.0</version>
</dependency>
and the endpoints are created using jax-rs.
I did this to the endpoint
#ApiResponses(value = {
#ApiResponse(code = 200, message = "OK",
examples = #Example(value = #ExampleProperty(mediaType = "application/json", value = "{\"result\" : { \"id\": \"blue\" }}"))
)
})
public Response getResult(){}
The generated swagger.json doesn't have the desired
examples:
application/json: {"result" : { "id": "blue" }}
I tried also passing response = ApiResponse.class, Examples.class and Example.class but it doesn't change.
How can I do this with annotations?

Annotation-based Swagger documentation for Vert.x

Is there any annotation based Swagger Documentation creator available for Vert.x yet ? The rest end points are all managed using routers and as such if there is any way available to generate the Swagger documentation, that would be great.
I've gone through the Java Jersey based documentation creator using various annotations, but couldn't find anything for the Vert.x documentation. The official swagger wiki on Git Hub also doesn't house any document related to Vert.x documentations.
Since this question was asked Swagger has been named OpenAPI and Vert.x offers the Web API Contract module. Using this anupsaund created the vertx-auto-swagger repo (in turn based on vertx-openapi-spec-generator). It does:
Read Java Annotations and map them into a openAPI spec.
Serve the openAPI spec out on an end point.
Serve a distributable version of SwaggerUI which presents the swagger spec from point 2.
Which then allows annotations as follows:
#Operation(summary = "Find products by ID", method = "GET", operationId = "product/:productId",
tags = {
"Product"
},
parameters = {
#Parameter(in = ParameterIn.PATH, name = "productId",
required = true, description = "The unique ID belonging to the product", schema = #Schema(type = "string"))
},
responses = {
#ApiResponse(responseCode = "200", description = "OK",
content = #Content(
mediaType = "application/json",
encoding = #Encoding(contentType = "application/json"),
schema = #Schema(name = "product", example =
"{" +
"'_id':'abc'," +
"'title':'Red Truck'," +
"'image_url':'https://images.pexels.com/photos/1112597/pexels-photo-1112597.jpeg'," +
"'from_date':'2018-08-30'," +
"'to_date':'2019-08-30'," +
"'price':'125.00'," +
"'enabled':true" +
"}",
implementation = Product.class)
)
),
#ApiResponse(responseCode = "404", description = "Not found."),
#ApiResponse(responseCode = "500", description = "Internal Server Error.")
}
)

Resources