Reputation: 11974
I need to submit a JS-formed Array of Objects to a Spring MVC Controller. All the property names match.
@PostMapping("/addAdmin")
public void addAdmin(@RequestParam List<UserRolesGUIBean> userRolesGUIBeans)
{
// ...
}
JS:
var entries = [];
//...
// entries is an array of objects of the form {id: "..", role: ".."}
// verified to be correct before submission
$.ajax({
type : "post",
dataType : "json",
url : 'addAdmin',
data : JSON.stringify(entries)
})
Bean
public class UserRolesGUIBean implements Serializable {
private String id;
private String role;
// + Constructors (Empty + Full), Getters and setters
}
Error:
Required List parameter 'userRolesGUIBeans' is not present]
Also tried this with ModelAttribute
and an ArrayList
,
PostMapping("/addAdmin")
public void addAdmin(@ModelAttribute ArrayList<UserRolesGUIBean> userRolesGUIBeans) {
Now there are no errors, but the list is empty, no data was received.
Tried everything -- arrays vs. lists, JSON.stringify(data)
or a data object with data {"entries" : entries}
, RequestBody
doesn't work and gives UTF Errors; and RequestParam
as above doesn't work either.
This is way too complicated for a simple task.
Upvotes: 2
Views: 7557
Reputation: 9266
As promised, please go to https://start.spring.io/ and create a new project with a single depdendency for spring-boot-starter-web
.
After that, you can create the following bean in your project.
import java.util.List;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
@PostMapping("/request-body")
public void getRequestBody(@RequestBody List<Person> list) {
for (Person person : list) {
System.out.println(person.name);
}
}
public static class Person {
private String name;
private String phoneNo;
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the phoneNo
*/
public String getPhoneNo() {
return phoneNo;
}
/**
* @param phoneNo the phoneNo to set
*/
public void setPhoneNo(String phoneNo) {
this.phoneNo = phoneNo;
}
}
}
Nothing special, just take in a list of Person
and print out the names. You can right click and run the project directly from the IDE.
You can open Postman and make a POST request as following.
This is what gets printed in the console.
If it works with Postman, you can make it work in JS. You just haven't figured out how. Instead of settling with that "workaround" you found, I think you should find out the proper way to submit a request in JS. In addition, some understanding of the Spring framework would help too. Otherwise, you will just keep randomly trying stuff like @ModelAttribute
without getting anywhere.
Upvotes: 2
Reputation: 11974
SOLUTION:
1) In theory, if I was doing Form Submission (like $('#myForm').submit()
), I could use @ModelAttribute
to automatically bind my form to the bean. That's what @ModelAttribute
does -- it's used for Form Submission. I don't have a real form; only my own custom values.
I could still "fake" a Form Submit by creating a Dynamic Form "on the fly," but I couldn't get the Arrayed-Field Form Submission (e.. obj[]
with []
notation in the HTML Name) to map to a @ModelAttribute List<Bean>
, so I disregarded this unusual Form Submit approach.
2) The real approach that worked is to just submit a custom JSON string which is my own. Not related to any form submission, so can't use @ModelAttribute
. Instead, this is the @RequestBody
approach. Then I have to parse the JSON RequestBody String myself -- and here we have to use Jackson, Java JSON, or GSON to parse the JSON Array.
In my case,
JS:
$.ajax({
type : "post",
dataType : 'json',
url : 'addAdmin',
data : JSON.stringify(entries)
})
Controller (note it takes a custom String only). Then it uses Jackson to parse the string manually, because Spring won't do it in this case. (Spring will only auto-parse if you're using @ModelAttribute
form binding.)
@PostMapping("/addAdmin")
public boolean addAdmin(@RequestBody String json) throws Exception {
String decodedJson = java.net.URLDecoder.decode(json, "UTF-8");
ObjectMapper jacksonObjectMapper = new ObjectMapper(); // This is Jackson
List<UserRolesGUIBean> userRolesGUIBeans = jacksonObjectMapper.readValue(
decodedJson, new TypeReference<List<UserRolesGUIBean>>(){});
// Now I have my list of beans populated.
}
Upvotes: 2
Reputation: 6944
You are trying to send a JSON object by using a post. You should use @RequestBody
annotation.
Try to change your method in this way:
@PostMapping("/addAdmin")
public void addAdmin(@RequestBody List<UserRolesGUIBean> userRolesGUIBeans)
{
// ...
}
In this way Spring will intercept the Json and transform it in List of wished objects
Upvotes: 2