I have a method which is taking #modelattribute as the parameter and is returning model and view object as shown below
#RequestMapping(value = "/pathtorequest", method = RequestMethod.POST)
public ModelAndView redirectdemo( HttpServletRequest req,#ModelAttribute(value="demo") Employee e) {
ModelAndView m=new ModelAndView("result");
Map<String,Object> map=m.getModel();
for(String s:map.keySet()){
System.out.println("key::"+s+" value::"+map.get(s));
}
return m;
}
foreach loop is not printing anything whereas an object is added to model with name=demo.
in the view page which is result i am getting the value of modelattribute in requestScope.
Why the object demo is not added to model map? isnt the demo a model object?
Because, although the Employee object is added by the #ModelAttribute annotated parameter, you then create a brand new ModelAndView with the line
ModelAndView m=new ModelAndView("result");
Then you iterate over m which contains only a view name (i.e. "result") but no model.
When you return a modelAndView, Spring will add to it all the other model attributes created by #ModelAttribute annotations.
If you want to manilpulate the model in your method, add it as a parameter:
#RequestMapping(value = "/pathtorequest", method = RequestMethod.POST)
public ModelAndView redirectdemo( HttpServletRequest req,#ModelAttribute(value="demo") Employee e, ModelMap modelMap) {
for(String s : modelMap.keySet()){
System.out.println("key::"+s+" value::"+modelMap.get(s));
}
}
Related
What are the main differences between the following Spring Framework classes?
Model
ModelMap
ModelAndView
Using Model.put(String,Object) we can access the values in .jsp files, but ModelMap.addAttribute(String,Object) also did same thing. I do not understand the difference between these classes.
Model is an interface while ModelMap is a class.
ModelAndView is just a container for both a ModelMap and a view object. It allows a controller to return both as a single value.
Differences between Model, ModelMap, and ModelAndView
Model: It is an Interface. It defines a holder for model attributes and primarily designed for adding attributes to the model.
Example:
#RequestMapping(method = RequestMethod.GET)
public String printHello(Model model) {
model.addAttribute("message", "Hello World!!");
return "hello";
}
ModelMap: Implementation of Map for use when building model data for use with UI tools.Supports chained calls and generation of model attribute names.
Example:
#RequestMapping("/helloworld")
public String hello(ModelMap map) {
String helloWorldMessage = "Hello world!";
String welcomeMessage = "Welcome!";
map.addAttribute("helloMessage", helloWorldMessage);
map.addAttribute("welcomeMessage", welcomeMessage);
return "hello";
}
ModelAndView: This class merely holds both to make it possible for a controller to return both model and view in a single return value.
Example:
#RequestMapping("/welcome")
public ModelAndView helloWorld() {
String message = "Hello World!";
return new ModelAndView("welcome", "message", message);
}
Model: is an interface it contains four addAttribute and one merAttribute method.
ModelMap: implements Map interface. It also contains Map method.
ModelAndView: As Bart explain it allows a controller return both as a single value.
I'm trying to achieve a loop of the following steps before save is called.
Show list
add to list
It works adding one item. On the second item added spring has lost the reference to the ModelAttribute which contained an item already and tries to reconstruct it from the form data, which it must not because it contains polymorphic types.
How do I preserve the updated model throughout every add?
Sample
#RequestMapping(value = "/foo", method = RequestMethod.GET)
public String show(#ModelAttribute("foos") ArrayList<Foo> foo, Map model) {
model.put("foo", foo);
return "foo.jsp";
}
#RequestMapping(value = "/addFoo", method = RequestMethod.POST)
public String add(#ModelAttribute("foos") ArrayList<Foo> foo,
RedirectAttributes redirectAttributes) {
foo.add(new FooImpl());
redirectAttributes.addFlashAttribute("foos", foo);
return "redirect:foo";
}
How can I do this without using SessionAttributes?
At the moment I just want to test redirecting from the update method back to the sox method. But instead I get an error complaining about a missing "update.jsp".
#RequestMapping(value = "/sox/update", method = RequestMethod.POST)
#ModelAttribute("formWrapper")
public final String update(HttpServletRequest request,
#ModelAttribute("formWrapper") FormWrapper formWrapper,
BindingResult bindResult,
ModelMap model)
{
return "redirect:/sox";
}
#ModelAttribute("formWrapper")
FormWrapper setupForm()
{
FormWrapper formWrapper = new FormWrapper();
return formWrapper;
}
#RequestMapping(value = "/sox", method = RequestMethod.GET)
public final String sox(HttpServletRequest request, ModelMap model)
{
return "sox";
}
I think your problem is the #ModelAttribute on the update method. Try it this way :
#RequestMapping(value = "/sox/update", method = RequestMethod.POST)
public final String update(HttpServletRequest request,
#ModelAttribute("formWrapper") FormWrapper formWrapper,
BindingResult bindResult,
ModelMap model)
{
return "redirect:/sox";
}
When you add the #ModelAttribute to a method spring treats the return as a model attribute :
Any other return type is considered to
be a single model attribute to be
exposed to the view, using the
attribute name specified through
#ModelAttribute at the method level
(or the default attribute name based
on the return type class name). The
model is implicitly enriched with
command objects and the results of
#ModelAttribute annotated reference
data accessor methods.
Look at 15.3.2.8 of the Spring Docs for more info: (http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-modelattrib)
#RequestMapping(value = "/index", method = RequestMethod.GET)
public final String index(final ModelMap model)
{
List myModels = ArrayList<MyModel>(getMyModels());
model.addAttribute("mymodel", myModels);
return "index";
}
In Spring I put the myModels list into the ModelMap to be passed to the "index" view. How do I then access those MyModel objects from the JSTL code?
Is it necessary for this controller method to be final and for the ModelMap parameter to be final?
By name, e.g <c:out value="${mymodel}"/>. Every model attribute you add to the ModelMap is made available as a JSP request-scoped attribute.
"no" and "no", final is irrelevant here - did someone tell you otherwise?
I'm using the following action on a SpringMvc application:
#RequestMapping(value = "/test", method = RequestMethod.GET)
public ModelAndView test(
#ModelAttribute List<Group> groups
) {
//return whatever
}
My Group class has an 'id' and a 'name' property. Default getter/setter.
How should i call this action in order to have this list correctly instanciated?
I tried something like:
/test?groups.id=2&groups.name=stackrocks&groups.id=3&groups.name=stackrules
Didn't work.
Also tried:
/test?groups[].id=2&groups[].name=stackrocks&groups[].id=3&groups[].name=stackrules
No success.
So, how to bind a list when using SpringMvc?
You can't bind parameters of method with the exactly that signature. #ModelAttribute binds attributes to the fields of the corresponding model object, so you can encapsulate your List into object:
public class Groups {
private List<Group> list = new AutoPopulatingList<Group>(Group.class);
...
}
#RequestMapping(value = "/test", method = RequestMethod.GET)
public ModelAndView test(
#ModelAttribute Groups groups
) {
//return whatever
}
and then call it as follows:
/test?list[0].id=2&list[0].name=stackrocks&list[1].id=3&list[1].name=stackrules