Difference between #ModelAttribute and HttpServletRequest Attribute - spring

I use spring mvc and I want to undestand some stuff.
At this code:
#RequestMapping(value="/enregistrerLostCard")
public #ResponseBody
void enregistrerLostCard(#ModelAttribute(value="auth") Auth auth2, HttpServletRequest request) {
Auth auth1 = (Auth) request.getAttribute("auth");
System.out.println(auth2.getLogin()); //print the right value
System.out.println(auth1.getLogin()); //i got nullpointer exception
}
#ModelAttribute(value="auth") and request.getAttribute("auth") isn't the same ?

HttpServletRequest is a Servlet container managed object. Its attribute store holds attributes that are useful in any part of the request handling by the Servlet container.
Model, ModelMap, ModelAndView, etc. are managed by Spring MVC (the DispatcherServlet stack). The attributes inside those are useful to the Spring side of the application.
In some cases, the Model attributes will be inserted into the HttpServletRequest attributes if needed. This typically happens when your handler method returns a String value as a view name. The model attributes will be pushed as HttpServletRequest attributes so that they can be used in the view, for example, in jsps.
Related:
how to pass variables from java to jsp in Spring

Related

Spring Model Attribute Binding Issue with Square Brackets

Spring MVC Version: 4.3.25
Spring Boot: 1.5.22 (Stuck to this due an old webshpere server version :( compatible only with JEE6)
Jackson Data-Bind: 2.10.3
My UI form submits POST request with parameters sent (inspected through browser tools).
Content-Type on Http Request is "application/x-www-form-urlencoded; charset=UTF-8"
changedValues[contacts[0]] 12312312313
changedValues[contacts[1]] 345354535
changedValues[contacts[2]] 35534534
name Sam
My Spring MVC controller goes like this.
Controller Code
#PostMapping("/saveMyPage")
public String saveMyPage(Model model,HttpServletRequest request, HttpServletResponse response,
HttpSession session,#ModelAttribute("myBean") MyBean oBean,BindingResult result){
Map <String,Object> uiChanged = oBean.changedValues;
... Other Code
}
Bean Code
public class MyBean implements Serializable{
private List<String> contacts;
private Map<String,Object> changedValues;
... Getters & Setters
}
On debugging, my Spring MVC controller I am hoping to get the list of only the changed contacts via the "changedValues" Hash Map. This is where the square brackets seem to break -
The key that Spring Binding maps now looks like
contacts[0 12312312313
contacts[1 345354535
contacts[2 35534534
name Sam
This breaks my code as the second square brackets were not understood by Spring Data Binding.
Still exploring if I can make Spring understand this binding of mine.

SpringMVC Controller Method Doesn't Bring in Model

I noticed that when a Form Submit happens, my handler method that captures a #Model object as a parameter does have a valid Model available to me, e.g.
public ModelAndView save(final HttpServletRequest request,
#ModelAttribute(MODEL_NAME) MyModel model,
BindingResult bindingResult)
But when I have a handler method corresponding to a URL redirect from a simple <a href=".."> button/link, e.g.
<a href="myController.do&function=add">
leading to
#RequestMapping(params = "function=add")
public ModelAndView add(final HttpServletRequest request,
#ModelAttribute(MODEL_NAME) MyModel model) throws Exception
in that case, the model object is NULL. The model wasn't carried through the request and made available to me in the handler method.
Is there a way to reexpose the model? I do have the same param in both methods, but in the 2nd one the "model" object is NULL.
If you want to use GET request with you will need to add the model to the URL. Or you can use POST with a form instead.
See: how to pass a java object from jsp to spring controller on clicking a link

Spring form commandName = session attribute

I have many pages with the same form where I bind my object using commandName. I try to put the object to session with name "myObject" and use it for form (commandName = "myObject"). But system throws exception (Neither BindingResult nor plain target object for bean name "myObject").
How can I bind the object to session for any controllers and requests?
That error is typical when your use a form:form tag that targets a command object that is not available in the request.
A good approach is to combine #ModelAttribute annotated method with #SessionAttributes on a Controller that intially forwards to the view that contains the form, something like
#Controller
#SessionAttributes("myObject")
public class FormController {
#ModelAttribute("myObject")
public MyObject createMyObjectBean() {
return new MyObject();
}
...
}
The initally createMyObjectBean will be called with whatever is the first request to the controller methods, but it won't be called on subsequent request as the myObject value will come from session due to #SessionAttributes
just note that for this approach to work, you must have a controller that forwards to the view that contains your form

What's the recommended way to implement generic functionality on spring MVC?

Let's say I want to do the same thing the Masterpage's code behind does on ASP.NET side. I'm currently learning Spring MVC and Im using JSP for my views. I know for the JSP side, everytime I create a page I include header.jsp and footer.jsp.
Lets say I have this var in my header.jsp ${ItemsQty} I would have to tho this in all controllers request mappings to get the value inserted.
model.addAttribute("ItemsQty", ItemsServices.count());
What's the correct way to set this value? adding the attribute in all controllers, all request methods?
Regards.
You could create an interceptor that adds the attribute to the modelmap. Interceptors can be mapped to any URL you like.
<mvc:annotation-driven>
<mvc:interceptors>
<mvc:mapping path="/items/**" />
<bean="my.package.items.ItemsInterceptor"/>
</mvc:interceptors>
</mvc:annotation-driven>
When the url matches mapping /items/** this interceptor will add the attribute to the modelmap after the handler is called.
class ItemsInterceptor extends HandlerInterceptorAdapter {
#Autowired
private ItemsServices service;
public void postHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView)
throws Exception {
if (modelAndView != null) {
modelAndView.addObject("ItemsQty", service.count());
}
}
}
What's the correct way to set this value? adding the attribute in all controllers, all request methods?
No. These attributes are session scoped attributes. Session scoped attributes are specified in Spring MVC using #SessionAttributes. So in your case it would be
#SessionAttributes({"ItemsQty"})
So the first time you add "ItemsQty" to the model, it will stay there (across multiple requests) until SessionStatus.setComplete() is called.

Spring MVC Annotation Based Controller command object losing values on POST

I am loading a user object my calling a service and then store this user as a command object in the model on GET in the controller. This user object has many properties that are not mapped in the jsp page. After submitting the form, I am getting the command object i the controller on POST. But strangely, I only see the properties in the command object which are mapped to the jsp page. All the other properties those were there when I load the object are lost. I need all the properties in object to be able to successfully save it in hte database.
Can anybody help me figure this problem? Thanks!
Update
I am adding some code to better understand it. In POST handler, I was expecting the command object to have all the properties that was loaded in GET handler in addition to the properties that are bound with jsp. Instead I am losing all propeties except those are bound to the jsp. Am I doing something wrong here?
#RequestMapping(method = RequestMethod.GET)
public String showForm(ModelMap model, HttpSession session, HttpServletRequest request) throws Exception {
UserBean user = Util.getUser(session);
UserBean command = (UserBean)userProfileService.loadByUserName(user.getUserName());
model.addAttribute("command", command);
return formView;
}
#RequestMapping(method = RequestMethod.POST)
public String onSubmit(#ModelAttribute("command") UserBean command, BindingResult result, HttpSession session) throws Exception {
UserBean user = (UserBean) command;
userProfileService.saveUser(user);
return "successView";
}
Update
I am adding some code to better understand it. In POST handler, I was expecting the command object to have all the properties that was loaded in GET handler in addition to the properties that are bound with jsp. Instead I am losing all propeties except those are bound to the jsp. Am I doing something wrong here?
#RequestMapping(method = RequestMethod.GET) public String showForm(ModelMap model, HttpSession session, HttpServletRequest request) throws Exception { UserBean user = Util.getUser(session); UserBean command = (UserBean)userProfileService.loadByUserName(user.getUserName()); model.addAttribute("command", command); return formView; }
#RequestMapping(method = RequestMethod.POST) public String onSubmit(#ModelAttribute("command") UserBean command, BindingResult result, HttpSession session) throws Exception { UserBean user = (UserBean) command; userProfileService.saveUser(user); return "successView"; }
Update
If I store the command object in session how would the jsp bind the propeties. I thought I needed to store it in model for that?
Could you explain please.
Update
storing the command object in session solves the problem. I was able to store it by using
#SessionAttributes ("command")
Thanks a lot!
That's expected behaviour. Spring does not take your existing object (how would it get it?) - it creates a new one and fills it with data.
You can use the #ModelAttribute annotated-method to specify a method which will load the existing object from storage (db?) by its ID (submitted).
#ModelAttribute annotated methods are executed before the chosen #RequestMapping annotated handler method. They effectively pre-populate the implicit model with specific attributes, often loaded from a database. Such an attribute can then already be accessed through #ModelAttribute annotated handler method parameters in the chosen handler method, potentially with binding and validation applied to it.
See 15.3.2.8 of the MVC docs
The Spring-MVC Model values become Request scope attributes in your JSP. This is a one way translation, Spring-MVC does not restore the Model values when the user POSTs a form from your page.
When I need to store information between a GET and a POST (that is, set something on a GET and read it back on a POST), I set a Session attribute.
In your case, I believe that you will need to do one of the following:
Call Util.getUser(session); in the onSubmit method.
Store the command object in the session in the showForm and retrieve it in the onSubmit method>
#ModelAttribute is used to direclty set the values in the Student object from the jsp, other wise in the servlet you have to get the properties using request.getattribute() and than call student setter method.
so u can use both the keywords in jsp page.
<form action="grade" method="get" name="contact1" modelAttribute="contact1">
</form>
or

Resources