Announcement Announcement Module
Collapse
No announcement yet.
Spring MVC 3 and returning validation errors to page from @Valid Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring MVC 3 and returning validation errors to page from @Valid

    I need some major help here. I've been banging my head against this problem for almost a week now and I'm guessing I am missing something very basic, so I hope someone here can point out my issues. .. with the code.

    The gist of it is that I can't seem to get the validation errors to show up in the view page. I have tried just about every combination of configurations offered up by the current spring mvc docs, but no joy. The errors are there, in the BindingResult object - I was able to see them by runtime debugging the deployed application. For some reason though, they are not being sent back to the view page and displayed by Spring's tag library. Can anyone please tell me what the heck I'm doing wrong?

    The Stack:
    Spring 3.0.6
    Tiles 2.2.2
    Glassfish 3.1.1

    The Code:

    Spring app-servlet.xml
    Code:
        <context:component-scan base-package="com.facets.w101.almanac.spring"/>
        <mvc:annotation-driven/>
        ... other stuff
    Spring main.beandef.xml
    Code:
        <bean id="messageSource"
              class="org.springframework.context.support.ResourceBundleMessageSource"
              p:basename="messages" />
        <bean id="userValidator" class="com.mycmpny.UserValidator" />
        ... other stuff
    Controller code
    Code:
        @Resource(name="userValidator")
        private UserValidator userVldr;
    
        @InitBinder
        public void initBinder(WebDataBinder binder) {
            binder.setValidator(this.userVldr);
        }
    
    
        @RequestMapping(value = "/newuser", method = RequestMethod.GET)
        public String newUserSetup(ModelMap model) {
            model.addAttribute("newUser", new User());
            return "newuser";
        }
    
        @RequestMapping(value = "/newuser", method = RequestMethod.POST)
        public ModelAndView newUserSave(@ModelAttribute @Valid User user, BindingResult result) {
            ModelAndView mav = new ModelAndView("newuser");
            mav.addObject("newUser", user);
            if(result.hasErrors()) {
                return mav;
            }
            /* Code that saves user */
            return mav;
        }
    JSP Code
    Code:
        <frm:form method="POST" commandName="newUser">
        <frm:errors path="*" cssClass="errorblock" element="div" />
        <frm:label path="name">Name:</frm:label>
        <frm:input path="name" id="userName" /><frm:errors path="name" /></td>
        <frm:label path="type">User Type:</frm:label>
        <frm:select path="type">
            <frm:option value="-" label="Please Select..."/>
            <frm:options />
        </frm:select><frm:errors path="type" />
    Notes:
    1. I tried to use <mvc:annotation-driven validator="userValidator"/> in the Spring configuration file to make the userValidator global per the documentation, but for some reason the user validator was never found, loaded, or used. I've tried configuring in the [appname]-servlet.xml and in my main.beandef.xml file, but no joy. So I resorted to the @InitBinder scheme.
    2. Apparently, if your request mapping does not have BindingResult result as a method argument, the whole validation thing blows up and instead of returning to the annotated request method, an exception containing the validation errors is thrown and Spring tries to send the browser to the 404 page. That you have to have BindingResult (or probably some other spring object) as an argument is (altogether now!) not documented.
    3. Enums. It would seem if you use frm:select spring tag for a command object's enum data member and add the attribute-less <frm:options /> child tag, Spring will automatically populate the drop-down select with options that have their value and text set to the enum's "getName()" values. I have yet to find how to tie a custom resource bundle message to it. This functionality is completely undocumented anyhow.

  • #2
    You are returning a modelandview without anything (only the form object). So you are basically destroying the state yourself. Instead of returning a ModelAndView simply return a string named "newuser" as the view name. Spring MVC will then take care of constructing the model etc. If you need to add stuff to the model either at Model or ModelMap as method arguments.

    Either that or add the values from the BindingResult to the ModelAndView as well. (There is a getModel method in binding result which you can use to retrieve all properties from the result and add those to the model).

    so in short..

    Code:
    ModelAndView mav = new ModelAndView("newuser");
            mav.addObject("newUser", user);
            if(result.hasErrors()) {
                mav.addAllObjects(result.getModel());
                return mav;
            }
    Last edited by Marten Deinum; Nov 12th, 2011, 04:44 AM.

    Comment

    Working...
    X