I am using Springfox Swagger2 version 2.4.0, Springfox Swagger UI version 2.4.0 and Swagger Annotations version 1.5.0 in my Spring Boot application.
The question here is, I am able to generate swagger UI for my controller's API and I am able to test the same. But I am not able to specify request header description for my request header. I m using #RequestHeader annotation for the same.
The code snippet in my controller API is follows:
#RequestHeader(name = "Api-Key") String apiKey
The Swagger UI for the request header is as follows:
The highlighted rectangular area in the image represents the description of the request header.
Currently it just picks up the data mentioned in the name attribute and shows it. But i wanna give a different description for the same. i.e. "Value of license key"
How can i achieve this in Swagger UI as #RequestHeader annotation only have value, defaultValue, name and required attributes? Any help would be really appreciated.
Update: Looking for a solution out of the box without any custom annotation of my own
Maybe my answer will help somebody.
As mentioned Dilip Krishnan in his answer you could use io.swagger.annotations.ApiParam or io.swagger.annotations.ApiImplicitParam Swagger annotations for fine-tuned custom documentation.
#ApiParam could be used for registered method parameters.
#ApiImplicitParam could be used if API parameter wasn't registered explicitly.
#RestController
#RequestMapping(value = "/v1/test", produces = "application/json")
#Api(value = "/v1/test")
public class TestController {
#ApiOperation(value = "Do Something method", tags = "Test method")
#RequestMapping(value = "/doSomeThing", method = RequestMethod.GET)
public Foo doSomeThing(
#ApiParam(value = "Param1 Description", required = true)
#RequestParam String param) {
throw new UnsupportedOperationException("do Some Things");
}
#ApiOperation(value = "Do Something Another method", tags = "Test method")
#ApiImplicitParams({
#ApiImplicitParam(name = "anotherParam1", value = "Another Param1 Description", paramType = "header"),
#ApiImplicitParam(name = "anotherParam1", value = "Another Param1 Description", paramType = "header")
})
#RequestMapping(value = "/doSomeThingAnother", method = RequestMethod.GET)
public Foo doSomeThingAnother(Bar bar) {
throw new UnsupportedOperationException("do Some Thing Another");
}
}
And in the end you could see following picture
TL;DR is that you would have to build your own plugin to do it.
Basically the only out-of-the-box annotations to augment the description in this case are #ApiParam and to be more accurate #ApiImplicitParam. Unfortunately neither of those annotations support descriptions.
So my suggestion would be to:
Create your own annotation that would look like this
#RequestHeader(name = "Api-Key")
#Description("Value of license key") String apiKey
NOTE: There is already an annotation in spring that is suitable for this.
Create your own ParameterBuilderPlugin
Implement the plugin as shown below
public class Test implements ParameterBuilderPlugin {
#Override
public void apply(ParameterContext parameterContext) {
ResolvedMethodParameter methodParameter =parameterContext.resolvedMethodParameter();
Optional<Description> requestParam = methodParameter.findAnnotation(Description.class);
if (requestParam.isPresent()) {
parameterContext.parameterBuilder()
.description(requestParam.get().value());
}
}
#Override
public boolean supports(DocumentationType documentationType) {
return false;
}
}
Pick a value of the order that is is applied after swagger annotations have been processed.
Also please upgrade your springfox library to the latest version.
We had the same issue, and resolved the problem in the following way:
.. #RequestHeader(value = "..") #ApiParam(value = "Description") String param ..
The idea is to add "description" field into generated swagger. It could look hacky, but it's a quick simple solution which can be useful in your personal case.
Quick, easy valid solution is to use an enum, for example:
#RequestHeader(value = "someval") ALLOWED_VALUES input
private enum ALLOWED_VALUES {A, B, C};
The following will show in swagger:
Available values : A, B, C
Related
I have a basic User DTO class...
public class User {
#JsonProperty("firstName")
private String firstName;
#JsonProperty("lastName")
private String lastName;
}
...and a basic request handler in a #RestController class:
#RequestMapping(path = "/users", method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE })
public UserMessage createUser(#RequestBody User user){
return userService.createUser(user);
}
How can I restrict incoming JSON payloads to contain at most only the required keys?
i.e. accept this payload:
{
"firstName":"foo",
"lastName":"bar"
}
And throw a custom exception on this:
{
"firstName":"foo",
"lastName":"bar",
"type":"admin",
"asdf":"asdf"
}
I read about custom Converters, ArgumentResolvers, and I believe I could simply put an additional Map parameter in the handler and validate before service call, however I'd like to know the "best" way of handling this issue.
Regarding the User bean in your example it also already not possible, that potential other JSON fields than firstName and lastName could be mapped, simply because there are no fields in User which could hold the relevant data.
Should the User bean in your question be not complete, e.g. for simplicity reasons, and contain more fields, also then should everything be fine, as long as you did not configure your your ObjectMapper with com.fasterxml.jackson.databind.DeserializationFeature#FAIL_ON_UNKNOWN_PROPERTIES => false or you use the annotation #JsonIgnoreProperties(ignoreUnknown = true) on your bean.
To sum it up: Jackson's default behavior is FAIL_ON_UNKNOWN_PROPERTIES (default: true)
For further information you can also consult the respective Deserialization docs.
Solved the issue, this thread helped
#JsonIgnoreProperties(ignoreUnknown=false) is not working in Spring 4.2.0 and upper version
mle, your answer wasn't right, since I was using the latest version of Spring Framework and the ObjectMapper's FAIL_ON_UNKNOWN_PROPERTIES is turned off by default. Additionally I was needed to set #JsonIgnoreProperties(ignoreUnknown = false) in my User DTO class (as the actual class' superclass had this set to true).
Tested it, runs like a charm, while custom errors can be handled in a #ExceptionHandler(HttpMessageNotReadableException.class) annotated handler.
Below are the 2 RequestMapping handler methods in my rest controller with the same value but different param.
#ApiOperation(value = "Query with name", nickname = "queryWithNameParam")
#RequestMapping(value = "/query", params = "name",
method = RequestMethod.GET)
public void queryWithNameParam()
#ApiOperation(value = "Query with code", nickname = "queryWithCodeParam")
#RequestMapping(value = "/query", params = "code",
method = RequestMethod.GET)
public void queryWithCodeParam()
I am able to invoke both the methods using resttemplate, but the API is not being shown on the browser when accessing swagger-ui.html
I am using springboot 2.0.3.RELEASE and springfox 2.9.2
Now there is only one option to fix this:
Add springfox-swagger-ui-rfc6570 instead of springfox-swagger-ui as a dependency.
Set enableUrlTemplating(true) in your docket configuration.
Source:
http://springfox.github.io/springfox/docs/current/#springfox-rfc6570-support-strong-incubating-strong
Open issues in springfox Github project:
https://github.com/springfox/springfox/issues/2354
https://github.com/springfox/springfox/issues/2042
Closed issues:
https://github.com/springfox/springfox/issues/2541
https://github.com/springfox/springfox/issues/1874
I am using springfox-swagger2 and springfox-swagger-ui version 2.8.0 which was not exists in previous version 2.5.0. I am seeing in this version there is an Example Value added in the request however, the example shows default as application/xml as default .
#RequestMapping(value = "/",
produces = {"application/xml","application/json"},
consumes = {"application/xml", "application/json"}, method = RequestMethod.POST)
public ResponseEntity<?> addEmp(
#ApiParam(name = "request", value = "Payment Adding a new Employee Payload", required = true)
#Valid #RequestBody Employee request)
This Example Value is getting derived from the the Object Employee and converting to either xml, json etc. My question is, is there any way the default value for Example Value can be defined in the drop down of from the multiple consuming object types defined in #RequestMapping'sconsumes` array.
Screenshot
To fix this issue set the validatorUrl(String str) as empty string in the UiConfiguration configuration bean, passing null wouldn't work. Hope this help whomever referring this thread in future.
#Bean
public UiConfiguration uiConfig() {
return UiConfigurationBuilder.builder()
.
.
.validatorUrl(StringUtils.EMPTY)
.build();
}
I am trying to integrate Swagger2 to my Spring Boot based application. The issue is that swagger does not consider model attributes.
#GetMapping(value = "/events", produces = MediaType.APPLICATION_JSON_VALUE)
public PagedResources<EventResource> getEvents(
#Valid SearchCriteria searchQuery,
BindingResult result,
PageableResourcesAssembler<EventResource> assembler){
// code
}
As you can see SearchCriteria is a class which gets automatically binded by Spring.
public class SearchCriteria {
private List<EventType> eventTypes;
private LocalDateTime from;
// getters setters
}
But what swagger generates is following:
which is not expected. The desired result might be generated by annotation getEvents method by
#ApiImplicitParams({
#ApiImplicitParam(name = "eventTypes", paramType = "query"),
#ApiImplicitParam(name = "from", paramType = "query")
})
PagedResources<EventResource> getEvents(#ApiParam(hidden = true ) #Valid SearchCriteria searchQuery
but the #ApiParam(hidden = true ) does not work, because in the Swagger UI is the searchQuery parameter still present.
What is the proper way how to describe request parameters contained in a POJO using swagger? To me the best way would by annotation SearchCriteria class with #ApiModel but it does not work.
This bug was fixed in Springfox v2.7.0.
Original Answer:
The #Valid-annotation actually does that the param will be seen as body-param.
As this shouldn't do this I've opened an issue on the springfox github page.
but the #ApiParam(hidden = true ) does not work
Springfox provides for that the springfox.documentation.annotations.ApiIgnore-annotation which should work.
Like written in this issue using the annotation from springfox is the right way.
I have a Spring data REST project I am using to learn.
Right now I want to set up a query in this repository:
#RepositoryRestResource(collectionResourceRel = "users", path = "users")
public interface UserRepository extends PagingAndSortingRepository<User, Long>
namely, this guy:
#RestResource(path = "login", rel = "login")
User findByUsernameAndPassword(String username, String password);
A basic repository is easy to set up. So are custom GET requests like:
List<Item> findByType(#Param("type") String type);
or
#RestResource(path = "byMaxPrice")
#Query("SELECT i FROM Item i WHERE i.price <= :maxPrice")
List<Item> findItemsLessThan(#Param("maxPrice") double maxPrice);
But these are still GET requests. I would like to use a POST request. The method = RequestMapping.POST markup isn't accepted by #RestResource .. and I dont see any mention of different request types in the documentation. how do I do this?
You need to define a custom Controller to handle POST requests. If you just want to do POST for the default Repository methods, unfortunately, you still have to make a pass through Controller
#RepositoryRestController
public class MyController implements Serializable {
...
#RequestMapping(value = "/myConstroller/myPostMethod", method = RequestMethod.POST
, consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseStatus(value = HttpStatus.OK)
public #ResponseBody List<MyObjects> updateMyObjectList(
#RequestBody List<MyObjects> objects) {
// Call your repository method here, or a custom service, or whatever
}
See Spring MVC docs for further information, specifically section 5.2.1, which describes the default HTTP Method support for Repositories, and 16.4, which gives a custom Controller example.
From 5.2.1:
POST
Creates a new entity from the given request body.
Thus, POST is supported, but not to do what you are trying to do. If you want to "hide" URL parameters by using POST instead of GET, you need a custom Controller.