Search code examples
javaexceptionspring-mvcforms-authenticationjava.lang.class

How to get a form's data after the user submitted it with Spring MVC?


i am getting an error message: org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.ClassCastException: java.lang.Object cannot be cast to com.crimetrack.business.Login

Login.java

public class Login {

    private String userName;
    private String password;
    private boolean loggedin;

    public Login(){};

    /**
     * @return the loggedin
     */
    public boolean isLoggedin() {
        return loggedin;
    }

    /**
     * @param loggedin the loggedin to set
     */
    public void setLoggedin(boolean loggedin) {
        this.loggedin = loggedin;
    }

    /**
     * @param userName
     * @param password
     */
    public Login(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }

    /**
     * @return the userName
     */
    public String getUserName() {
        return userName;
    }

    /**
     * @param userName the userName to set
     */
    public void setUserName(String userName) {
        this.userName = userName;
    }

    /**
     * @return the password
     */
    public String getPassword() {
        return password;
    }

    /**
     * @param password the password to set
     */
    public void setPassword(String password) {
        this.password = password;
    }

}

@Controller
public class AuthenticationController {

    private final Logger logger = Logger.getLogger(getClass());

    private AuthenticationManager authenticationManager;
    private Login login = new Login();

    String message = "Congrulations You Have Sucessfully Login";
    String errorMsg = "Login Unsucessful";

    @RequestMapping(value="login.htm")
    public ModelAndView onSubmit(Object command) throws ServletException {

        String userName = ((Login)command).getUserName();
        String password = ((Login)command).getPassword();

        login.setUserName(userName);
        login.setPassword(password);

        logger.info("Login was set");

        logger.info("the username was set to " + login.getUserName());
        logger.info("the password was set to " + login.getPassword());

        if (authenticationManager.Authenticate(login) == true){
            return new ModelAndView("main","welcomeMessage", message);
        }

        //return new ModelAndView("main","welcomeMessage", message);
        return new ModelAndView("login","errorMsg", "Error!!!");
    }

}

Solution

  • Try this solution:

    JSP

    <form:form action="yourUrl" modelAttribute="login" method="POST">
    <% ... %>
    </form:form>
    

    Controller

    // your method that prints the form
    public ModelAndView onGet(@ModelAttribute Login login) {
        // return ...
    }
    
    @RequestMapping(value="login.htm")
    public ModelAndView onSubmit(@ModelAttribute Login login) {
        String userName = login.getUserName();
        String password = login.getPassword();
        // ...
    }
    

    Explanation

    The annotation @ModelAttribute does exactly the same as model.addAttribute(String name, Object value). For example, @ModelAttribute Login login is the same as model.addAttribute("login", new Login());.

    That said, with the onGet method, you passing such an object to your view. Thanks to the attribute modelAttribute="login", the tag <form:form> will look into the model's list of attributes to find one which name is login. If it doesn't find, an exception is thrown.

    Then, that's the magic part: with the tag <form:input path="userName" />, Spring MVC will automatically set the property userName of the bean which is in the modelAttribute="login" attribute, i.e. in your case, login. If you had put something like <form:input path="wtf" />, it would have thrown an exception, because the bean Login doesn't have such a property.

    So, finally, on your onSubmit method (thanks once again the to annotation @ModelAttribute), you can access to the login bean, previously autobinded by Spring MVC.

    Note

    I personally (almost) never use a ModelAndView instance, but proceed as follow:

    // the methods can have the name you want
    // not only onGet, onPost, etc. as in servlets
    
    @RequestMapping("url1.htm")
    public String loadAnyJsp(@ModelAttribute Login login) {
        return "path/to/my/views/login";
    }
    
    @RequestMapping("url2.htm")
    public String redirectToAnotherController(@ModelAttribute Login login) {
        return "redirect:url1.htm";
    }
    

    The path to the JSP is specified within your web.xml file, for example:

    ...
    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver" p:favorPathExtension="true" p:favorParameter="true" p:ignoreAcceptHeader="true" p:defaultContentType="text/html">
        <description>Depending on extension, return html with no decoration (.html), json (.json) or xml (.xml), remaining pages are decoracted</description>
        <property name="mediaTypes">
            <map>
                <entry key="xml" value="application/xml" />
                <entry key="json" value="application/json" />
                <entry key="html" value="text/html" />
                <entry key="action" value="text/html" />
            </map>
        </property>
        <property name="defaultViews">
            <list>
                <bean class="org.springframework.web.servlet.view.xml.MarshallingView" p:marshaller-ref="xstreamMarshaller" />
                <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
            </list>
        </property>
        <property name="viewResolvers">
            <list>
                <bean id="nameViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver">
                    <description>Maps a logical view name to a View instance configured as a Spring bean</description>
                </bean>
                <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/views/" p:suffix=".jsp" />
            </list>
        </property>
    </bean>
    ...
    

    You should read the doc to get more information (cf. 16.5 Resolving views).