How to use swagger with query params deserialising to class? - java

I have spring rest controller and i want it documented via swagger. It looks like this:
#ApiOperation(value = "Returns comments list")
#RequestMapping(method = RequestMethod.GET)
public CollectionResponse<CommentDTO> getComments(CommentFilterDTO filterDTO) {
Page<CommentEntity> requisitionComments = commentService.getComments(filterDTO);
return Convert.convert(requisitionComments, COMMENT_ENTITY_2_COMMENT_DTO);
}
CommentsFilterDTO is
public class CommentFilterDTO {
private Long requisitionId;//get, set
private CommentType commentType;//get, set
// etc
}
This controller takes query string with pageable and filterDTO params like this:
my/comments?requisitionId=1&commentType=COMMENT
Now i'm trying to document it via swagger and i want all possible query parameters documented as well, but if i leave it like this i see only
I can document query params via #ApiImplicitParams like
#ApiImplicitParams({
#ApiImplicitParam(name = "requisitionId", value = "Requisition id", required = true, dataType = "long", paramType = "query"),
...
})
Is there any way to tell swagger what all CommentFilterDTO fields can be used as query parameters?

Related

Can I use some properties file instead Swagger annotations for my Controllers classes in Spring Boot

I'm using swagger with spring boot in my project, and there are some API's that I need to use annotations for change some descriptions, parameters names, ou insert examples.
For do it, I need to change my controller, and insert some annotations, for example:
#ApiOperation(value = "Returns a person list")
#ApiImplicitParams({
#ApiImplicitParam(name = "Authorization", value = "Access Token", required = true, allowEmptyValue = false, paramType = "header", dataTypeClass = String.class, example = "Bearer access_token"),
#ApiImplicitParam(name = "X-Custom-Header", value = "A Custom Header", required = true, allowEmptyValue = false, paramType = "header", dataTypeClass = String.class, example = "my header example")
})
#RequestMapping(value = "/person", method = RequestMethod.GET, produces="application/json")
public List<Pessoa> get() {
return personRepository.findAll();
}
But in some cases, it make my Controller class with a lot of information just because swagger, my question is: There is a way instead of use annotations in my Controller class, use a properties file, or another Class just with the Swagger annotations, something like:
myController.myMethod.apiOperation=Returns a person list
I knew that i can insert only the value property in the file, but i would like to not use any annotation related to swagger/OpenApi in my controller.

RequestParam value converter

We are using Swagger to generate our API interfaces and model classes. However, Swagger generates the request parameters of our endpoints in a camelCase style instead of snake_case as it specified in our APIs.
For example, the code generated is:
#RequestMapping(value = "/search/test",method = RequestMethod.GET)
public ResponseEntity<Location> getLocation(#RequestParam(value = "locationId",required = true) locationID)
when it should be:
#RequestMapping(value = "/search/test",method = RequestMethod.GET)
public ResponseEntity<Location> getLocation(#RequestParam(value = "location_id",required = true) locationID)
Is there any way to match programmatically (maybe using a HttpConverter) a request containing the param "location_id" with the method containing "locationId" without throwing a PathNotFound exception?
All our params are even Integer or String.

Provide sample value for request parameter in Swagger

I have a method signature for a rest method in a Spring-Boot RestController that looks like this:
#RequestMapping(
value = "/path",
method = RequestMethod.POST,
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE
)
#ApiImplicitParams({
#ApiImplicitParam(
name = "message",
value = "Message that is sent to the method",
required = true,
dataType = "string",
paramType = "body"
)
})
public #ResponseBody String receiveMessage(#RequestBody String message) {
// ...
return "{\"success\": true}";
}
I would like to provide a "sample" value for the message parameter that is a JSON string (e.g. {"key" : "value"}). Does anybody know how I can do this using Swagger annotations? I tried
#ApiImplicitParams({
#ApiImplicitParam(
// ...
example = "...JSON value..."
)
})
but it didn't work. What I would like to have is a "sample value" in the documentation, that the reader can click on to have the parameter value field in the documentation filled with the given sample value. Is this possible?
Here is a screenshot of how it might look like:
Just to prevent "useless" answers: I cannot change the type of the parameter from String to some class type due to my business logic.
Unfortunately you cannot provide an sample or example value for atomic parametera (String, Number, ...).
You can only provide an example if the parameter is an object with a schema, you only have to add an example property to the property description:
properties:
firstName:
description: first name
type: string
example: John
As a last resort you could add an example value in the parameter's description (value in the ApiImplicitParam annotation).
#ApiImplicitParam(
name = "message",
value = "Message that is sent to the method. Example: value",
required = true,
dataType = "string",
paramType = "body"
)
For Spring Boot users, assuming you've a REST method, accepting json body, but for some reasons doesn't explicitly uses #RequestBody. Follow below steps to generate proper Swagger documentation
Update SpringFox configuration bean for additional model
#Bean
public Docket apiDocket() {
return new Docket(DocumentationType.SWAGGER_2)
// ...
.additionalModels(new TypeResolver().resolve(YourRequestModel.class));
}
Update controller API for #ApiImplicitParams
#PostMapping("/your-api")
#ApiOperation(value = "brief description", notes = "Greater details come here")
#ApiImplicitParams({
#ApiImplicitParam(paramType = "header", name = "x-locale", example = "en"),
#ApiImplicitParam(paramType = "body", dataType = "YourRequestModel")
})
public YourResponsetModel processRequest() {
// ...
return null;
}
This will generate us Swagger with an optional header x-locale, and body of type YourRequestModel.
You can try this:
public MyObject myController(#ApiParam(example = "examplestring") #RequestParam("name") String name,
#ApiParam(example = "1")#RequestParam("eventNo") int eventNo, #ApiParam(example = "2")#RequestParam("halRequestNo") int halRequestNo){

Collect multiple query params in a class

I am implementing a web service using spring boot 1.3.6. In my controller, I have a method like:
#RequestMapping(value = "/employees/{id}", method = RequestMethod.PUT)
createEmployee(#PathVariable String id,
#QueryParam(required = false, value = "department") Set<String> departments)
I want to collect the request parameters in a class like:
class EmployeeParams {
public String id;
public Set<String> departments;
}
I tried using:
#RequestMapping(value = "/employees/{id}", method = RequestMethod.PUT)
createEmployee(EmployeeParams param) { ... }
But it does not work. I get the id in above class but not departments. What is the proper way of collecting the request parameters in Spring requests?
You should add a custom converter that implements Spring org.springframework.core.convert.converter.Converter<String, EmployeeParams> and register it with Spring.
See Spring documentation.
This stack overflow issue also discusses some details on adding a custom converter or formatter.

Spring Data Pagination & AJAX

I have the following Controller and I've just included pagination into my returned results
#RequestMapping(value = "/search/{person}", produces="application/json", method = RequestMethod.GET)
public Page<Person> findAllPersons(#PathVariable String person) {
Page<Person> list = personRepo.findAll(new PageRequest(1, PAGE_SIZE));
return list;
}
I'm now trying to figure out how to actually tab through these results - The search on the Person table has is it's own AJAX request, where as selecting "next" or "previous" on my UI tool can launch it's own GET
<a id="previous" href="onclick="setPageNumber(1)">
<a id="next" href="onclick="setPageNumber(2)">
function setPageNumber(num) { //relaunch request with page number value retrieved from previous or next}
Should I include a pageNumber as a #PathVariable like so:
#RequestMapping(value = "/search/{person}/{pageNumber}", produces="application/json", method = RequestMethod.GET)
public Page<Person> findAllPersons(#PathVariable String person, #PathVariable int pageNumber) {
Page<Person> list = personRepo.findAll(new PageRequest(pageNumber, PAGE_SIZE));
return list;
}
or should setting the pageNumber be a completely separate controller method that somehow invokes findAllPersons with the pageNumber argument? I may be confusing myself here - any input is welcome thanks!
For REST service I would put it to the parameters rather then to URI page_start=X&page_size=Y.
I know this post isn't active for a long time but for anyone still looking for a way to use Spring pagination with Ajax, here are some possible solutions:
1. If your repository is an instance of JpaRepository (or more precisely PagingAndSortingRepository) then you can simply pass a Pageable to it:
#Controller
public class FooController {
//...
#GetMapping("/foo/list")
public List<Foo> handleList(Pageable pageable) {
return fooRepository.findAll(pageable);
}
//...
}
2. Instead of Pageable, you can also retrieve your pagination parameters as #RequestParam and create a PageRequest yourself. This approach might be useful if the project does not use Spring Data and JPA:
#Controller
public class FooController {
//...
#GetMapping("/foo/list")
public List<Foo> handleList(
#RequestParam(value = "size", required = false) Optional<Integer> pageSize,
#RequestParam(value = "page", required = false) Optional<Integer> pageNumber,
#RequestParam(value = "sort", required = false) Sort sort,
) {
PageRequest pageable = new PageRequest(pageNumber.orElse(0), pageSize.orElse(10), sort);
return fooRepository.customfindAll(pageable);
}
//...
}
(e.g. this repository above might be a class extending a JDBCRepository such as this one )
And for the AJAX part of these two possible solutions, something like that can be used:
// ... handle pageNo, listSize etc.
var url = '/yourprj/foo/list?page=' + pageNo + '&size=' + listSize
$.ajax({
type: "GET",
contentType: "application/json",
url: url,
success: function(result) {
// handle Foo list...
}
});
3. Alternatively, if you are using Thymeleaf+Spring Data there is a dialect to automatically add pagination.

Categories