Announcement Announcement Module
Collapse
No announcement yet.
Why my Validator in Controller is not triggered in Spring 3? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Why my Validator in Controller is not triggered in Spring 3?

    I tried to test Validation in Spring 3 MVC with new feature. But seems it's not working. I don't really know why. Seems I have followed the reference already.

    Some code piece in my home.jsp. When I click "login" button, it sends json to controller. I am using JQuery here.
    Code:
    <body>
        <form:form modelAttribute="loginUser" method="post">
            <form:errors path="*" cssClass="errorBox" />
    		<table id="loginTable">
    		   <tr>
    		       <td>Company Code</td>
    		       <td><input type="text" id="companyCode"/></td>
    		       <td><form:errors path="companyCode" /></td>
    		   </tr>
    	       <tr>
    	           <td>User Login Id</td>
    	           <td><input type="text" id="loginId"/></td>
                   <td><form:errors path="loginId" /></td>
    	       </tr>
    	       <tr>
    	           <td>Password</td>
    	           <td><input type="text" id="password"/></td>
                   <td><form:errors path="password" /></td>
    	       </tr>
    	       <tr>
    	            <td><input type="button" id="login" value="Login"/></td>
    	            <td><a id="register" href="register">Register Corp</a></td>
    	       </tr>
    		</table>
    	</form:form>
    </body>
    <script type="text/javascript">
    $(document).ready(function() {
        $("#login").click(function() {
            var loginUser = $('#loginUser').serialize();
            $.ajaxSetup({global : false, contentType : 'application/json'});
            $.post("login", '{"companyCode":"CORE"}', function(data) {
                alert(data);
            }, 'json');
        });
    });
    </script>
    In my controller, the method is triggered as I can see the login id is null and companyCode is CORE as expected.
    Code:
    @Controller
    public class LoginController {
    	Logger logger = LoggerFactory.getLogger(LoginController.class);
    
    	@Autowired
    	private Validator loginUserValidator;
    
    	@InitBinder
    	protected void initBinder(WebDataBinder binder) {
    		binder.setValidator(loginUserValidator);
    	}
    
    	@RequestMapping("/login")
    	public ModelAndView login(@Valid @RequestBody LoginUser loginUser) {
    		logger.info(loginUser.getLoginId());
    		logger.info(loginUser.getCompanyCode());
    		ModelAndView homeView = new ModelAndView();
    		homeView.setViewName("home");
    		homeView.addObject(loginUser);
    		return homeView;
    	}
    }
    However, my LoginUserValidator is not triggered and no error msg is shown back to home page
    Code:
    @Component
    public class LoginUserValidator implements Validator {
    	Logger logger = LoggerFactory.getLogger(LoginController.class);
    
    	public boolean supports(Class<?> clazz) {
    		return LoginUser.class.equals(clazz);
    	}
    
    	public void validate(Object obj, Errors errors) {
    		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "companyCode", "companyCode.empty");
    		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "loginId", "loginId.empty");
    		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "password.empty");
    		logger.info("Error counts: " + errors.getErrorCount());
    	}
    }
    In my applicationContext.xml
    Code:
    	<context:annotation-config/>
    
    	<tx:annotation-driven/>
    In my xxxxx-servlet.xml
    Code:
    <context:component-scan base-package="com.aaa.bbb"/>
    
        <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
        
        <bean id="loginUserValidator" class="com.aaa.bbb.validator.LoginUserValidator" />

    Any idea where I am missing?

  • #2
    Is the validator not triggered or don't you see the error messages?

    Because that is a difference.

    In Spring 3 you would have to check the binding result for errors yourself and send it to the page again, you are sending it to a different page.

    Comment


    • #3
      Hi Marten,

      I cannot find the error log in LoginUserValidator, so that should be considered as Validator not triggered?
      Code:
      logger.info("Error counts: " + errors.getErrorCount());
      And how can I check the binding result for errors myself? I am sending the result to ModelAndView which is named "home". And that supposed to be the home.jsp at the very beginning. In my home.jsp, the form:errors tag should be used for displaying error msg.

      Am my understanding correct? What I want to do is validate some login fields and report back to home.jsp if user input incorrect field value or password is not correct. Is my program doing something wrong? What is the correct way to implement that?

      Comment


      • #4
        First off all you probably want to start to tell MVC that it is the @ModelAttribute. If you want to access the BindingResult simply add it to the method signature right after your parameter annotated with @ModelAttribute.

        Comment


        • #5
          Hi Marten,

          Thx for prompt reply.
          If I change the method signature as below:
          Code:
          public ModelAndView login(@Valid @RequestBody @ModelAttribute("loginUser") LoginUser loginUser, BindingResult result)
          It complains:
          Handler parameter annotations are exclusive choices - do not specify more than one such annotation on the same parameter
          If I change the method signature as below:
          Code:
          public ModelAndView login(@Valid @ModelAttribute("loginUser") LoginUser loginUser, BindingResult result)
          Then the loginUser instance cannot be converted with value passed from request json.
          How am I supposed to map the json object to LoginUser model then? I need to submit form directly instead of using JSON?

          I also find an issue in JIRA:
          Authorize @ModelAttribute to play along with @RequestParam/@RequestHeader/...
          Last edited by chengusky; Mar 22nd, 2010, 04:27 AM. Reason: Add more information

          Comment


          • #6
            Ah I missed the JSON bit, sorry for that.

            For what I know the @RequestBody doesn't use databinding and hence your validator isn't called. The @RequestBody simply does conversion with a JSON mapper and thus bypassed the databinder.

            You can do manual validation in your method and then check for errors yourself and act accordingly.

            Comment


            • #7
              I see, thx for you prompt reply which helps me clear my thought and get a bit more understanding on Spring.

              I doubt the Spring Reference is not that detail or intuitive enough. How do you know say "@RequestBody doesn't use databinding and hence your validator isn't called. The @RequestBody simply does conversion with a JSON mapper"? Reading Spring source?

              Can you refer any further document I can read as an Spring beginner? Thx

              Comment


              • #8
                The DataBinder is only used for @ModelAttribute, JSON works in a different way (which is explained in the reference guide although it might be that it isn't clear that databinding is skipped).

                Comment

                Working...
                X