How do I pass a list of lists as #RequestParam? - java

Desired request:
http://localhost:8080/values?input=[["aaa","bbb","ccc","ddd"],["abcd","abcd","abcd","abcd"]]
I would love to be able to pass the URL in some way using brackets.
However if it is not possible, how do I still pass the list of lists ?
My controller path:
#GetMapping(path = "/values/")
public String getValues(#RequestParam List<List<#Size(min=4, max=4)String>> input) {
return input.get(0).get(2);
}
which should return ccc.

This is not a good way to do this job. Instead you can pass them as request parameter and and receive them from hashMap. But since you are passing list of lists, so it would be convenient to pass them in request body. To do that you have to create a request POJO class following these steps:
public class ListRequest{
private List<List<String>> inputList;
//generate getter, setter for it
}
Now, change in your controller, replace GET method with POST:
#PostMapping(path = "/values/")
public String getValues(#RequestBody ListRequest input) {
List<List<String>> yourData=input;
System.out.println(yourData);
//operate on your data as you wish
return input.get(0).get(2);
}

Create a Pojo class with a list of list as field.
Send the values in the request body and use a post method.
In the controller method, use this Pojo object to retrieve those values.

Related

I am using Postman, to pass the data to a REST api but my variable is showing null value

My main question is how to pass a (Map, String) to a REST API, I know if I use #RequestBody all the passed contents are stored to map but what can be done to pass map as well as any other parameters REST API.
#GetMapping(path="/invoices")
public String invoiceReceived( Map<String,Object> invoice,String format) throws MessagingException {
System.out.println(format); // this prints NULL
return "returnValue";
}
So I tried using PathVariable but they throw exception. What can be done?
#GetMapping(path="/invoices/{invoiceData}/{format}")
public String invoiceReceived(#PathVariable("invoiceData") Map<String,Object> invoice,
#PathVariable("format") String format) throws MessagingException {
System.out.println(format); // this prints NULL
return "returnValue";
}
What should I do to accept a map and a variable as input? And what should be the JSON file look like which should be given as input?
{
"invoiceData":[{"invoiceId":"23642",
"clientName":"Client",
"amount":"23742.67",
"email":"client#abc.com"
}],
"format":"html"
}
This question was identified similar to another question, So I am trying to explain how is this different, I know that I can use #RequestBody to get all the variables in the map, but The call will be made with two parameters some of which will be stored in map but one parameter will be used for another variable. So how can I send a map along with any other variable?
I think you can use query strings and path variables.
If you declare a controller's method like:
#GetMapping(path="/invoices")
public String invoiceReceived(#RequestBody Map<String,Object> invoice, #RequestParam String format) {
...
}
the url to which the request is send and the JSON request body will be something like below.
The url:
http://localhost:8080/invoices?format=html
The JSON request body:
{
"invoiceId":"23642",
"clientName":"Client",
"amount":"23742.67",
"email":"client#abc.com"
}
Also you can use a path variable like:
http://localhost:8080/invoices/html
#GetMapping(path="/invoices/{format}“)
public String invoiceReceived(#RequestBody Map<String,Object> invoice, #PathVariable String format) {
...
}

How to POST a List as Body in Retrofit 2.6

Already searched a lot but couldn't find an appropriate answer. I have the following JSON. I understand this is a List object. How do I send a POST request as #Body in retrofit 2? Also, what is the POJO that I need to have to get a successful response from the API.
Please note that I have looked into all JSONObject based solutions. I am looking only for POJO based solutions where List/fields are sent as constructors.
{
"ring":[
{
"ring_pitch_id":"xxxx-xxxx-xxxx-xxxx",
"ring_match_id":"xxxx-xxxx-xxxx-xxxx",
"name":"xxxx",
"type":"xxxx",
"status":"xxxx"
}
]
}
Here is your pojo.
This is body:
public class RingBody {
List<RingModel> ring = new ArrayList<RingModel>();
}
This is items of list of your body.
public class RingModel {
#SerializedName("ring_pitch_id")
String ringPitchId;
#SerializedName("ring_match_id")
String ringMatchId;
String name;
String type;
String status;
}
The way I resolved this is by creating two model classes, ringList and ring. Similar to Ionut's answer, the ringList class contained List with setter. The ring model class contained all the 5 fields with getters and setters. In the calling method had the code that created object of ring class passing all 5 parameters and creating a list of it by writing List<ring> temp = new ArrayList<>();. temp.add(object_of_ring);. Creating object of ringList class and passing ring either as constructer or setter worked.

Is there a way to recieve an object or a list in the same param of a REST call?

In java, you can add 3 dots in a function to say this can receive one, or more objects and I'm trying to implement this on a rest call
#PutMapping(value = FIELD_SAVE_URI)
#Secured(CdsPermissionDefinition.CDS_MODIFY)
public ResponseEntity<DefaultFieldDto> saveField(#RequestBody #NotNull DefaultFieldDto... fields){
//TODO impl
return ResponseEntity.ok(new DefaultFieldDto());
}
Now, if I don't send list [] the server is giving me an error, but I want the option to receive an object {} or a list [] in the same param
void test(){
a();
a(new DefaultFieldDto());
a(new DefaultFieldDto(), new DefaultFieldDto(), new DefaultFieldDto());
}
private void a(DefaultFieldDto... fields){
//Do something
}
This is basically what I want to implement from a REST service perspective
That is basically a bad design you are going for. As per REST standards PUT should accept only a JSON not a List.
But If you insist on List, you should support only List in the Request body. And for case of sending a object {}, send it as Array of one object [{}].

sending javascript object arrays as parameters to controller

Question is pretty self explanatory. I want to send 2 different arrays of objects through a POST form without ajax to my controller.
I changed my question to using ajax and using a get request due to the size of the params. Currently getting a 400 (Bad Request). I have no idea why. Please take a look...
I have objects:
var phone = {phoneId:"", phoneNumber:"", phoneType:""};
var schedule = {scheduleId:"", time:"", day:""};
Which I place into a javascript arrays:
var phones = [phone1, phone2, phone3];
var schedules = [schedule1, schedule2];
and I use ajax to send:
var data = {
index: id,
schedules: schedules,
phones: phones
}
var url = "/myController/myUrl"
$.getJSON(url, data, function(result){
if(result.ok){
$('#messageAlertSuccess').show();
} else {
$('#messageAlertError').show();
}
});
I created wrapping classes to map them like so:
public class PhoneWrapper(){
private String phoneId;
private String phoneNumber;
private String phoneType;
}
And of course the scheduleWrapper follows the same convention.
Here's the method in my controller:
#ResponseBody
#RequestMapping(value="/myUrl", method=RequestMethod.GET)
public Result doSomething(#RequestParam("index") int index,
#RequestParam("phones") Set<PhoneWrapper> phoneWrappers,
#RequestParam("schedules") Set<ScheduleWrapper> scheduleWrappers,
Model model,
HttpSession session){
//do stuff here.
}
I am currently getting a 400. So what's wrong?
Update: here's the url that the .getJSON jquery method is building:
http://localhost:8080/myApp/myController/myUrl?index=9&schedules%5B0%5D%5BscheduleId%5D=1&schedules%5B0%5D%5BfromDay%5D=Monday&schedules%5B0%5D%5BtoDay%5D=Friday&schedules%5B0%5D%5BfromTime%5D=08%3A30%3A00&schedules%5B0%5D%5BtoTime%5D=16%3A00%3A00&schedules%5B1%5D%5BscheduleId%5D=5&schedules%5B1%5D%5BfromDay%5D=Saturday&schedules%5B1%5D%5BtoDay%5D=Monday&schedules%5B1%5D%5BfromTime%5D=09%3A00%3A00&schedules%5B1%5D%5BtoTime%5D=13%3A00%3A00&phones%5B0%5D%5BphoneId%5D=6&phones%5B0%5D%5BphoneNumber%5D=787-788-1111&phones%5B0%5D%5BphoneType%5D=PHONE&phones%5B1%5D%5BphoneId%5D=106&phones%5B1%5D%5BphoneNumber%5D=787-795-4095&phones%5B1%5D%5BphoneType%5D=FAX
I see a few things that don't look right
unless you have getters and setters in your wrappers (DTO is a better name), i don't use them for my DTOs for xhr calls, you need to change
public class PhoneWrapper(){
private String phoneId;
private String phoneNumber;
private String phoneType;
}
to have public fields vs private
public class PhoneWrapper(){
public String phoneId;
public String phoneNumber;
public String phoneType;
}
Your js arrays are not arrays but objects;
var phones = {phone1, phone2, phone3};
var schedules = {schedule1, schedule2};
Here they are as arrays
var phones = [phone1, phone2, phone3];
var schedules = [schedule1, schedule2];
Make sure you naming is the same of both the js and java sides. I find it very helpful to turn on the debugging when troubleshooting these problems. log4j -
<logger name="org.springframework.web.servlet.mvc" >
<level value="debug" />
</logger>
EDIT
So after the question was updated with more info I notice that it was the same problem as Binding a list in #RequestParam
I would say that you are almost there! The first thing the you need is a wrapper to hold the two Set<> parameters since spring is not able to map a collection directly to parameters (yet?).
Also, there are two ways to handle this kind of requests:
use a json request and #Requestbody with a single javascript object in the request body an map this into a java class (automatically by spring). This means you need to change a little how the data is send down and this approach has one side effect: you cannot merge data simply by defining the parameter as a model attribute.
a second possibility is to stay with the post form submit. Also here you need to create the wrapper and use this one as a requestparam. Either one per Set<> parameter like #Sotirios mentioned in his answer or one parameter which holds both sets. Then you need to modify your submit data to send the phone and schedule information like input fields. I haven't used sets in this case but
lists and the parameter names would look like phoneWrapper[0].phoneId.
The advantage of the second approach is that you can merge the request data with existing values so you do not need to send down a complete phone information all the time.
var phones = {phone1, phone2, phone3};
var schedules = {schedule1, schedule2};
These two are not arrays (square brackets), but objects (curly brackets).
Compare with
var phones = ["phone1", "phone2", "phone3"];
var schedules = ["schedule1", "schedule2"];
and if you are to pass actual object references (phone1, phone2, phone3, schedule1 and schedule2 are object variables) then you need to use
var phones = [phone1, phone2, phone3];
var schedules = [schedule1, schedule2];
For spring the map request parameters to Class instance fields, they have to match the name of the parameter.
So with
<input type="hidden" name="someParameter" value="123"/>
and
public class SomeClass {
private String someParameter;
// getters and setters
}
a Spring controller will be able to be injected with a SomeClass instance whose field someParameter has the value 123 that comes from the html hidden input request parameter. This is also known as a command object.
A javascript array has no meaning to either html or http.
As for the solution, I would keep your class PhoneWrapper, use javascript to populate 3 <input> elements, and change the method definition to
#RequestMapping(value=MY_URL, method=RequestMethod.POST)
public String doSomething(#RequestParam("index") int index,
PhoneWrappers phoneWrappers,
ScheduleWrappers scheduleWrappers,
Model model,
HttpSession session){
Notice there are no more array [] brackets. (You would do the same for ScheduleWrappers).

Playframework renderJSON() array

I'm using renderJSON() method to return an array of objects, with a custom JsonSerializer for the class of each element. The response has the following format:
[{"id":2,"name":"fred"},{...},...]
But I would like to add the name of the array at the begginning:
"arrayname":[{"id":2,"name":"fred"},{...},...]
How can I add the name of the object to a JSON response with renderJSON()? Should I use a template or can I do it with java code?
"arrayname":[{"id":2,"name":"fred"},{...},...]
looks like invalid Json, but if you wrap the array in an object you could get:
{"arrayname":[{"id":2,"name":"fred"},{...},...]}
E.g. something like this:
public class MyArrayWrapper {
public final User[] arrayname;
public MyArrayWrapper(User[] arrayname) {
this.arrayname = arrayname;
}
}
Then you can call renderJSON(new MyArrayWrapper(yourUserArray)); to get JSON like:
{"arrayname":[{"id":2,"name":"fred"},{...},...]}
Or just return as a list Arrays.asList(arr);

Categories

Resources