Hi everyone,
I'm looking for some help with a problem I've run across. I have a block of code that ingests new entities and updates existing entities into my application that's getting a hibernate exception occasionally. The error seems to occur in certain situations when the incoming data does not validate. Here's the ingest code:
Code:
public TServiceModel ingest(final TCriteria criteria,
final Translator<TServiceModel> translator,
final Prevalidator<TServiceModel> prevalidator) throws Exception {
// Find existing entity that matches incoming entity data.
final TServiceModel newRecord = match(criteria);
try {
if (null != prevalidator) {
// prevalidate the record before merging new data.
prevalidator.validate(newRecord);
}
// Merge new data into existing/new entity
final TServiceModel populatedRecord = translator.translate(newRecord);
// Fetch repository for entity type.
final Repository<TServiceModel> repo = getRecordRepository();
// Run validator and save entity if successful
repo.validateAndSave(populatedRecord);
return populatedRecord;
} catch (final Exception e) {
// In case of invalid data, evict record to rollback changes.
HibernateUtil.getCurrentSession().evict(newRecord);
LOG.debug("Ingest failed. Evicting new entity.");
throw e;
}
}
This works great in most situations. My problem is when an entity doesn't validate and is evicted, hibernate tries to persist some of the child entities even though the persistent sets claim to be evicted. It seems it only occurs when I add a new element to the persistent set and then try to evict the entity.
Here's the exception that gets thrown during a commit (or if I flush after evicting):
Code:
org.hibernate.AssertionFailure: possible nonthreadsafe access to session
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:83)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at com.gdi.core.hibernate.HibernateSessionRequestFilter.doFilter(HibernateSessionRequestFilter.java:62)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:964)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
I've considered possibly narrowing the hibernate transaction down to this block of code, but when I have certain conditions occur, I like to log instances of that error in the database, so a rollback would not suffice. I just want the specific entity that's being worked with to be evicted.
Is there something I'm missing or is there possibly a better way of handling this problem?
Thanks in advance!