We have a use case where we have nested @Embedded objects.
E.g., EntityA contains an EmbeddedB and EmbeddedB contains an EmbeddedC.
At save time, validation throws a NullPointException.
Code:
at org.hibernate.validator.event.ValidateEventListener.validateSubElements(ValidateEventListener.java:161)
at org.hibernate.validator.event.ValidateEventListener.validateSubElements(ValidateEventListener.java:166)
at org.hibernate.validator.event.ValidateEventListener.validateSubElements(ValidateEventListener.java:166)
at org.hibernate.validator.event.ValidateEventListener.validate(ValidateEventListener.java:138)
at org.hibernate.validator.event.ValidateEventListener.onPreInsert(ValidateEventListener.java:172)
at org.hibernate.action.EntityInsertAction.preInsert(EntityInsertAction.java:178)
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:72)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:64)
I think that the issue might be because there is no null check on the entity in validateSubElements. In the validate, it returns if the entity == null. But there is no such check when it recursively validates sub elements. I have included two different ways that the problem could be fixed.
The issue is either with ValidateEventListener.java line 159 or line 166.
Code:
private void validateSubElements(
ValidatableElement element, Object entity, List<InvalidValue> consolidatedInvalidValues
) {
if ( element != null /* && entity != null */) { // this would fix it
for ( ValidatableElement subElement : element.subElements ) {
Object component = subElement.getter.get( entity );
InvalidValue[] invalidValues = subElement.validator.getInvalidValues( component );
for ( InvalidValue invalidValue : invalidValues ) {
consolidatedInvalidValues.add( invalidValue );
}
if (component != null) { // and so would this
validateSubElements( subElement, component, consolidatedInvalidValues );
}
}
}
}