How to pass Array of Objects as parameter in Java swagger UI? - java

I need to pass an array of objects as parameter in java Swagger UI. I am unable to do it. However I can easily pass array of string as parameters. But cant figure out how to pass array of objects nested inside another class or DTO. I am using Java Spring and developing RESTful webservice.
Below is my 1st DTO that is passed as ModelAttribute in my REST api as parameter:
public class BusinessDetailsDTO {
private BusinessMembersDTO[] businessMembers;
public BusinessMembersDTO[] getBusinessMembers() {
return businessMembers;
}
public void setBusinessMembers(BusinessMembersDTO[] businessMembers) {
this.businessMembers = businessMembers;
}
}
Below is 2nd DTO whose array is made property in 1st DTO:
public class BusinessMembersDTO {
private String ownerRole;
private String businessLocation;
private Long memberId;
//getter setter below
}
Below is the controller method definition:
#ApiOperation(value = "Add business info")
#RequestMapping(method = RequestMethod.POST, value = "/addBusinessInfo", produces={"application/json"})
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Success", response = ResponseEntity.class),
#ApiResponse(code = 401, message = "Unauthorized"),
#ApiResponse(code = 403, message = "Forbidden"),
#ApiResponse(code = 404, message = "Not Found"),
#ApiResponse(code = 500, message = "Failure") })
public ResponseEntity<BusinessDetails> addBusinessInfo(#RequestParam(
#ModelAttribute BusinessDetailsDTO businessDetailsDTO) {
My problem is, I am unable to figure out how should I pass values ownerRole which is present in BusinessMembersDTO.
The swagger UI shows Array[] in DataType column next to businessMembers members field.
Plz help.

Try to put BusinessDetailsDTO directly as response in ApiResponse as below
#ApiResponse(code = 200, message = "Success", response = BusinessDetailsDTO.class)

Related

How to map path params to gRPC object in spring based REST API?

My REST API must work with gRPC objects as input parameters.
The most simple example is:
GET http://localhost:8083/api/books?page.number=1&page.size=30
where the proto definition is:
message PagedMessage {
Page page = 1;
}
message Page {
int32 number = 1;
int32 size = 2;
}
The controller is:
#RequestMapping(value = "/api/books")
public class ObjectOps {
#Autowired
private BooksService booksService;
#GetMapping(value = "/")
#ResponseBody
BooksList listBooks(#RequestParam PagedMessage request) {
return booksService.getBooks(request);
}
}
And in the application I have this bean:
#Bean
ProtobufJsonFormatHttpMessageConverter protobufJsonFormatHttpMessageConverter() {
return new ProtobufJsonFormatHttpMessageConverter();
}
The only way it worked for me is to pass the paging information as GET body:
{
"page" : {
"number": 1,
"size": 30
}
}
but it will be great to have the list books method object be populated from the request path parameters.
I think you can just remove the #RequestParam annotation and Spring will populate the object.
Referenced by this answer: https://stackoverflow.com/a/16942352/8075423

Can we use swagger annotation values in our java code

I am new to java. Trying to develop a application to schedule http api calls in a cron job. Only the method name will be the input. All the apis are configured with swagger annotations. Can I use these annotations to determine whether the api is post or get or delete etc. For example
public class ABC {
#ApiOperation(
httpMethod = "GET",
value = "value",
notes = "notes",
response = ABC.class)
ABC getValue()
{
}
}
only getValue is the input to my application. Can I get the #ApiOperation values to determine the http method type.
You can, but it is in the RequestMapping annotation (the one where you specify which URL should be linked to the method):
For example, this method will be called when someone navigates to myBaseURl/persons in GET. It will return JSON.
#ApiOperation( value = "List of persons",
notes = "List all my base's persons. ",
response = Person.class,
responseContainer = "List",
tags = { "Persons", })
#RequestMapping(value = "/persons",
produces = { "application/json" },
method = RequestMethod.GET)
public PagedResources<PersonResource> persons(...) {}

How to Swagger Annotate a Spring GET #RequestMapping having a complex Object

The issue is that I have a complex Object as Request Param for a GET-Request and after I place the Swagger Annotations inside the Object. The Swagger UI shows that the entry param is a body in which i have to place the Params.
body: {
"modelId": 0,
"makeId": 0
}
My REST controller looks like this
#RequestMapping(method = RequestMethod.GET, value = "/model")
public SearchModelsResponse searchModels(
#ApiParam(value = "Search for something",
required = true) final ModelSearch search) {...}
And the Request object
public class ModelSearch {
#ApiParam(value = "Something important)", required = true)
private Long modelId;
#ApiParam(value = "Something else important)", required = false)
#Nullable
private Long makeId;
....
}
Is there a Way to Annotate it correctly so Swagger shows it as correctly as Request Parameters and not as a body construct ?
OK the solution in this kind of scenario is to manually define the Parameters, this is possible with the #ApiImplicitParam annotation.
So as result this looks like this.
#ApiImplicitParams({
#ApiImplicitParam(name = "modelId", value = "this is modelId", required = true, dataType = "string", paramType = "query"),
#ApiImplicitParam(name = "makeId", value = "this is makeId", required = true, dataType = "string", paramType = "query")
})
#RequestMapping(method = RequestMethod.GET, value = "/model")
public SearchModelsResponse searchModels(
final ModelSearch search) {...}
It's not a beautifull solution since I actually want swagger to interprete my code but the result gives the option to show it as request parameters not as a body construct.

neither #RequestBody nor #RequestParam work

I want to make a PUT call in spring.
this is my controller code:
#RequestMapping(value = "/magic", method = RequestMethod.PUT)
TodoDTO magic(#RequestBody String id){
return service.magic(id);
}
because i want to pass a id string in the call.
the problem is, i receive this
{
"timestamp": 1486644310464,
"status": 500,
"error": "Internal Server Error",
"exception": "java.lang.NullPointerException",
"message": "{\n\t\"id\":\"589c5e322abb5f28631ef2cc\"\n}",
"path": "/api/todo/magic"
}
if i change the code like this:
#RequestMapping(value = "/magic", method = RequestMethod.PUT)
TodoDTO magic(#RequestParam(value = "id") String id){
return service.magic(id);
}
i receive
{
"timestamp": 1486644539977,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.bind.MissingServletRequestParameterException",
"message": "Required String parameter 'id' is not present",
"path": "/api/todo/magic"
}
i make the same call, a PUT at link http://localhost:8080/api/todo/magic
with the body
{
"id":"589c5e322abb5f28631ef2cc"
}
which is the id of one object in my db.
my question is, how can i achieve my goal? if i pass the param in the link, like api/todo/magic/589c5e322abb5f28631ef2cc, with #PathVariable, it works
Create your own custom class like below
Class Request
{
private String id;
//getter and setter
}
And change method to
#RequestMapping(value = "/magic", method = RequestMethod.PUT)
TodoDTO magic(#RequestBody Request request){
return service.magic(request.getId());
}
You can take id in url also and use #Pathvariable in method signature
#RequestMapping(value = "/magic/{id}", method = RequestMethod.PUT)
TodoDTO magic(#PathVariable String id){
return service.magic(request.getId());
}
When you're using #RequestBody String id it expects just a string:
"589c5e322abb5f28631ef2cc"
If you want to send an object with id field like
{
"id":"589c5e322abb5f28631ef2cc"
}
you should create a class with id field and modify method's signature to get this class instead of String.
While creating a wrapper class as suggested in the other answers will work, I think it may be possible to avoid this overhead and simply use a Map.
#RequestMapping(value = "/magic", method = RequestMethod.PUT)
TodoDTO magic(#RequestBody Map<String, String> data){
return service.magic(data.get("id");
}

Pass multiple parameters to rest API - Spring

I am trying to figure out if it is possible to pass a JSON object to rest API, Or pass a multiple parameters to that API ? And how to read these parameters in Spring ? Lets assume that the url looks like the below examples :
Ex.1 http://localhost:8080/api/v1/mno/objectKey?id=1&name=saif
Is it valid to pass a JSON object like in the url below ?
Ex.2 http://localhost:8080/api/v1/mno/objectKey/{"id":1, "name":"Saif"}
Questions:
1) Is it possible to pass a JSON object to the url like in Ex.2?
2) How can we pass and parse the parameters in Ex.1?
I tried to write some methods to achieve my goal, but could not find the right solution?
I tried to pass JSON object as #RequestParam
http://localhost:8080/api/v1/mno/objectKey?id=1 There was an unexpected error (type=Unsupported Media Type, status=415). Content type 'null' not supported
http://localhost:8080/api/v1/mno/objectKey/id=1 There was an unexpected error (type=Not Found, status=404). No message available
http://localhost:8080/api/v1/mno/objectKey/%7B%22id%22:1%7D There was an unexpected error (type=Not Found, status=404). No message available
#RequestMapping(value="mno/{objectKey}",
method = RequestMethod.GET,
consumes="application/json")
public List<Book> getBook4(#RequestParam ObjectKey objectKey) {
...
}
I tried to pass the JSON object as #PathVariable
#RequestMapping(value="ghi/{objectKey}",method = RequestMethod.GET)
public List<Book> getBook2(#PathVariable ObjectKey objectKey) {
...
}
I created this object to hold the id parameter and other parameters like name , etc ....
class ObjectKey{
long id;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
(1) Is it possible to pass a JSON object to the url like in Ex.2?
No, because http://localhost:8080/api/v1/mno/objectKey/{"id":1, "name":"Saif"} is not a valid URL.
If you want to do it the RESTful way, use http://localhost:8080/api/v1/mno/objectKey/1/Saif, and defined your method like this:
#RequestMapping(path = "/mno/objectKey/{id}/{name}", method = RequestMethod.GET)
public Book getBook(#PathVariable int id, #PathVariable String name) {
// code here
}
(2) How can we pass and parse the parameters in Ex.1?
Just add two request parameters, and give the correct path.
#RequestMapping(path = "/mno/objectKey", method = RequestMethod.GET)
public Book getBook(#RequestParam int id, #RequestParam String name) {
// code here
}
UPDATE (from comment)
What if we have a complicated parameter structure ?
"A": [ {
"B": 37181,
"timestamp": 1160100436,
"categories": [ {
"categoryID": 2653,
"timestamp": 1158555774
}, {
"categoryID": 4453,
"timestamp": 1158555774
} ]
} ]
Send that as a POST with the JSON data in the request body, not in the URL, and specify a content type of application/json.
#RequestMapping(path = "/mno/objectKey", method = RequestMethod.POST, consumes = "application/json")
public Book getBook(#RequestBody ObjectKey objectKey) {
// code here
}
you can pass multiple params in url like
http://localhost:2000/custom?brand=dell&limit=20&price=20000&sort=asc
and in order to get this query fields , you can use map like
#RequestMapping(method = RequestMethod.GET, value = "/custom")
public String controllerMethod(#RequestParam Map<String, String> customQuery) {
System.out.println("customQuery = brand " + customQuery.containsKey("brand"));
System.out.println("customQuery = limit " + customQuery.containsKey("limit"));
System.out.println("customQuery = price " + customQuery.containsKey("price"));
System.out.println("customQuery = other " + customQuery.containsKey("other"));
System.out.println("customQuery = sort " + customQuery.containsKey("sort"));
return customQuery.toString();
}
Multiple parameters can be given like below,
#RequestMapping(value = "/mno/{objectKey}", method = RequestMethod.GET, produces = "application/json")
public List<String> getBook(HttpServletRequest httpServletRequest, #PathVariable(name = "objectKey") String objectKey
, #RequestParam(value = "id", defaultValue = "false")String id,#RequestParam(value = "name", defaultValue = "false") String name) throws Exception {
//logic
}
Yes its possible to pass JSON object in URL
queryString = "{\"left\":\"" + params.get("left") + "}";
httpRestTemplate.exchange(
Endpoint + "/A/B?query={queryString}",
HttpMethod.GET, entity, z.class, queryString);

Categories

Resources