Skip to content

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

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

Closed
spring-projects-issues opened this issue Aug 30, 2017 · 6 comments
Closed
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues 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:

Referenced from: commits f944815, 26284ca

@spring-projects-issues
Copy link
Collaborator Author

Matt Newman commented

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

@spring-projects-issues
Copy link
Collaborator Author

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-projects-issues
Copy link
Collaborator Author

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-projects-issues
Copy link
Collaborator Author

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-projects-issues
Copy link
Collaborator Author

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.

@skozlov
Copy link

skozlov commented Dec 31, 2019

Still doesn't work with Spring 5.2.0.RELEASE and hibernate-validator:6.0.7.Final.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) in: web Issues in web modules (web, webmvc, webflux, websocket) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

3 participants