Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSR-303 @Valid validation is not invoked for @RequestBody controller method arguments [SPR-6709] #11375

Closed
spring-issuemaster opened this issue Jan 15, 2010 · 29 comments

Comments

Projects
None yet
2 participants
@spring-issuemaster
Copy link
Collaborator

commented Jan 15, 2010

Scott Frederick opened SPR-6709 and commented

If an argument to a Spring MVC Controller method is annotated with both the @RequestBody and @Valid annotations, the argument should be passed to the validation framework after being populated, but the validation is not invoked.

More details and an example are included in the forum thread.


Affects: 3.0 GA

Reference URL: http://forum.springsource.org/showthread.php?t=81563

Referenced from: commits f1ad53d, 9d2ee70, 18f5d90

26 votes, 30 watchers

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Feb 3, 2010

Michal Huniewicz commented

Yep, I confirm this. I have the same problem.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented May 18, 2011

Arjen Poutsma commented

Rossen, could you take a look at this one?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jul 20, 2011

Vijay Dendukuri commented

I'm using 3.1 M2, But i'm still getting the following exception.

java.lang.IllegalStateException: Errors/BindingResult argument declared without preceding model attribute. Check your handler method signature!
org.springframework.web.method.annotation.support.ErrorsMethodArgumentResolver.resolveArgument(ErrorsMethodArgumentResolver.java:60)
org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:65)
org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:153)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:117)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:100)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:502)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:465)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:863)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:792)

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jul 20, 2011

Vijay Dendukuri commented

I take it back, Actually its working now. With out the BindingResult Argument

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jan 7, 2012

Alexander Shabanov commented

The issue still reproduced on 3.1.0.RELEASE

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jan 9, 2012

Rossen Stoyanchev commented

Is it possible that you're using the AnnotationMethodHandlerAdapter still? New features in annotated controllers require switching to the support classes listed here.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jan 10, 2012

Alexander Shabanov commented

Yes, I think this is the reason. I didn't try it yet, but I'm pretty sure this would solve the problem. Please, close the bug.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jan 10, 2012

Rossen Stoyanchev commented

Resolving as requested.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jan 25, 2012

Mike Finney commented

I also got a java.lang.IllegalStateException: Errors/BindingResult argument declared without preceding model attribute. Check your handler method signature!

I am using Spring 3.1.0.RELEASE. Other than using the 3.1.0 jars, how can I make sure I am using the latest "support classes" listed here: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/new-in-3.1.html#d0e1515 Is there a xml declaration or java config I should do?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jan 25, 2012

Rossen Stoyanchev commented

See comment by Vijay above. You need to remove the BindingResult or Errors method argument. That can only be used after a @ModelAttribute argument.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Feb 16, 2012

chris fang commented

@Valid @RequestBody can work together in 3.1 , but how can we get the errors without the BindingResult method argument?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Feb 16, 2012

Rossen Stoyanchev commented

The idea here is that @RequestBody validation errors can be handled in one place. The DefaultHandlerExceptionResolver handles it by returning a 400 error. You can do the same if you want to add more detail to the body of the response.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Feb 16, 2012

Scott Frederick commented

@Chris - Rossen's answer is, of course, the best technique provided you want validation errors to be handled in the same way across your application (i.e. you want the body of the response to be the same). If you need to customize validation error handling per controller, another option is to add a @ExceptionHandler-annotated method to the controller, passing "org.springframework.validation.BindException.class" as the value parameter to the annotation (see http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-exceptionhandler). The BindException has a getBindingResult() method that gives the details of the validatation failure.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Feb 16, 2012

chris fang commented

@Scott Frederick - Thanks for your response. I tried @ExceptionHandler(BindException.class). But @Valid doesn't throw any bindException when using with @RequestBody. I think I may need to switching to the new support class in order to get the new feature ( RequestMappingHandlerMapping
RequestMappingHandlerAdapter
ExceptionHandlerExceptionResolver)

Thanks a lot.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Feb 16, 2012

Rossen Stoyanchev commented

I think Scott meant MethodArgumentNotValidException. This is described in the documentation and in the javadoc of @RequestMapping.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Feb 16, 2012

Scott Frederick commented

Actually, I was guessing at the exception that would be thrown, based on what Spring 3.0 throws when DataBinder gets a validation error. I guess I should check my assumptions before I give answers (or at least say that I'm guessing). </blush>

Thanks for the correction Rossen.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 2, 2012

Thomas Bruyelle commented

There is blog post that suggests a solution for this issue by using the HandlerMethodArgumentResolvers availables in Spring 3.1

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 5, 2012

Rossen Stoyanchev commented

The blog post was written before this issue was resolved. @Valid is supported for @RequestBody arguments in Spring 3.1.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 21, 2012

rajeev singla commented

I am still getting the error I am using <spring.version>3.1.0.RELEASE</spring.version> and if I do @RequestBody @Valid Org org or @Valid @RequestBody Org org. I am still getting the exception

java.lang.IllegalStateException: An Errors/BindingResult argument is expected to be immediately after the model attribute argument in the controller method signature: public java.lang.String insertOrg(Org,java.lang.String,java.lang.String,java.lang.String,org.springframework.validation.BindingResult)
org.springframework.web.method.annotation.ErrorsMethodArgumentResolver.resolveArgument(ErrorsMethodArgumentResolver.java:61)
org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:74)
org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:155)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:117)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:900)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
edu.apollogrp.platform.common.util.MediaTypeFilter.doFilter(MediaTypeFilter.java:42)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)</pre>

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 21, 2012

Scott Frederick commented

Rajeev,

The problem you are having is not related to using @RequestBody and @Valid together. It appears to be a problem with the ordering of the arguments to your controller handler method. You need to put the BindingResult argument immediately after the Org argument (as the exception message says).

If that doesn't fix your problem, I suggest you post to the Spring Forum (http://forum.springsource.org/forumdisplay.php?25-Web) with the code for the controller.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 22, 2012

Thomas Bruyelle commented

Rajeev,

I use @Valid and @RequestBody with Spring 3.1.1.RELEASE and it works like a charm.

Like Scott said, your problem is about the BindingResult parameter. I suggest you don't use the BindingResult in parameter of your controller method, but rather declare a new method annotated with @ExceptionHandler on MethodArgumentNotValidException in your controller. This method will be invoked each time the validation failed.

Exception MethodArgumentNotValidException gives you access to the BindingResult :

@ExceptionHandler
public void handleMethodArgumentNotValidException( MethodArgumentNotValidException error )
{
    (...) error.getBindingResult() (...)
}
@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 23, 2012

rajeev singla commented

Thanks for response Scott and Thomas.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 26, 2013

Puneet Pandey commented

Scott and Thomas: I use this combination of @Valid and @RequestBody with Spring 3.1.1 and it works perfectly. However, my requirement is such that I need to use Spring 3.1.0. I use Spring 3.1.0 and deploy the code to a Jetty server and while deploying itself I run into error. (Very same code with Spring 3.1.1 gets deployed and runs like gem).

The issue I get while deploying my code is : Failed startup of context o.m.j.p.JettyWebAppContext{/,file:/D:/SAMS-2013/WORKSPACE-06/com.sams.validation/src/main/webapp/},file:/D:/SAMS-2013/WORKSPACE-06/com.sams.validation/src/main/webapp/
java.util.zip.ZipException: invalid entry size (expected 3100 but got 2760 bytes).

Is it that the combination of @Valid and @RequestBody does not work? Please suggest.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 26, 2013

Puneet Pandey commented

Is it that the combination of @Valid and @RequestBody does not work with Spring 3.1.0?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 26, 2013

Scott Frederick commented

I don't see anything to indicate that the combination of @Valid and @RequestBody is the source of the ZipException, but there isn't very much information here to go on. I suggest posting your problem, with as much detail as possible, to the Web section of the Spring Forum: http://forum.springsource.org/forumdisplay.php?25-Web.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 27, 2013

Puneet Pandey commented

Scott: I too couldn't see any relation between Validation annotations and ZipException. Unfortunately, however, I was getting the exception only when I was changing the Spring version. I could process a little further but couldn't get the issue resolved completely. Will post the issue in Springsource forum too. Thanks!

@spring-issuemaster

This comment has been minimized.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 27, 2013

Oliver Drotbohm commented

An exception like this usually indicates corrupted JAR files. Have you tried purging your local Maven repo (or equaivalent) and re-grabbing the binaries?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 27, 2013

Puneet Pandey commented

Oliver: You are correct, it was actually a case of corrupted jar. I have actually progressed and deployed the code to the Virgo Server. But, still could not get it to work. Have posted the issue to the SpringSource. Please have a look into it and suggest.

Link:

http://forum.springsource.org/showthread.php?135923-Spring3-MVC-annotation-driven-Rest-Services-in-OSGi-environment-bean-validation-issue&p=441701#post441701

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.