Spring fox swagger ui version 2.8.0 Example Value - spring-boot

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

Related

How to write appropriate endpoint in Spring Boot for GET request?

I have an assignment to write simple GET request.
The format that is going to be typed in URL is like this:
http://localhost:8080/api/tasks/20-08-2020
Server should return TODOs for that date. I did managed to write a finder method. But not sure how to write an endpoint. This is what I have so far:
#GetMapping(value = "/{date}", consumes="application/json")
public ResponseEntity<List<Task>> getTasksByDateUsingURL(#PathVariable("date") #DateTimeFormat(pattern="dd-MM-yyyy") #Valid LocalDate dueDate){
List<Task> tasks = taskService.getAllTasksByDate(dueDate);
return new ResponseEntity<List<Task>>(tasks,HttpStatus.OK);
}
This is inside RestController class:
#RestController
#RequestMapping(value="/api/tasks")
public class TaskController {...}
I cannot hit this GET endpoint...
Workaround for your problem is to get the string as parameter and parse it manually
#GetMapping(value = "/{date}", consumes="application/json")
public ResponseEntity<List<Task>> getTasksByDateUsingURL(
#PathVariable("date")
String date
){
LocalDate dueDate = parse(date);
List<Task> tasks = taskService.getAllTasksByDate(dueDate);
return new ResponseEntity<List<Task>>(tasks,HttpStatus.OK);
}
private LocalDate parse(String stringDate) {
// TODO
}
As author said in comments:
When try to call the endpoint from browser, the mapping is not executed.
Seems like that the browser is sending request with wrong Content-Type header. Your mapping is explicitly requires only application/json value.
When try to call the endpoint from Postman, the application returns 400 status.
I could not see the body of response, but I guess the problem is #Valid annotation on the parameter. How should Spring validate the LocalDate?
So the solution is to remove consumes="application/json" from mapping or send corresponding Content-Type value
and remove #Valid annotation from parameter.

How to accept RequestBody of different class types dynamically

I am using Spring Boot . Writing rest api's
where for the same api url , the request json structure varies
Is there any way we can apply Factory design or some thing else
#RequestMapping(value = "/myservice/{type}", method = RequestMethod.POST)
#ResponseBody
public ResponseEntity<?> myServiceApi(#PathVariable String type,
#RequestBody SomeClass1 somereq) {
// here based on type , the RequestBody can be either SomeClass1 or SomeClass2
// both the SomeClass1 and SomeClass2 has nothing in common .
}
The above code will work only if the request json is in SomeClass1 format , but i needed it to accept among {SomeClass1 , SomeClass2}
You could do this by passing the JSON as a String into your controller method and then mapping this to whichever object you expect to need:
#PostMapping(value = "/myservice/{type}")
public ResponseEntity<?> myServiceApi(#PathVariable String type,
#RequestBody String somereq) {
ObjectMapper mapper = new ObjectMapper();
if (<something that indicates SomeClass1>) {
SomeClass1 someClass1 = mapper.readValue(somereq, SomeClass1.class);
} else if (<something that indicates SomeClass2>) {
SomeClass2 someClass2 = mapper.readValue(somereq, SomeClass2.class);
}
}
Although to be honest if you really are expecting bodies with completely different structures my advice would be to just make separate API calls for these.

Best way how to describe "ModelAttribute" with Swagger

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.

Customizing Request Header description in Swagger UI using Springfox-Swagger2

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

Why Spring Boot project/REST web-service not response into JSON format?

I have developed 1-REST web services with help of Spring-Boot technology.
Now, while i am going to requesting any thing it isn't responding me into JSON format ? in stead of it it's responding into plain "String" format.
Also, note i have used annotation #RestController at Controller class level.
Some how i am thinking some configuration i am missing. is it so ?
My current Maven Configuration is ,
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.6.RELEASE</version>
</parent>
Also, i have noticed that while i am requesting(POST) for getting List then in such case it's returns an array of JSON object.
Can anyone guide me what's wrong with me ?
if i understand you right, you want to produce a JSON object in response ?
you have an option in your #RequestMapping that produces a specific format of response.
#RequestMapping(value = "/list", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
Also you can use a specific format of response to add your object to return, and type of response with ResponseEntity<?>
something similar to this:
public ResponseEntity<?> getAll() {
List<Category> categories = categoryDAO.getAll();
if (!categories.isEmpty()) {
return new ResponseEntity<>(categories, HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
EDIT
i add the annotations for #PostMapping it's similar to #RequestMapping
#PostMapping(value = "/list", produces = "application/json; charset=UTF-8")
or also is valid:
#PostMapping(value = "/list", produces = MediaType.APPLICATION_JSON_VALUE)
i'll leave you a link so you can see what properties had #PostMapping
#PostMapping

Resources