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

Error on type argument constraint validation failure [SPR-15916] #20470

Closed
spring-issuemaster opened this Issue Aug 30, 2017 · 5 comments

Comments

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

commented Aug 30, 2017

Matt Newman opened SPR-15916 and commented

When using type argument constraints on a collection, if a validation failure occurs, a NotReadablePropertyException is thrown.

The issues occurs with Spring 4.3.10 and Hibernate 5.3.5, but not with Spring 4.3.9 and Hibernate 5.2.5.

First noticed this when upgrading from Spring Boot 1.4.7 to 1.5.6.

A minimal reproduction is available at https://github.com/mdjnewman/spring-framework-issues/tree/master/SPR-15916.

The following error is thrown by shouldRaise400IfNestedValidationFails in the demo project:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: JSR-303 validated property 'thingIds[0].<collection element>' does not have a corresponding accessor for Spring data binding - check your DataBinder's configuration (bean property versus direct field access)

	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
	at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:65)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
	at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167)
	at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134)
	at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:155)
	at org.springframework.issues.TestControllerTests.doTheThingShouldNotDoTheThingWithoutAnId(TestControllerTests.java:56)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.IllegalStateException: JSR-303 validated property 'thingIds[0].<collection element>' does not have a corresponding accessor for Spring data binding - check your DataBinder's configuration (bean property versus direct field access)
	at org.springframework.validation.beanvalidation.SpringValidatorAdapter.processConstraintViolations(SpringValidatorAdapter.java:162)
	at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:117)
	at org.springframework.validation.DataBinder.validate(DataBinder.java:891)
	at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.validateIfApplicable(ModelAttributeMethodProcessor.java:168)
	at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:115)
	at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
	at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
	... 38 more
Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'thingIds[0].<collection element>' of bean class [org.springframework.issues.model.ThingRequest]: Bean property 'thingIds[0].<collection element>' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
	at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:633)
	at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:624)
	at org.springframework.validation.AbstractPropertyBindingResult.getActualFieldValue(AbstractPropertyBindingResult.java:99)
	at org.springframework.validation.AbstractBindingResult.getRawFieldValue(AbstractBindingResult.java:283)
	at org.springframework.validation.beanvalidation.SpringValidatorAdapter.getRejectedValue(SpringValidatorAdapter.java:268)
	at org.springframework.validation.beanvalidation.SpringValidatorAdapter.processConstraintViolations(SpringValidatorAdapter.java:148)
	... 52 more

Affects: 4.3.10

Issue Links:

  • #20490 Wrong exception thrown by Springframework Beans when Type validation fails ("is duplicated by")
  • #20394 SpringValidatorAdapter fails to retrieve value for Bean Validation 2.0's "" literal
  • #20411 Unable to use Hibernate Validator 4.3.2 if Bean Validation API 1.1 is on the classpath

Referenced from: commits f944815, 26284ca

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Aug 30, 2017

Matt Newman commented

On further inspection, 4.3.10 works with Hibernate 5.2.5 ... maybe this is a Hibernate issue?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Aug 31, 2017

Juergen Hoeller commented

This looks like you're using Hibernate Validator 6.0 there... Could you check the specific version? (since "Hibernate" itself is ambigous between ORM and Validator)

We generally only have Bean Validation 2.0 and Hibernate Validator 6.0 support in Spring Framework 5.0. That said, we could add some tolerance to 4.3.11 as well.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Aug 31, 2017

Peter Hart commented

I'm a colleague of Matt's looking at this issue also. This issue is definitely occurring with hibernate validator > 5.2.5 < 6.0. It also looks like the fix that has been used for validation 2.0 won't work for hibernate 5.3, as the path returned by hibernate in this case is subtly different from the one returned by hibernate 6.0/validation 2.0. The path being looked at in SpringValidatorAdapter::determineField is thingIds[0].<collection element>, whereas for 2.0 validation, if I'm understanding this correctly, it should be defined as thingIds[0].<list element>. Also, in hibernate 6.0, it looks like the final node in the path has kind 'CONTAINER_ELEMENT', whereas with hibernate 5.3 it's seems to have type PROPERTY, because validator 1.1 doesn't have/support the CONTAINER_ELEMENT kind.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Aug 31, 2017

Juergen Hoeller commented

Thanks for the insight. I guess we'll have to do some lenient sanity processing of the path, truncating any part starting with a "<" here. We'll also apply that to our 5.0 branch since it is still supposed to be compatible with Hibernate Validator 5.x as well.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Sep 1, 2017

Juergen Hoeller commented

I've revised the algorithm to ignore path elements starting with "<" in addition to selecting them by element kind 'property', making it compatible with Bean Validation 2.0 / Hibernate Validator 6.0 as well as HV5's variant of the feature there. This is available in master for 5.0 RC4 now, along with our general Bean Validation 2.0 story.

For 4.3.11, I'll backport a variant that ignores a path as of the "<" part at least. This is just a Hibernate Validator specific feature outside of a fully supported Bean Validation generation there, but we should nevertheless be able to leniently handle it... tolerating HV5 as well as HV6's variant if we happen to encounter it at runtime.

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.