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&&¶m4=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¶m4=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
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),
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);
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.
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.
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.