How to take LIST input in #RequestParam in Spring MVC? - java

Heyy,
I want to take a list of data in my request param,here "personIdCollection" is a set of list but when i am hitting through postman i am getting a bad request.
Here is my code.
controller
#PostMapping("/face-tag-data")
public String getFaceTaggedData(#RequestParam String projectId,#RequestParam List<String> personIdCollection) {
return null;
}
and here is my ajax
var data = {};
data.personIdCollection = personIdCollection;
data.projectId = $("#projectId").val();
$.ajax({
type:'POST',
url:contextPath+'/face-tag-data',
data:data,
success:function(resp){
console.log(resp);
},
failure:function(resp){
console.log(resp);
}
});

This is working for me. I do not use an ajax-request but instead submit my form directly but it should work either way.
My controller looks like:
#RequestMapping(value="addSingleArticles", method=RequestMethod.POST)
public #ResponseBody String addSingleArticles(
ArticleSubmitData pupilPackageData,
HttpServletRequest request) {
... // do something with the data
}
As you can see I have defined my own composite type which consists of three lists. So you obviously can use it with only one list directly.
public class ArticleSubmitData {
private List<Article> singleArticles;
private List<Article> packageArticle;
private List<Article> popupArticles;
... // getter & setter, inner classes etc.
}
In my server page oder faclet I use the following html-code to make this work
...
<input id="" class="" type="text" name="singleArticles[${line.index}].engraving" />
...
So the trick is to define the variables on your webpage as an array and use this in your controller as a list. As you can see in my example I also use an inner class in my composite class which has extra attributes.

Related

Mapping object which containing a list in request - Spring MVC

Is it possible to wrap an object which contain some String and a List of another object as property from requst in spring mvc?
My classes are :
public class MyObj {
private String ma;
private String mb;
private List<SecObj> mc;
}
and:
public class SecObj {
private String sa;
private String sb;
}
I want to get an object of MyObj from the request.
In my JSP
<form:form action="" method="POST" commandName="myObj" >
<form:input path="ma" />
<form:input path="mb" />
.........
3 or 4 mc
..........
</form:form>
If it is possible then
what should i write int <form:input path="?" /> path?
how i receive it in the request parameter #RequestParam ?
If it not possible at once then
please tell me an good way to wrap this type of one to many relationship from request parameter
Regarding the list, take a look at this issue: Spring MVC : List<E> need to pass as command object . The example shows that you can then fill in each field of SecObj individually, assuming SecObj has a public default constructor.
You could also register a formatter for SecObj to allow Spring to silently convert a whole user input String to SecObj. See http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#format-configuring-formatting-mvc for details.

Pass multiple JSON objects from client to server using jQuery and JAVA

I would like to ask about how to pass the multiple JSON object from Client to Server side. At first, I got the JSON object from 3rd Party API. After that, I want to pass them to Java method on the Server side. This is what I have tried but it is not success
on Client side (JSP)
function getInfo(InkBlob){
var myInkBlob = JSON.stringify(InkBlob);
jQuery.ajax({
type: 'POST',
url: '/webapp/filepicker/importAssets',
dataType: 'json',
data: {"inkBlob": myInkBlob}
});}
jQuery POST the data as
If I don't use JSON.stringify, the result will be like,
This is the method that Response for the incoming data
#RequestMapping(value = "/importAssets", method = RequestMethod.POST)
#ResponseBody
public void importAssets2(String[] inkBlob) throws Exception {
System.out.println(inkBlob); // print as [Ljava.lang.String;#56bdbbec (and another 2 similar)
System.out.println(inkBlob.length); // print as 15}
I want to use the data inside the object. For example, if I want to get the URL of the first object. I want to just inkBlob[0].URL. And the expected length of the inkBlob in this example should be 3 because only 3 object pass to the method. How can I achieve that???
Spring provides way to pass on a complete bean submitted from the form
Try using this :
Here InkBlob is a bean containing variable names and types exactly same as getting passed in post request.
#RequestMapping(value = "/importAssets", method = RequestMethod.POST)
#ResponseBody
public void importAssets2(#ModelAttribute(inkBlob) InkBlob inkBlob) throws Exception {
............Other code
}
Sample code for client
<form:hidden path="fileName" value="xxxx"/>
<input type = "hidden" name = "isWritable" value = "yyyyy"/>
<input type = "hidden" name="mimeType" value="zzzzz"/>
............
</form:form>
And on Server Side Handle it like this :
#RequestMapping(value = "/importAssets", method = RequestMethod.POST) #ResponseBody
public void importAssets2(#ModelAttribute("inkBlob") InkBlob inkBlob) throws Exception {
............Other code }
Where InkBlob should be like this :
public class InkBlob implements Serializable {
private static final long serialVersionUID = 15463435L;
String fileName;
String isWritable;
String mimeType;
......
public void setFileName(String fileName){
this.fileName = fileName;
}
.... Other Getters and settters.
}

Bind Collection to Form - why is it not working?

Could someone please help me find out why my attempt to bind Collection to the form in Spring MVC is not working?
Here is how my object looks like -
public class TestObj {
private Integer testNumber;
private String home;
private String destination;
}
Here is my form object that contains list of above object -
public class TestForm {
private List<TestObj> testList;
//contains getter and setter for testList
}
In my controller, I have implemented formBackingObject method -
public class MyController extends SimpleFormController {
public MyController() {
setCommandClass(TestForm.class);
setCommandName("testForm");
}
protected Object formBackingObject(HttpServletRequest request) throws Exception {
if (isFormSubmission(request)) {
testForm = (TestForm) super.formBackingObject(request);
//THIS ALWAYS RETURNS NULL ON FORM SUBMISSION
List<TestObj> testList = testForm.getTestList();
} else {
//load initial data using hibernate. TestObj is hibernate domain object.
List<TestObj> testList = myService.findTestList();
testForm = new TestForm(testList);
}
return testForm;
}
Here is my JSP snippet -
<form:form commandName="testForm" method="post">
<c:forEach items="${testForm.testList}" var="testvar" varStatus="testRow">
<tr>
<td>
<form:hidden path="testList[${testRow.index}].home" />
<c:out value="${testvar.home}" />
</td>
<td>
<form:input path="testList[${testRow.index}].destination" />
</td>
</tr>
</c:forEach>
<tr><td><input type="submit"></td></tr>
</form:form>
While the first time I load the data shows up fine on the form, when I press submit button the control goes to the formBackingObject method and the isFormSubmission returns true. However, when I get the command object using super.formBackingObject(request), it returns the form object with the testList value as null. I am unable to figure out why this simple case is not working?
I will really appreciate any help in getting this to work.
Are you using Spring 3? If so, you should take a look at this post.
With respect to list processing and object binding, take a look at this post.
Try using the following code. May be that can solve your problem.
private List<TestObj> operationParameterses = LazyList.decorate(new ArrayList<TestObj>(), FactoryUtils.instantiateFactory(TestObj.class));
It won't return you all null list.
Hope that helps you.
Cheers.
I guess my understanding of formBackingObject method must be wrong. I removed that method from the implementation, used referenceData for initial form load and onSubmit to process it on submit. This works fine and does get collection in the form back as expected.
Thanks all for the help though.

How to bind a Set<CustomObject> in spring mvc form

I have a command object associated with a spring form controller:
public class PluginInstance {
private Set<PluginParameter> pluginParameters = new HashSet<PluginParameter>();
... some other string/long properties and getter setters...
}
the PluginParameter also have a Set in it which contain the values
public class PluginParameter {
private String parmName;
private Set<PluginParmvalue> pluginParmvalues = new HashSet<PluginParmvalue>();
...some other string/long properties and getter setters...
}
(Normally the pluginParmvalues will contain only one value, a list have been used for future expandability)
In the spring form I binding the values as
<form:input path="pluginParameters[${itemsRow.index}].pluginParmvalues[0].parmValue" />
but the thing is that there can be a form:select(to present multiple predefined options to the user) or form:input (user can input any value). This has to be decided from another object
public class PluginConfigParm {
private String parmName;
private ArrayList<String> choices;
...getter setters and other properties
}
where I have to compare the name of PluginConfigParm.paramName with PluginParameter.paramName when they match and PluginConfigParm.choices.size() > 0 then form:select will be shown populated with the values from PluginConfigParm.choices otherwise form:input will be shown.
The question is simple: How can I do that.
Any help will be highly appreciated.
By using List<> instead of Set<> in controller. Problem solved. May be Set<> has no getter/setter that can be bind with spring form.
So <form:input path="pluginParameters[${itemsRow.index}].pluginParmvalues[0].parmValue" />
and List<> in controller makes my life easier.
The Set is not an indexed collection so I could not work by using this syntax
pluginParameters[${itemsRow.index}].pluginParmvalues[0].parmValue
eg:
class person{
set name<string> = new HashSet<String>()
}
<input type="hidden" path="person.name" name="person.name" value="<%=valueStr%>"/>
take valueStr = "hello, world"
by giving it as comma seperated values.. set works
Its working for me

Binding a list in #RequestParam

I'm sending some parameters from a form in this way:
myparam[0] : 'myValue1'
myparam[1] : 'myValue2'
myparam[2] : 'myValue3'
otherParam : 'otherValue'
anotherParam : 'anotherValue'
...
I know I can get all the params in the controller method by adding a parameter like
public String controllerMethod(#RequestParam Map<String, String> params){
....
}
I want to bind the parameters myParam[] (not the other ones) to a list or array (anything that keeps the index order), so I've tried with a syntax like:
public String controllerMethod(#RequestParam(value="myParam") List<String> myParams){
....
}
and
public String controllerMethod(#RequestParam(value="myParam") String[] myParams){
....
}
but none of them are binding the myParams. Even when I add a value to the map it is not able to bind the params:
public String controllerMethod(#RequestParam(value="myParam") Map<String, String> params){
....
}
Is there any syntax to bind some params to a list or array without having to create an object as #ModelAttribute with a list attribute in it?
Thanks
Or you could just do it that way:
public String controllerMethod(#RequestParam(value="myParam[]") String[] myParams){
....
}
That works for example for forms like this:
<input type="checkbox" name="myParam[]" value="myVal1" />
<input type="checkbox" name="myParam[]" value="myVal2" />
This is the simplest solution :)
Arrays in #RequestParam are used for binding several parameters of the same name:
myparam=myValue1&myparam=myValue2&myparam=myValue3
If you need to bind #ModelAttribute-style indexed parameters, I guess you need #ModelAttribute anyway.
Subscribing what basil said in a comment to the question itself, if method = RequestMethod.GET you can use #RequestParam List<String> groupVal.
Then calling the service with the list of params is as simple as:
API_URL?groupVal=kkk,ccc,mmm
Just complementing what Donal Fellows said, you can use List with #RequestParam
public String controllerMethod(#RequestParam(value="myParam") List<ObjectToParse> myParam){
....
}
Hope it helps!
One way you could accomplish this (in a hackish way) is to create a wrapper class for the List. Like this:
class ListWrapper {
List<String> myList;
// getters and setters
}
Then your controller method signature would look like this:
public String controllerMethod(ListWrapper wrapper) {
....
}
No need to use the #RequestParam or #ModelAttribute annotation if the collection name you pass in the request matches the collection field name of the wrapper class, in my example your request parameters should look like this:
myList[0] : 'myValue1'
myList[1] : 'myValue2'
myList[2] : 'myValue3'
otherParam : 'otherValue'
anotherParam : 'anotherValue'
It wasn't obvious to me that although you can accept a Collection as a request param, but on the consumer side you still have to pass in the collection items as comma separated values.
For example if the server side api looks like this:
#PostMapping("/post-topics")
public void handleSubscriptions(#RequestParam("topics") Collection<String> topicStrings) {
topicStrings.forEach(topic -> System.out.println(topic));
}
Directly passing in a collection to the RestTemplate as a RequestParam like below will result in data corruption
public void subscribeToTopics() {
List<String> topics = Arrays.asList("first-topic", "second-topic", "third-topic");
RestTemplate restTemplate = new RestTemplate();
restTemplate.postForEntity(
"http://localhost:8088/post-topics?topics={topics}",
null,
ResponseEntity.class,
topics);
}
Instead you can use
public void subscribeToTopics() {
List<String> topicStrings = Arrays.asList("first-topic", "second-topic", "third-topic");
String topics = String.join(",",topicStrings);
RestTemplate restTemplate = new RestTemplate();
restTemplate.postForEntity(
"http://localhost:8088/post-topics?topics={topics}",
null,
ResponseEntity.class,
topics);
}
The complete example can be found here, hope it saves someone the headache :)
Change hidden field value with checkbox toggle like below...
HTML:
<input type='hidden' value='Unchecked' id="deleteAll" name='anyName'>
<input type="checkbox" onclick="toggle(this)"/> Delete All
Script:
function toggle(obj) {`var $input = $(obj);
if ($input.prop('checked')) {
$('#deleteAll').attr( 'value','Checked');
} else {
$('#deleteAll').attr( 'value','Unchecked');
}
}

Categories