Hi *,
I have the following scenario: An entity has quite a few custom validators attached (at property level as well as at class level), and for most of them the validation basically consists of checking the properties against a list of valid values. Also, not all combinations of property values are valid, so in addition to the single values having to be valid, they also must match one another. This cannot be implemented using a general algorithm, so I have to load the list of valid (single) values and the valid combinations of values from a database.
Implementing this as a set of custom Hibernate validators implies that every time these validators are run, they query the database. In particular, the validators seem to be invoked one last time before flushing the entities down to the database. The "real problem" with this (besides minor performance penalty) is that this seems to interfere with the currently ongoing flush of the entity manager, so the ultimate result is an IndexOutOfBoundsException within the ActionQueue.executeActions(List) method -- for some reason, the list of current actions that this method iterates is cleared "behind its back" during the execution of a single action (the one that queries the database) so when executeActions() does the next iteration, it gets the IOOBE. (See below.)
Well on the one hand, IMHO this should actually not happen within Hibernate code -- first, if there is a general problem, it should be reported as such with a meaningful exception message, and second, iterating the list over its iterator instead of "the array way" would have prevented this and/or thrown the more meaningful ConcurrentModificationException.
But on the other hand, I'd like to ask if if is generally OK to perform DB queries within custom validator code? In my case, the validator runs the query through the same entity manager that is currently flushing (and invoking the validator as a side effect). Is that OK? Or should I use a separate entity manager for such situations? Or maybe my use case is generally not what custom validators are intended for, so I should better do this kind of validation "the old way" instead of through annotated validations? (This would have the added benefit that I only validate when the affected properties actually changed, and not every single time the entity is persisted.)
If the given approach itself is OK, what could be the reason for this issue?
Thanks for any ideas,
Mike
Further information: I am using Hibernate 3.3.2 as part of JBoss Seam 2.2 on a JBoss 4.2 server. Here the relevant exception stack trace and the relevant code snippet from Hibernate code:
Code:
Caused by: java.lang.IndexOutOfBoundsException: Index: 2, Size: 0
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.get(ArrayList.java:322)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:366)
at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:504)
... 62 more
Code:
260: private void executeActions(List list) throws HibernateException {
261: int size = list.size();
262: for ( int i = 0; i < size; i++ ) {
263: execute( ( Executable ) list.get( i ) );
264: }
265: list.clear();
266: session.getBatcher().executeBatch();
267: }