Personnalize route format - Swagger with Play Framework - java

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)

Related

Swagger 3 / OpenApi How to add two descriptions to the same status code

I am trying to do some documentation to my small api.
What should I do in situation when on status code 400 I can have 2 possible descriptions?
I would like to do something like:
#ApiResponses(value = {
#ApiResponse(responseCode = "200", description = "description",
content = {#Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = #Schema(implementation = StudentFullDTO.class))}),
#ApiResponse(responseCode = "400", description = "description" +
"ExceptionResponseObject", content = #Content),
#ApiResponse(responseCode = "400", description = "Odescription",
content = #Content)})
#PatchMapping("/{id}")
public ResponseEntity<StudentFullDTO> patch(#PathVariable String id,
#RequestBody #Valid Map<Object, Object> fields) {
StudentEntity studentEntity = studentEntityService.patchStudentEntity(id, fields);
StudentFullDTO studentFullDTO = modelMapperService.mapObjectToObjectOfEnteredClass(studentEntity, StudentFullDTO.class);
return new ResponseEntity<>(studentFullDTO, HttpStatus.OK);
}
Is it possible to define the same status multiple times?
You'll need to merge the two descriptions and specify them within the same #ApiResponse(description = "...") annotation. This is because OpenAPI Specification only allows defining each HTTP status code once per operation.
#ApiResponse(responseCode = "400",
description = "Possible reasons: reason 1; reason 2",
content = #Content),

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);

Swagger datatype not generating docs

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.

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.

How to annotate Play 2 webapp model for swagger?

I'm an android/java developer new to Play2 framework. I'm trying to generate documentation to my RESTful API with swagger.
I've managed to include swagger into my Play2 webapp and generate simple api-docs.json. The only part I am missing is model description. I have User controller and User model in /controllers and /models accordingly.
#Api(value = "/user", listingPath = "/api-docs.{format}/user", description = "User registration and authorisation")
public class User extends Controller {
#POST
#ApiOperation(value = "Create user", notes = "Used to register new user.")
#ApiParamsImplicit(#ApiParamImplicit(name = "body", value = "Created user object", required = true, dataType = "User", paramType = "body"))
#BodyParser.Of(BodyParser.Json.class)
public static Result createUser() {
JsonNode json = request().body().asJson();
ObjectNode result = Json.newObject();
JsonNode body = json.findPath("body");
if(body.isMissingNode()) {
result.put("status", "KO");
result.put("message", "Missing parameter [body]");
return badRequest(result);
}
JsonNode name = body.get("name");
if(name == null) {
result.put("status", "KO");
result.put("message", "Missing parameter [body.name]");
return badRequest(result);
}
result.put("status", "OK");
result.put("message", "Hello " + name.getTextValue());
return ok(result);
}
}
I've tried to annotate model exactly as in an example
#XmlRootElement(name = "User")
public class User {
public String name;
#XmlElement(name = "name")
public String getName() {
return name;
}
}
The result is:
{
apiVersion: "beta",
swaggerVersion: "1.1",
basePath: "http://localhost:9000",
resourcePath: "/user",
apis: [
{
path: "/user",
description: "User registration and authorisation",
operations: [
{
httpMethod: "POST",
summary: "Create user",
notes: "Used to register new user.",
responseClass: "void",
nickname: "createUser",
parameters: [
{
name: "body",
description: "Created user object",
paramType: "body",
required: true,
allowMultiple: false,
dataType: "User"
}
]
}
]
}
]
}
Any ideas ?
I've found the answer myself.
It appears that swagger acknowledges a model when it is being used as a return value, ie responseClass:
#ApiOperation( value = "Find quiz by ID",
notes = "Returns a quiz with given ID",
responseClass = "models.Quiz" )
#ApiErrors( value = {
#ApiError(code = 400, reason = "Invalid ID supplied"),
#ApiError(code = 404, reason = "Quiz not found") })
public static Result getQuizById(
#ApiParam(value = "ID of question that needs to be fetched", required = true) #PathParam("quizId")
String quizId) {
ObjectNode result = Json.newObject();
return ok(result);
}
Simply adding method like this makes corresponding model appear in api-docs.json.

Categories

Resources