[hibernate-issues] [Hibernate-JIRA] Commented: (HV-524) java.util.NoSuchElementException in type level validation using EclipseLink

Nicholas Padilla (JIRA) noreply at atlassian.com
Fri Jan 13 00:55:10 EST 2012


    [ http://opensource.atlassian.com/projects/hibernate/browse/HV-524?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=45121#comment-45121 ] 

Nicholas Padilla commented on HV-524:
-------------------------------------

Hey ladies and gents! I have worked on this a bit today and here are my findings: 

When defining a @Constraint implementation AND specifying ElementType.TYPE usage you can end up in a scenario where BeanMetaDataImpl doesn't know how to build the 
ValueContext for the field.  Since in some cases, like @ScriptAssert, you are not really looking for specific Member/PropertyPath to lookup.

This happens because this line 
{code:borderStyle=solid}
initClassConstraints(Class<?> clazz, AnnotationIgnores annotationIgnores, BeanMetaDataCache beanMetaDataCache)
{code}
calls 
{code:borderStyle=solid}
BeanMetaDataImpl [line: 715] - initClassConstraints(Class<?>, AnnotationIgnores, BeanMetaDataCache)
{code}
which intentionally creates a NULL Member -  which we try to use later as a propertyName.  
This is correct since this constraint is of ElementType.TYPE. 

It then reaches this point in the code: 
{code:borderStyle=solid}
ValidatorImpl [line: 137] - validate(T, Class<?>...)	
{code}
The ValueContext gets created with an empty Path object, next:
{code:borderStyle=solid}
ValidatorImpl [line: 444] - validateConstraint(ValidationContext<T, ?>, ValueContext<U, V>, BeanMetaConstraint<?>)
{code}
This call tries to set our Path to be correct, using the Parent and the propertyName(), however, we have an ElementType.TYPE so we don't set it. Nothing to set either since we create a NULL Member earlier. Next:
{code:borderStyle=solid}
BeanValidationListener$AutomaticLifeCycleValidationTraversableResolver [line: 123] - isReachable(Object, Node, Class<?>, Path, ElementType)	
{code}
This call expects a non-null and non-empty Path object, but guess what? It is still empty.  So when it calls isValidationRequired() a few lines down it bombs with the error below; this is because there is nothing to call .next() on. 

{noformat}
Caused by: java.util.NoSuchElementException
	at java.util.Collections$EmptyIterator.next(Collections.java:2998)
	at org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener$AutomaticLifeCycleValidationTraversableResolver.isRootObjectPath(BeanValidationListener.java:180)
	at org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener$AutomaticLifeCycleValidationTraversableResolver.isReachable(BeanValidationListener.java:123)
	at org.hibernate.validator.engine.resolver.SingleThreadCachedTraversableResolver.isReachable(SingleThreadCachedTraversableResolver.java:46)
	at org.hibernate.validator.engine.ValidatorImpl.isValidationRequired(ValidatorImpl.java:1242)
	... 70 more
{noformat}

*ALSO: one major note - this only errors out when trying to call .persist using EclipseLink, when using the @Valid from Spring MVC it works as expected.*
	
I hope this helps in resolving this issue, let mr know if there are any questions - I am tired now so I may not be firing on enough cylinders to get all this
out the way it should be. :)

Please see my log file that contains a full logging of this problem.

> java.util.NoSuchElementException in type level validation using EclipseLink
> ---------------------------------------------------------------------------
>
>                 Key: HV-524
>                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HV-524
>             Project: Hibernate Validator
>          Issue Type: Bug
>          Components: validators
>    Affects Versions: 4.2.0.Final
>         Environment: EclipseLink 2.2.0
>            Reporter: sinuhepop
>         Attachments: HV-524.zip
>
>
> When EclipseLink obtains an entity from database does a validation. It works ok with field level validators, but throws an exception with type level ones.
> The problem is that SingleThreadCachedTraversableResolver sends an "empty" pathToTraversableObject to EL's BeanValidationListener, who finally fails when calling "pathToTraversableObject.iterator().next().getName()".
> I don't know who (HV or EL) is responsible of the issue, but it worked with HV-4.0.2.GA.
> Thanks for your effort.
> Sinuhé.
> {noformat}
> Caused by: javax.validation.ValidationException: Call to TraversableResolver.isReachable() threw an exception
> 	at org.hibernate.validator.engine.ValidatorImpl.isValidationRequired(ValidatorImpl.java:1251) ~[hibernate-validator-4.2.0.Final.jar:4.2.0.Final]
> 	at org.hibernate.validator.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:448) ~[hibernate-validator-4.2.0.Final.jar:4.2.0.Final]
> 	at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:397) ~[hibernate-validator-4.2.0.Final.jar:4.2.0.Final]
> 	at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:361) ~[hibernate-validator-4.2.0.Final.jar:4.2.0.Final]
> 	at org.hibernate.validator.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:313) ~[hibernate-validator-4.2.0.Final.jar:4.2.0.Final]
> 	at org.hibernate.validator.engine.ValidatorImpl.validate(ValidatorImpl.java:139) ~[hibernate-validator-4.2.0.Final.jar:4.2.0.Final]
> 	at org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener.validateOnCallbackEvent(BeanValidationListener.java:84) ~[eclipselink-2.2.0.jar:2.2.0.v20110202-r8913]
> 	at org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener.preUpdate(BeanValidationListener.java:72) ~[eclipselink-2.2.0.jar:2.2.0.v20110202-r8913]
> 	at org.eclipse.persistence.descriptors.DescriptorEventManager.notifyListener(DescriptorEventManager.java:671) ~[eclipselink-2.2.0.jar:2.2.0.v20110202-r8913]
> 	at org.eclipse.persistence.descriptors.DescriptorEventManager.notifyEJB30Listeners(DescriptorEventManager.java:641) ~[eclipselink-2.2.0.jar:2.2.0.v20110202-r8913]
> 	at org.eclipse.persistence.descriptors.DescriptorEventManager.executeEvent(DescriptorEventManager.java:200) ~[eclipselink-2.2.0.jar:2.2.0.v20110202-r8913]
> 	at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.calculateChanges(DeferredChangeDetectionPolicy.java:85) ~[eclipselink-2.2.0.jar:2.2.0.v20110202-r8913]
> 	at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.calculateChangesForExistingObject(DeferredChangeDetectionPolicy.java:54) ~[eclipselink-2.2.0.jar:2.2.0.v20110202-r8913]
> 	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:623) ~[eclipselink-2.2.0.jar:2.2.0.v20110202-r8913]
> 	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1496) ~[eclipselink-2.2.0.jar:2.2.0.v20110202-r8913]
> 	at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:264) ~[eclipselink-2.2.0.jar:2.2.0.v20110202-r8913]
> 	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1130) ~[eclipselink-2.2.0.jar:2.2.0.v20110202-r8913]
> 	at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:84) ~[eclipselink-2.2.0.jar:2.2.0.v20110202-r8913]
> 	... 73 common frames omitted
> Caused by: java.util.NoSuchElementException: null
> 	at java.util.Collections$EmptyIterator.next(Unknown Source) ~[na:1.7.0]
> 	at org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener$AutomaticLifeCycleValidationTraversableResolver.isRootObjectPath(BeanValidationListener.java:180) ~[eclipselink-2.2.0.jar:2.2.0.v20110202-r8913]
> 	at org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener$AutomaticLifeCycleValidationTraversableResolver.isReachable(BeanValidationListener.java:123) ~[eclipselink-2.2.0.jar:2.2.0.v20110202-r8913]
> 	at org.hibernate.validator.engine.resolver.SingleThreadCachedTraversableResolver.isReachable(SingleThreadCachedTraversableResolver.java:46) ~[hibernate-validator-4.2.0.Final.jar:4.2.0.Final]
> 	at org.hibernate.validator.engine.ValidatorImpl.isValidationRequired(ValidatorImpl.java:1242) ~[hibernate-validator-4.2.0.Final.jar:4.2.0.Final]
> 	... 90 common frames omitted
> {noformat}

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

       



More information about the hibernate-issues mailing list