Pass multiple parameters to rest API - Spring - java

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

Related

How to solve org.springframework.web.bind.MissingServletRequestParameterException in Spring MVC when I sunmit a json string that is larger than 1M?

I use Spring MVC #RequestParam to accept a form.
I am sumbit a form that contains a json string, and when the json string is larger than 1M , It is
{
"timestamp":1556663224346,
"status":400,
"error":"Bad Request",
"exception":"org.springframework.web.bind.MissingServletRequestParameterException",
"message":"Required String parameter 'corpId' is not present",
"path":"/api/test"
}
#RequestMapping(value = "/test", method = RequestMethod.POST, produces = { "application/json;charset=UTF-8" })
#ResponseBody
public String test(
#ApiParam(required = true, value = "json string") #RequestParam(required = true) String content)
I think it is because of the HttpMessageConvert can not convert it or it is has a limit for Json Serializing.
You exceed the default http-header-size(8kb), you could configure your server.max-http-header-size with a suitable number

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 read JSON in GET request query parameter

I have to read JSON values from the URL using a query parameter for GET request.
I am using Tomcat latest in a Spring Boot project.
#RequestMapping(
value = "/values",
method = RequestMethod.GET,
headers = HttpHeaders.ACCEPT + "=" + MediaType.APPLICATION_JSON_VALUE,
produces = "application/json")
public ResponseEntity<String> myMethod(
#RequestParam(value="key") String jsonRequestString) {
//parse JSONString
//--
}
GET request to the URL
Url:- http://localhost:port/values?key={"org":"AA","points":[{"name":"xy","Measures":"343"}]}]
Throws
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
EDIT :- Sending JSON in original form leading me to nowhere, so working approach would be to send the JSON in an encoded form.
You can encode the key parameter to Base64 format and append to the URL, then decode and use it in your controller method.
Key JSON text:
{"org":"AA","points":[{"name":"xy","Measures":"343"}]}]
Base64 encoded text:
eyJvcmciOiJBQSIsInBvaW50cyI6W3sibmFtZSI6Inh5IiwiTWVhc3VyZXMiOiIzNDMifV19XQ==
Decoded to again back to JSON text:
{"org":"AA","points":[{"name":"xy","Measures":"343"}]}]
Few things you should take care of.
Use POST HTTP method to post your JSON to server.
Create a JAVA pojo class which should has a same structure as your JSON. Like for below JSON,
{
"id": 123,
"status": "Ordered",
"product": "Pepsi"
}
i would create a class( You can create a two separate class as you has array inside json) ,
public class Order {
private long id ;
private String status;
private String product ;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
}
Then,
#RequestMapping(value = "/values", method = RequestMethod.POST,produces={"application/json"},
consumes={"application/json"})
public ResponseEntity myMethod(
#RequestBody Order orderObj) {
}
Please take reference from this example and build the solution.
You can directly pass String into the JSONObject constructor
There are lots of libraries available.
1.http://www.java2s.com/Code/Jar/j/Downloadjavajsonjar.htm (JSON jar)
2.http://www.java2s.com/Code/Jar/j/Downloadjsonsimple11jar.htm (Simple JSON)
3.http://www.java2s.com/Code/Jar/g/Downloadgson224sourcesjar.htm (GSON from google)
I personally use JSON and GSON jars.
JSONObject jsonObject = new JSONObject(variable)
You can simply try something like this
#GetMapping(value = "/values", produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<String> testMethod(#RequestParam("key") String key) throws Exception {
JSONObject jsonObject = new JSONObject(key);
//
}

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

#RequestBody is always empty in Spring

The JSONObject is always coming as empty for the method below.
#RequestMapping(value = "/package/{id}", method = RequestMethod.PUT)
#ResponseStatus(HttpStatus.OK)
#ResponseBody
public SPackage updatePackage(#PathVariable String id, #RequestBody JSONObject
sPackage) {
}
and my ajax is like this. I am ways getting the object as empty map on the server side
var jsonObject= {"customerName":$('#customerName').val()}
var jsonData = JSON.stringify(jsonObject);
$.ajax({
type: "PUT",
url: "http://localhost:8081/someproj/package/" + $('#id').val(),
dataType: "json",
data: jsonData,
async: false,
contentType: "application/json; charset=utf-8",
beforeSend : function() {
openModal();
},
success: function(data) {
closeModal();
$('#success').show();
console.log(data);
}
});
I guess spring doesn't know to convert your json to JSONObject, the best thing would be to accept a POJO object which has similar structure to your json,
#RequestMapping(value = "/package/{id}", method = RequestMethod.PUT)
#ResponseStatus(HttpStatus.OK)
#ResponseBody
public SPackage updatePackage(#PathVariable String id, #RequestBody YourJsonPOJO
sPackage) {
}
Are you sure there're no exceptions occurring in your Spring code. When converting from JSON to custom object in Spring, you need to specify a custom class that has same fields & format as the JSON coming in. Otherwise, Spring doesn't know who to convert HTTP POST data into a Java object.
In your case, you could do define a POJO like this:
public class MyRequestObj {
private String customerName;
// add more fields for any other keys from JSON
}
And put this in your Controller class:
#RequestMapping(value = "/package/{id}", method = RequestMethod.PUT)
#ResponseStatus(HttpStatus.OK)
#ResponseBody
public SPackage updatePackage(#PathVariable String id, #RequestBody MyRequestObj
myRequestObj) {
String customerName = myRequestObj.getCustomerName();
}
Of course, if you only want to pass in the customer name as a String to your Controller, then you could also pass it as query string (append ?customerName=someCustomer) and you can retrieve it in Spring as:
#RequestMapping(value = "/package/{id}", method = RequestMethod.PUT)
#ResponseStatus(HttpStatus.OK)
#ResponseBody
public SPackage updatePackage(#PathVariable String id, #RequestParam("customerName") String customerName) {
}
You can use this workaround:
#RequestBody Map<String, String> json
That way you can continue using Jackson HttpMessageConverter and work with custom objects in payload.
You can check extended explanaition why this happens at answer here
#RequestBody gives empty JsonObject when making a POST Request

Categories

Resources