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.
Related
I would like to customize the swaggerUI with some custom messages. And i am able to create custom messages as below
#ApiOperation(value = "Add a new car to the inventory",
nickname = "addCar",
response = String.class,
responseContainer = "String")
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Car Added Successfully",
response = String.class, responseContainer = "String"),
#ApiResponse(code = 405, message = "Invalid input") })
But it makes my controller looks really clumsy. Is there any way to customize it without make the controller so noisy.
Thanks
What I tried was
#ApiResponse(responseCode = "200", description = "Success", content = {#Content(mediaType = "application/json", schema = #Schema(implementation = ResponseEntity.class))})
but this is what I get under the response section in my apidoc. It seems like it's not reading the ResponseEntity class and not generating any schema.
Error-ModelName{namespace='org.springframework.http', name='ResponseEntity'}
and I am wondering if I can use openapi3 annotation to fix this.
I try to get some data from a grqphql endpoint with F#.
I use Fsharp.Data
let apiQuery = """query findData {
apiData(Model:{
PageNumber: 1,
PageSize: 100
})
{
ErrorMessage Success ValidationResult TotalCount
Data{
ItemId
}
}
}"""
let queryGraphQl () =
Http.RequestString
( apiUrl,
headers = [ ContentType HttpContentTypes.Json;
Authorization ("bearer " + token)
],
body =
TextRequest apiQuery
)
But I get (500) Internal Server Error
The same in Python works fine:
query_headers = {
"Authorization": 'bearer %s' % token,
'Content-Type': 'application/json'
}
response = requests.post(url, json={'query': apiQuery}, headers=query_headers)
Any suggestions what I am missing?
In Postman I have to add
Content-Length and Host like to be calculated when request is sent.
It appears that the F# and Python code is not equivalent. The Python code contains additional query keyword in the payload.
I don't know the specifics of your particular endpoint, but I wrote similar code using one of the public interfaces.
open System.Net
open FSharp.Data
open FSharp.Data.HttpRequestHeaders
let key = "********-****-****-****-*************"
let uri k = $"https://api.everbase.co/graphql?apikey={k}"
let gurl = uri key
let apiQuery = """{ "query" :
"{ client { ipAddress { country { name } city { name } } } }"
}"""
let connectToGraph apiUrl apiQuery =
try
let res = Http.RequestString( url = apiUrl, httpMethod="POST", body = TextRequest apiQuery, headers = [ ContentType HttpContentTypes.Json; UserAgent "mozilla" ])
res
with
| _ as ex -> ex.Message
[<EntryPoint>]
let main argv =
let res = connectToGraph gurl apiQuery
printf "Response: %A" res
0
I suppose you should separate the query in your F# code from the rest of the definition with a ':'. Also the actual payload should be wrapped in quotes/double quotes to form a valid Json value.
I have a c# method that I'm trying to convert to ruby on rails . I'm using unirest but I think something is not working correctly. This is my C# method :
private static string HTTPPoster(string url, string prmSendData)
{
try
{
WebClient wUpload = new WebClient();
wUpload.Proxy = null;
Byte[] bPostArray = Encoding.UTF8.GetBytes(prmSendData);
Byte[] bResponse = wUpload.UploadData(url, "POST", bPostArray);
Char[] sReturnChars = Encoding.UTF8.GetChars(bResponse);
string sWebPage = new string(sReturnChars);
return sWebPage;
}
catch
{
return "-1";
}
}
And This is what I tried so far in rails with unirest :
def HTTPPoster(url)
xml = "My XML Goes Here"
byte_array = xml.bytes
headers = {}
headers['Content-Type'] = "application/json"
headers['Accept'] = "application/json"
response = Unirest.post(url,
headers: headers,
parameters: {
body: byte_array
})
puts "response #{response.body}"
if ![200,201].include?(response.code)
raise "Mblox Error: #{response.code}, #{response.body}"
end
end
If you also know other libraries that can achieve what I need please let me know.
I used Faraday gem and sent the data as xml and not as byte array. And now I am achieving want I wanted.
response = Faraday.post(url) do |req|
req.headers['Content-Type'] = "application/xml"
req.headers['Accept'] = "*/*"
req.headers['Accept-Encoding'] = "gzip, deflate, br"
req.body = xml
end
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.