I'm trying to create a Home page with 2 functionalities:
I'm mapping each request to a different controller and trying to get the result back to my home.jsp
. But I'm having trouble passing only certain specific ModelAttribute
around, between Controllers. More specifically, i cant get the changed I make to the ModelMap
and BindingResult
in one controller to be reflected in others.
I'm sure there's something basically wrong with what I'm doing. Please help.
There are 2 forms in my home.jsp
. One for Login:
<form:form name="loginForm" modelAttribute="loginUser" action="login" method="post">
Email: <form:input name="loginEmail" id="loginEmail" value="" path="email"/>
<form:errors path="email" cssClass="error" />
<br/>
password: <form:password name="loginPassword" Id="loginPassword" value="" path="password" />
<form:errors path="password" />
<br/>
<input type="submit" id="id_login" value="Login">
</form:form>
and the other one for Sign Up:
<form:form name="SignUpForm" modelAttribute="signUpUser" action="signup" method="post">
Full Name: <form:input name="name" id="name" value="" path="name"/>
<form:errors path="name" cssClass="error" />
<br/>
Email: <form:input name="signupEmail" id="signupEmail" value="" path="email"/>
<form:errors path="email" cssClass="error" />
<br/>
password: <form:password name="signUpPassword" Id="signUpPassword" value="" path="password" />
<form:errors path="password" />
<input type="submit" id="id_signUp" value="Sign Up">
</form:form>
I have 3 controllers: HomeController.java
:
@RequestMapping("/home")
public String showHome(ModelMap model,
@ModelAttribute("loginUser") User loginUser,
BindingResult loginResult,
@ModelAttribute("signUpUser") User signUpUser,
BindingResult signUpResult) {
return "home";
}
AuthenticationController.java
:
@RequestMapping("/login")
public String login(@ModelAttribute("loginUser") User user,
BindingResult result, ModelMap model, HttpServletRequest request,
HttpServletResponse response) {
loginFormValidator.validate(user, result);
if(Errors in `result`)
return "forward:/home";
// Authentication Logic
request.getSession().setAttribute("s_user_obj", some_variable);
return "forward:/home";
}
and ProfileController.java
:
@RequestMapping("/signup")
public String signUpUser(@ModelAttribute("signUpUser") User user,
BindingResult result, ModelMap model) {
// Do stuff related to Sign Up
// Forward to home.jsp
}
When the request is forwarded to /home
, I'm getting same values in both loginUser
and signUpUser
. Worse, there are no errors i.e. the result
variable is not reflecting the ones in the previous controllers.
I'm sure there's a better way of doing this, this is a newbie's attempt at it. Please advice.
The issue that I see here is the way @ModelAttribute("loginUser")
and @ModelAttribute("signUpUser")
is interpreted for methods by Spring - here is some reference - http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-modelattrib-method-args
The arguments are retrieved from the model(and instantiated if necessary), but the problem part is that they are repopulated based on the request parameters, which would end up populating both your attributes the same way. The only workaround that I can think of is to explicitly retrieve the model attributes yourself in your method:
@RequestMapping("/home")
public String showHome(ModelMap model) {
model.get("loginUser");...
model.get("signUpUser");...
return "home";
}
Update
Based on your comments, let me recommend an alternate flow and a more explicit flow:
Have a method which sets both your loginUser and signUpUser model attributes this way:
private void populateAttributes(Model model, User loginUser, User signupUser){
if (loginUser==null) loginUser = new User();
if (singupUser==null) singupUser = new User();
model.addAttribute("loginUser", loginUser);
model.addAttribute("signupUser", signupUser);
}
Now in your login flow:
@RequestMapping("/login")
public String login(User user,
BindingResult result, Model model, HttpServletRequest request,
HttpServletResponse response) {
loginFormValidator.validate(user, result);
if(Errors in `result`)
populateAttributes(user, null);
return "home";
// Authentication Logic
request.getSession().setAttribute("s_user_obj", some_variable);
populateAttributes(model, user, null);
return "home";
}
Similar flow in your signup:
@RequestMapping("/signup")
public String signUpUser(User user,
BindingResult result, Model model) {
populateAttributes(model, null, user);
return "home"
}
and showHome:
@RequestMapping("/home")
public String showHome(Model model,) {
populateAttributes(model, null, null);
return "home";
}