Swagger datatype not generating docs - java

I have the below code in Swagger,
#Path("/v1")
#ApiOperation(value = "POST - Some Value", nickname = "post-funtion", consumes = "application/json", produces = "text/html; charset=UTF-8", tags = {
"Some Controller" })
#ApiImplicitParams({
#ApiImplicitParam(name = "Authorization", paramType = "header", dataType = "string", format = "JWT", required = false, value = "A User Service JWT"),
#ApiImplicitParam(name = "Request", value = "Request Object", paramType = "body", dataType = "org.pkg.SomeRequest", required = true) })
#ApiResponses({
#ApiResponse(code = 200, message = "Value Added", response = SomeResponse.class) })
private Object retrieveByName(Request request, Response response)
{
return new RetrieveByNameRqstHandler(catalogService, request, response).handle();
}
The code is supposed to automatically generate default json request depending upon the datatype which in this case is "org.pkg.SomeRequest" but there is nothing generated. On the contrary if I change the "org.pkg.SomeRequest" with "org.pkg.SomeResponse" there is a default JSON generated for this. Can anybody help me please?
Consider both classes SomeRequest,SomeResponse have the same code.
This is the image where I use "org.pkg.SomeRequest" in the dataType
This is the image where I use "org.pkg.SomeResponse" in the dataType

According to this GitHub issue on Swagger core project, if you add the annotation #ApiImplicitParam should resolve your problem.
#ApiImplicitParams({
#ApiImplicitParam(
required = true,
dataType = "com.example.SomeObjectDto",
paramType = "body"
)
})
But normally if you just add the class on your method signature it'll work.
private Object retrieveByName(SomeObjectDto someObjectDto) {
someCode();
}
Also SomeObjectDto class should contain "get" methods for your variables like.
class SomeObjectDto {
private String info;
getInfo(){
return info;
}
}
Will produce the following JSon.
{ info: "string" }

ApiImplicitParam can map a parameter to a correct type, but the type must be detected by swagger, so must be a valid reference.
The only way I could make this working is by using additionalModels method.
Example in spring-boot:
configure swagger
import springfox.documentation.spring.web.plugins.Docket;
import com.fasterxml.classmate.TypeResolver;
...
#Bean
public Docket api(TypeResolver typeResolver) {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("your-group-rest-api")
.select()
.apis(RequestHandlerSelectors.basePackage("your.package"))
.paths(PathSelectors.any())
.build()
.additionalModels(typeResolver.resolve(YourModel.class))
.apiInfo(apiInfo());
}
controller
#ApiOperation...
#ApiImplicitParams(
#ApiImplicitParam(dataType = "YourModel", name = "requestJson", paramType = "body"))
#ApiResponses...
#RequestMapping...
public void yourMethod(#RequestBody String requestJson,...)
Of course, you could have an InputStream parameter for the request and map that to your model.

Related

Working with SwaggerUI & JAX-RS - Adding a custom header globally

I was trying to inject a global header to my suite of requests. While studying the solution I found the annotation #ApiImplicitParam that has #Target(value=METHOD)
example:
#DeleteMapping(value = "/token/{version}", produces = "application/json; charset=UTF-8")
#ApiOperation(value = "delete actual token", produces = "application/json", response = Application.class)
#ApiImplicitParams(
{
#ApiImplicitParam(name = "My-custom-header", required = true, paramType = "header",
dataType = "string", value = "custom header", defaultValue = "GOOD")
}
)
public Application deleteAuthenticationToken(
#ApiParam(required = true, value = "version", defaultValue = "v1") #PathVariable("version") String version,
HttpServletRequest request) {
here the docs
https://docs.swagger.io/swagger-core/current/apidocs/io/swagger/annotations/ApiImplicitParam.html
This means that this annotation can't be set to the resource and being automatically applied to all the methods.
I need that every call has this custom header, is there a way of doing it globally?
EDIT1: I added a HeaderParam in the swagger config but it doesn't work
private void inizializeSwagger(){
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion(PropertiesConfig.getConfig().getString(PropertiesConst.P_SWAGGER_API_VERSION));
beanConfig.setSchemes(PropertiesConfig.getConfig().getStringArray(PropertiesConst.P_SWAGGER_PROTOCOL));
beanConfig.setHost(PropertiesConfig.getConfig().getString(PropertiesConst.P_SWAGGER_HOST));
beanConfig.setResourcePackage(PropertiesConfig.getConfig().getString(PropertiesConst.P_SWAGGER_RESOURCES_PACKAGE));
Swagger swagger = new Swagger();
swagger.securityDefinition("basic", new BasicAuthDefinition());
Parameter globalOperationParameter = new HeaderParameter();
globalOperationParameter.setName("System");
globalOperationParameter.setRequired(Boolean.TRUE);
globalOperationParameter.setDescription("definition of the calling system");
swagger.parameter("System", globalOperationParameter);
new SwaggerContextService().updateSwagger(swagger);
beanConfig.setScan(true);
}
EDIT2:
It adds the parameters but SwaggerUI 2.0 doesn't show it
EDIT3:
I had to change the swaggerUI library implementation:
in the cycle of // operations (row 4695) I added the following
for(name in spec.parameters) {
var actualParam = spec.parameters[name];
if(actualParam.in === 'header') {
parameters.unshift({"name":actualParam.name,
"in":actualParam.in,
"description":actualParam.description,
"required":actualParam.required,
"type":"string",
"default":""})
}
}
In other words I added the params I needed in the cycling operation.
I leave this ticket opened for better and cleaner solutions

How to specify request body in Spring boot for swagger UI?

I have the following annotated controller for swagger:
#PostMapping("/getMediaDataProduct/V2")
#ResponseBody
#ApiOperation(value = "get media data product v2")
#ApiResponses({#ApiResponse(code = 200, message = "Successful", response = MediaDataProductResponseV2.class)})
#ApiImplicitParams(value = {
#ApiImplicitParam(name = "xxxxx", value = "xxxx", paramType = "header", required = true),
#ApiImplicitParam(name = "xxxx", value = "xxxx", paramType = "header", required = true),
#ApiImplicitParam(name = "xxxx", value = "xxxx", paramType = "header"),
#ApiImplicitParam(name = "xxxx", value = "xxxx", paramType = "header", required = true),
// #ApiImplicitParam(name = "xxxxxx", value = "xxx", paramType = "header" ,required = true),
#ApiImplicitParam(name = "xxxxxx", value = "xxxxx", paramType = "header"),
#ApiImplicitParam(name = "xxxxxxx", value = "xxxxxxxx", paramType = "header", required = true)})
public ResponseEntity getMediaDataProductV2(#RequestBody final String request, #RequestHeader final HttpHeaders headers) {
Slogger.get().debug("/getMediaDataProduct/V2: this.mediaDataService: " + this.mediaDataService);
MediaDataProductResponseV2 response = mediaDataService.getMediaDataProductV2(request);
HttpStatus status = getHttpStatus(response.getStatusMessages(), response.getSystemErrors());
List<StatusMessage> statusMessages = appendSuccessStatusMessage(response.getStatusMessages(), status);
if(statusMessages !=null) {
response.setStatusMessages(statusMessages);
}
return new ResponseEntity<>(response, new HttpHeaders(), status);
}
How can you specify the request body so it's displayed in the swagger UI?
update: I have tried to research on this in many forums but doesn't seem to find an answer. "How can you specify the request body class by using swagger annotations just as I do with ApiResponses?". There is a default parameter in swagger UI created for body but don't know how to specify it by referencing the request body class.
If I understood your problem correctly, you need to have a response type shown in the swagger definition. Most of the time Swagger will automatically map your method return type as response type.
But, it fails to do so when it's a generic class, as in your case its ResponseEntity.
If you can make your return type to something like ResponseEntity<MediaDataProductResponseV2>, it should work.
According to Swagger documentation, you can declare paramType attribute at #ApiImplicitParam only with the following values:
Valid values are path, query, body, header or form.
the Default is ""
In your case, try to do something like this.
#ApiImplicitParams(value = {
#ApiImplicitParam(name = "request", value = "The body is a simple string", paramType = "body", required = true),
#ApiImplicitParam(name = "headers", value = "It'll contain all header attributes in request", paramType = "header", required = true)})
public ResponseEntity getMediaDataProductV2(#RequestBody final String request, #RequestHeader final HttpHeaders headers) {
Slogger.get().debug("/getMediaDataProduct/V2: this.mediaDataService: " + this.mediaDataService);

Trying to pass Json object to Jersey restfull service as FormDataParam

I do not know how to pass Java object to Jersey restfull service as FormDataParam. The service works perfectly with curl, but Swagger responds with error. The problem is most probably with annotation #FormDataParam. Swagger does not throw 415 Error Unsupported Media File, but it
Here is the code Jersey service:
#POST
#ApiOperation(value = "Upload", notes = "", response = ImageAPIResponse.class)
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, "application/x-javascript" })
#Consumes(MediaType.MULTIPART_FORM_DATA)
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Successful or application error (see notes)", response = ImageAPIResponse.class) })
public ImageAPIUploadUpdateResponse upload(
#ApiParam(required = true, value = "user name part of credentials") #FormDataParam("user_name") String userName, //
#ApiParam(required = true, value = "") #FormDataParam("file") File file, //
#ApiParam(required = true, value = "") #FormDataParam("file") FormDataContentDisposition contentDispositionHeader,
#ApiParam(required = false, value = "") #FormDataParam("file_name") String fileName,
#ApiParam(required = false, value = "") #FormDataParam("meta_data") ImageMetaData metaData) {
ImageAPIResponse imageAPIResponse = new ImageAPIResponse();
//metaData object keeps being null...
return imageAPIResponse;
}
public class ImageMetaData{
public String fileName;
public String fileType;
}
Did anyone encounter a similar problem with FormDataParam? It would be great if I could use this Jersey annotation in my parameters.

Swagger UI and Play routing *path

I'm having trouble with Swagger understanding Play! 2.0 routing wildcard routing, so the swagger ui ends up with broken URL.
My routes file has this route:
GET /settings/api/:project/*path #controllers.API.getParams(project, path)
Then my Controller has the following code:
#ApiOperation(value = "Returns settings for given project and path.", response = String.class, httpMethod = "GET")
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Request completed successfully."),
#ApiResponse(code = 500, message = "Internal error while processing request")
})
#ApiImplicitParams({
#ApiImplicitParam(name = "project", value = "Project name", required = true, dataType = "String", paramType = "path"),
#ApiImplicitParam(name = "path", value = "path", required = true, dataType = "String", paramType = "path")
})
public Result getParams(String project, String path) {
return ok(path);
}
Then when Swagger UI gets rendered, I see the path for this action rendered as
POST /settings/api/{project}/{path<.+>
And when I do a call it turns into
/settings/api/test/{path<.+>
So basically the :project gets replaced but the *path remains broken/intact.
Please share if you know how to fix this. Thanks!
So turns out that swagger doesn't support wildcard routes.

Personnalize route format - Swagger with Play Framework

I am developing an API with Swagger UI using Play Framework.
But I got a little problem (not a big problem) :
My URL are :
https://url/find?param1=false&&&param4=1
But I have '&&' when a parameter is not given ( I mean param2 and param3)
What I want is simply :
https://url/find?param1=false&param4=1
Here is :
My Controller :
#Api(value = "url", description = "...")
public class nameClassApiController extends ApiController {
#ApiOperation(value = "...", notes = "...", response = nameClass.class, httpMethod = "GET")
#ApiResponses(value = { #ApiResponse(code = 200, message = "success"), #ApiResponse(code = 500, message = "error", response = ApiError.class) })
public static Result getList(
#ApiParam(value = "param1", required = false) #QueryParam("param1") Long param1,
#ApiParam(value = "param2", required = false) #QueryParam("param2") Long param2, ....) {
return getJsonSuccessResponse(className.getList(param1, param2, ...));
}
And my route definition :
GET url/find className.getList(param1: java.lang.Long ?= null, param2: java.lang.Long ?= null, param3: java.lang.Long ?= null, param4: java.lang.Long ?= null)
NB : Te parameters are optional so in my route I need to put the parameter by default to null.
Any solutions ?
Thank you !
Fixed by upgrading swagger-UI version to 2.0 (latest)

Categories

Resources