How to customize model in Springfox's Swagger 2 for a string request body? - spring-boot

I would like to customize the model for my API documentation I am making with Springfox's Swagger (Spring REST API).
This is an example for my code:
#ApiOperation("Creating a kafka topic")
#ApiImplicitParams(
#ApiImplicitParam(name = "requestBody", value = "The body of request", required = true,
example = "{\"server\": \"localhost:9092\",\"topic\": \"test\", \"parmas\":{...}}")
)
public ResponseEntity<String> createTopic(#RequestBody String requestBody) {
TopicCreationRequest request = gson.fromJson(requestBody, TopicCreationRequest.class);
...
return ResponseEntity.ok().body(response.toString());
}
Is it possible?

Thanks to Thomas__ I switched POJO and it work

Related

ResponseEntity return type wildcard with swagger generated interface

I want to know the difference between returning ResponseEntity<?> with wildcard VS ResponseEntity<ABC.class> as return type when Swagger generated API interface contains 2 different classes as return types, i.e one for an exception and another for normal flow.
My controller interface is :-
#Operation(summary = "Get user by user name", tags = { "user" })
#ApiResponses(value = {
#ApiResponse(responseCode = "200", description = "successful operation", content = #Content(schema = #Schema(implementation = User.class))),
#ApiResponse(responseCode = "400", description = "Invalid username supplied", content = #Content(schema = #Schema(implementation = Error.class)))
})
#GetMapping(value = "/user/{username}", produces = { "application/xml", "application/json" })
ResponseEntity<?> getUserByName(#PathVariable("username") String username);
the #Schema defines return type.
Can I use ResponseEntity<User> instead of the <?> for the getUserByName method ?
I have the the global exception handler #ControllerAdvice in my application which returns ResponseEntity<Error> .
Answer for your question is simply Yes. Since you are using a Controller Adviser, you can directly define the endpoint return type as User in ResponseEntity
Using a Wildcard(ResponseEntity<?>) as a return type, the symbol ? defines that the return value of the controller method can be any type of ResponseEntity.
Using as ResponseEntity<?> or simply keep it as ResponseEntity<> are considered as raw type of its usage.
But really it is not a good practice to do so. So, you have to declare the exact return type of the controller method in this format ResponseEntity<ABC>.
Let's take this example java of method returning a list of objects(List<Object>).
It is possible on this list to add a Car.class type, a Van.class type. But how ever the consumer of a method should not have to deal with such disruptive questions and we have to define an exact type.
Yes you can use ResponseEntity<User> if your method returns a User type ResponseEntity.
I hope this'll help you to solve the issue :)

Automatically adding #ImplicitParams with specific type of method argument of Spring Controller

Previously, I had Spring controller as below.
#RequestMapping(method = GET)
public List<TheResponse> getResponses(
#RequestParam(defaultValue = "1") int offset,
#RequestParam(defaultValue = "10") int limit) {
Pagination pagination = new Pagination(offset, limit);
...
return someResponse;
}
Swagger was generating document of this method with correct parameters information.
Later I created PaginationArgResolver by implementing HandlerMethodArgumentResolver. After that, I have to update the method as below, and apply #ApiImplicitParams to make it work with Swagger.
#ApiImplicitParams({
#ApiImplicitParam(name = "offset", dataType = "int", defaultValue = "1"),
#ApiImplicitParam(name = "limit", dataType = "int", defaultValue = "10")
})
#RequestMapping(method = GET)
public List<TheResponse> getResponses(#ApiIgnore Pagination pagination) {
...
}
Is there anyway #ImplicitParams is applied automatically whenever Pagination type argument is found?
OR
If I expose #PaginationSupported annotation, can I process it to achieve same results?
I am currently using springfox v2.4.0.
PS. I can edit source of Pagination class, in case some swagger annotation is needed there.
Why adding #ApiIgnore springfox will resolve these attributes inside the class automatically. When you want to add default values and other stuff you can add the #ApiParam annotation to the class attributes as well.
class Pagination {
#ApiParam(defaultValue = "1")
private int offset;
// [..]
}

null string parameter in body of POST request to WebAPI2 service

I have an action defined in a WebAPI2 controller as follows:
[HttpPost]
[Route("DataImport/Product/")]
public DataImportJournalEntry ImportData([FromBody] string base64)
{
return _dataImportService.Import(Convert.FromBase64String(base64));
}
and I'm building a request, using RestSharp, as follows:
var base64 = {4Kb xml file loaded and encoded to base64}
var client = new RestClient(Config.BaseAddress);
var request = new RestRequest("DataImport/Product/", Method.POST);
request.AddParameter("base64", base64, ParameterType.GetOrPost);
request.AddHeader("accepts", "application/json");
var response = client.Execute<DataImportJournalEntry>(request);
The routing is correct as the action is called but the base64 parameter is null on the server side?
Found it..when using the FromBody attribute there can be only one parameter in the body and WebAPI is looking for it as ={value} not as you would expect {key}={value}. So I simply passed the parameter name as an empty string in the test:
...
var request = new RestRequest("DataImport/Product/", Method.POST);
request.AddParameter("", base64);
...
More details here: http://encosia.com/using-jquery-to-post-frombody-parameters-to-web-api/

Spring MVC - Hit to URL with RequestParam failing with 404 Not Found Error

I am using Spring MVC in my project and while mapping user request to a URI, I get the 404 error. Here is my function skeleton which I want to be invoked:
#RequestMapping(value="/inventory/discovery", method = RequestMethod.GET, params = {"discoveryType"}, produces = {"application/json"})
public String getDiscoveryByType(#RequestParam("discoveryType") String discoveryType)
{
return discoveryType;
}
I am expecting this method to be called when I give the URL
http://<some-ip>/inventory/discovery/discoveryType?=DMVPN
However, when I test the code using Chrome's Advanced Rest Client I see that the URI it is trying to access is "/inventory/DMVPN" and not the "/inventory/discovery?discoveryType=DMVPN".
Am I missing something here? I don't see anything wrong with my URL syntax
I have another function in my code (but I don't think it is causing the problem) which has same request-mapping value, but has no params attribute.
#RequestMapping(value = "/inventory/discovery", method = RequestMethod.GET, produces = { "application/json" })
public ResponseEntity<DiscoveryNIOListResult> getAllDiscovery() {
logger.trace("getAllDiscovery");
List<DiscoveryNIO> listDiscoveryNIO = discoveryDasClient.getDiscoveryList();
DiscoveryNIOListResult result = new DiscoveryNIOListResult();
result.setResponse(listDiscoveryNIO);
return new ResponseEntity<DiscoveryNIOListResult>(result, HttpStatus.OK);
}
Ok, so a second look at your URL:
http://<some-ip>/inventory/discovery/discoveryType?=DMVPN
This is NOT passing discoveryType as a request GET parameter. For that you would need to do:
http://<some-ip>/inventory/discovery&discoveryType?=DMVPN
If you want to use path variables instead, you could do something like:
http://<some-ip>/inventory/discovery/DMVPN
And change your handler to something like:
#RequestMapping(value="/inventory/discovery/{discoveryType}", method = RequestMethod.GET, produces = {"application/json"})
public String getDiscoveryByType(#PathVariable("discoveryType") String discoveryType)
{
return discoveryType;
}
It looks like you were trying to mix these two methods, and that wont work.
Try changing your URL to:
http://<some-ip>/inventory/discovery?discoveryType=DMVPN

Spring Restful issue with list of length 1

We are having a json which shows a list of object as below:
skillCheckAnswers: [
{
optionId: 6786,
optionText: "Copy constructor",
optionWeight: "1.00"
},
{
optionId: 6787,
optionText: "Friend constructor",
optionWeight: "2.00"
},
{
optionId: 6788,
optionText: "Default constructor",
optionWeight: "3.00"
},
{
optionId: 6789,
optionText: "Parameterized constructor",
optionWeight: "4.00"
}
]
Which is ok as long as there are more than 1 object in the list. But if the list contains only 1 item then the json displays :
{
optionId: 6785,
optionText: "Friend class",
optionWeight: "4.00"
}
Please note that the second Json is not given as a List but as a single object ( missing square braces[] ).
Is there a way where I can output the list of length 1 with square braces?
Edit--
We can use foreach for the first JSON but foreach starts giving error if the number of object goes to 1. To handle this we are having an if else loop to check if the List is of length 1 or more than 1. If the list is of length then we handle this as a single obkect. This seems to be a stupid solution and I guess there would be an easy way out.
Can anyone tell me if this is even possible?
You should do something like:
From Spring controller:
#RequestMapping(method = RequestMethod.GET, value = "/myquestions")
public #ResponseBody
List<Answer> generateQuestions() {
List<Answer> answers = new ArrayList<Answer>();
Answer ans1 = new Answer();
ans1.setOptionId("6785");
ans1.setOptionText("Friend class");
ans1.setOptionWeight("4.00");
answers.add(ans1);
return answers;
}
The output is as follows:
[
{
"optionId": "6785",
"optionText": "Friend class",
"optionWeight": "4.00"
}
]
So far I understood, you problem is related to JSON converter. I have tested with Spring MappingJacksonHttpMessageConverter message converter. You can see Spring documentation for how to configure the JSON converter. http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch18s02.html
You mentioned you use Spring. Doesn't Spring automatically look after JSON conversions for your the restful API it provides. You can put something like this is your conext file:
You can use org.springframework.http.converter.json.MappingJacksonHttpMessageConverter and set it up in your context file to do the JSON conversion for you.
Then you can use Spring MVC's #ResponseBody annotation to provide a restful service with having to handcode the JSON response.

Resources