0

This is probably a very simple error somewhere. Please help. I have a home.jsp page with two <form:form> tags:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<%@ taglib uri="/META-INF/c.tld" prefix="c"%>
<%@ taglib uri="/META-INF/fmt.tld" prefix="fmt"%>
<%@ taglib uri="/META-INF/spring-form.tld" prefix="form"%>

<html>

<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">

<head>
    <title>Home Page</title>
</head>

<body>

<div>
    <form:form name="loginForm" modelAttribute="loginUser" action="login" method="post">

        <c:if test="${loginMsg != null}"><c:out value="${loginMsg}"></c:out></c:if>
        <br/>

        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>
</div>

<div>
    <form:form name="SignUpForm" modelAttribute="signUpUser" action="signup" method="post">

        <c:if test="${signupMsg != null}"><c:out value="${signupMsg}"></c:out></c:if>   
        <br/>

        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" />
        <br/>

        <input type="submit" id="id_signUp" value="Sign Up">

    </form:form>
</div>

</body>

</html>

Each form is handled by a different controller. The problem is, when I fill (just) one of the forms and click the submit button, both the ModelAttributes are getting populated with the same value

There's nothing special to my controllers:

@RequestMapping("/login")
public String login(@ModelAttribute("loginUser") User user,
        BindingResult result, @ModelAttribute("signUpUser") User signUpUser,
        BindingResult signUpResult, ModelMap model, HttpServletRequest request,
        HttpServletResponse response) {

    // Here, both user and signUpUser have the same value (WHY?)
    // But I dint fill the sign up form at all

    loginFormValidator.validate(user, result);

    if(Errors in `result`)
        return "forward:/home";

    // Authentication Logic
    request.getSession().setAttribute("s_user_obj", some_variable);
    return "forward:/home";

}

UPDATE:

Here's the HTMLs generated. BEFORE login action:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">

<head>
    <title>Welcome to m0m0</title>
</head>

<body>

<div>
    <form id="loginUser" name="loginForm" action="login" method="post">

        <br/>                           
        Email: <input id="loginEmail" name="email" name="loginEmail" type="text" value=""/>

        <br/>
        password: <input id="password" name="password" name="loginPassword" Id="loginPassword" type="password" value=""/>

        <br/>
        <input type="submit" id="id_login" value="Login">

    </form>
</div>

<div>
    <form id="signUpUser" name="SignUpForm" action="signup" method="post">

        <br/>
        Full Name: <input id="name" name="name" name="name" type="text" value=""/>

        <br/>                   
        Email: <input id="signupEmail" name="email" name="signupEmail" type="text" value=""/>

        <br/>
        password: <input id="password" name="password" name="signUpPassword" Id="signUpPassword" type="password" value=""/>

        <br/>
        <input type="submit" id="id_signUp" value="Sign Up">

    </form>
</div>

</body>

</html>

AFTER login action:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">

<head>
    <title>Welcome to m0m0</title>
</head>

<body>

<div>
    <form id="loginUser" name="loginForm" action="login" method="post">

        <br/>                           
        Email: <input id="loginEmail" name="email" name="loginEmail" type="text" value="a@b.com"/>

        <br/>
        password: <input id="password" name="password" name="loginPassword" Id="loginPassword" type="password" value=""/>

        <br/>
        <input type="submit" id="id_login" value="Login">

    </form>
</div>

<div>
    <form id="signUpUser" name="SignUpForm" action="signup" method="post">

        <br/>
        Full Name: <input id="name" name="name" name="name" type="text" value=""/>

        <br/>                   
        Email: <input id="signupEmail" name="email" name="signupEmail" type="text" value="a@b.com"/>

        <br/>
        password: <input id="password" name="password" name="signUpPassword" Id="signUpPassword" type="password" value=""/>

        <br/>
        <input type="submit" id="id_signUp" value="Sign Up">

    </form>
</div>

</body>

</html>
th3an0maly
  • 3,360
  • 8
  • 33
  • 54

1 Answers1

2

spring binds the parameters to both models, because it doesn't consider the model name for binding (and btw. there's no information about the model name in the request)

Each form is handled by a different controller.

but this method handles both?

@RequestMapping("/login")
public String login(@ModelAttribute("loginUser") User user,
    BindingResult result, @ModelAttribute("signUpUser") User signUpUser,
    BindingResult signUpResult, ModelMap model, HttpServletRequest request,
    HttpServletResponse response) {

// Here, both user and signUpUser have the same value (WHY?)
// But I dint fill the sign up form at all

loginFormValidator.validate(user, result);

if(Errors in `result`)
    return "forward:/home";

// Authentication Logic
request.getSession().setAttribute("s_user_obj", some_variable);
return "forward:/home";

}

EDIT:

public class Form {
    private User loginUser;
    private User signupUser;
    .....
}

then you can do the following

<form:input path="loginUser.name" />

and

<form:input path="signupUser.name" />

in this case you'll only have 1 model attribute, not 2

marco.eig
  • 4,209
  • 2
  • 18
  • 26
  • I dont understand what you mean by "it doesn't consider the model name for binding" and "there's no information about the .." I have provided `ModelMap model` as an argument to `login()` To your second question: No, there's another method called `SignUp()` that handles the sign up form. Initially, each method had only one (relevant) `@ModelAttribute`. I have modified `login()` to include `signUpUser` to demonstrate that both `signUpUser` and `user` have the same values in their fields. – th3an0maly Sep 18 '12 at 10:15
  • 2
    spring cannot distinguish between singup form and login form, since both are of type user. the model attribute name is not part of the request body when submitting the form. so it's up to you whether to treat it as a login model or a signup model. spring won't take care of this. – marco.eig Sep 18 '12 at 10:48
  • is there a way I can do something like `path="loginUser.name"` so that Spring knows which `@ModelAttribute` it's dealing with? Please refer to the second answer in this post: http://stackoverflow.com/questions/12230216/how-to-update-two-entities-model-elements-from-one-jsp-in-spring-mvc – th3an0maly Sep 18 '12 at 11:24
  • no that's not possible (unless you implement your own binding logic). you can wrap both userForm and signupForm in a additional model. see my updated answer – marco.eig Sep 18 '12 at 11:40
  • That's more like it, @reagten. But is it possible to send only, say, `Form.loginUser` to the controller having `login()` method? – th3an0maly Sep 18 '12 at 11:46
  • 1
    create 2 form:form elements (like in your post), in the first you can use path prefix "loginUser." and in the second "signupUser." – marco.eig Sep 18 '12 at 11:52
  • 1
    let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/16825/discussion-between-reagten-and-th3an0maly) – marco.eig Sep 18 '12 at 12:09