Hibernate errors with Singleton RuntimeManager and outer transaction in BPM Suite
Environment
- Red Hat JBoss BPM Suite
- 6.4
- jBPM library embedded application
- Singleton RuntimeManager strategy
- Spans a transaction in user application
Issue
Hibernate errors with Singleton RuntimeManager and outer transaction in BPM Suite
- An application embeds jBPM libraries. Sometimes I get the following errors
2018-05-15 13:36:36,410 WARN [org.jbpm.shared.services.impl.TransactionalCommandService] (default task-87) Could not commit session: javax.persistence.PersistenceException: org.hibernate.HibernateException: Found shared references to a collection: org.jbpm.services.task.impl.model.TaskImpl.deadlines.endDeadlines
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602)
at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:492)
at org.jbpm.shared.services.impl.JpaPersistenceContext.queryStringWithParameters(JpaPersistenceContext.java:190)
at org.jbpm.shared.services.impl.JpaPersistenceContext.queryWithParametersInTransaction(JpaPersistenceContext.java:57)
at org.jbpm.shared.services.impl.commands.QueryNameCommand.execute(QueryNameCommand.java:49)
at org.jbpm.shared.services.impl.TransactionalCommandService.execute(TransactionalCommandService.java:71)
at org.jbpm.kie.services.impl.RuntimeDataServiceImpl.getTasksByStatusByProcessInstanceId(RuntimeDataServiceImpl.java:880)
at org.jbpm.services.cdi.impl.RuntimeDataServiceCDIImpl$Proxy$_$$_WeldClientProxy.getTasksByStatusByProcessInstanceId(Unknown Source)
at com.example.MyService.findTaskIdsByProcessInstanceId(MyService.java:135)
...
Caused by: org.hibernate.HibernateException: Found shared references to a collection: org.jbpm.services.task.impl.model.TaskImpl.deadlines.endDeadlines
at org.hibernate.engine.internal.Collections.processReachableCollection(Collections.java:183)
at org.hibernate.event.internal.FlushVisitor.processCollection(FlushVisitor.java:46)
at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:104)
at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:65)
at org.hibernate.event.internal.AbstractVisitor.processValues(AbstractVisitor.java:44)
at org.hibernate.event.internal.AbstractVisitor.processComponent(AbstractVisitor.java:85)
at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:110)
at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:65)
at org.hibernate.event.internal.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:59)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:155)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:216)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:85)
at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:44)
at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1251)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1319)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:87)
at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:606)
at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:483)
... 276 more
2018-05-15 13:36:36,763 ERROR [org.hibernate.AssertionFailure] (default task-2) HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: possible nonthreadsafe access to session
2018-05-15 13:36:36,763 WARN [org.jbpm.services.task.persistence.TaskTransactionInterceptor] (default task-2) Could not commit session: org.hibernate.AssertionFailure: possible nonthreadsafe access to session
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:160)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:582)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:456)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:50)
at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1251)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1319)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:87)
at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:606)
at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:483)
at org.jbpm.services.task.persistence.JPATaskPersistenceContext.queryStringWithParameters(JPATaskPersistenceContext.java:575)
at org.jbpm.services.task.persistence.JPATaskPersistenceContext.queryWithParametersInTransaction(JPATaskPersistenceContext.java:398)
at org.jbpm.services.task.impl.TaskDeadlinesServiceImpl.unschedule(TaskDeadlinesServiceImpl.java:137)
at org.jbpm.services.task.commands.CancelDeadlineCommand.execute(CancelDeadlineCommand.java:71)
at org.jbpm.services.task.commands.CancelDeadlineCommand.execute(CancelDeadlineCommand.java:33)
at org.jbpm.services.task.commands.CompositeCommand.execute(CompositeCommand.java:145)
at org.jbpm.services.task.commands.TaskCommandExecutorImpl$SelfExecutionCommandService.execute(TaskCommandExecutorImpl.java:65)
at org.drools.core.command.impl.AbstractInterceptor.executeNext(AbstractInterceptor.java:41)
at org.jbpm.services.task.persistence.TaskTransactionInterceptor.execute(TaskTransactionInterceptor.java:69)
at org.drools.core.command.impl.AbstractInterceptor.executeNext(AbstractInterceptor.java:41)
at org.drools.persistence.jta.TransactionLockInterceptor.execute(TransactionLockInterceptor.java:73)
at org.drools.core.command.impl.AbstractInterceptor.executeNext(AbstractInterceptor.java:41)
at org.drools.persistence.jpa.OptimisticLockRetryInterceptor.execute(OptimisticLockRetryInterceptor.java:82)
at org.jbpm.services.task.commands.TaskCommandExecutorImpl.execute(TaskCommandExecutorImpl.java:40)
at org.jbpm.services.task.impl.command.CommandBasedTaskService.complete(CommandBasedTaskService.java:177)
at org.jbpm.runtime.manager.impl.task.SynchronizedTaskService.complete(SynchronizedTaskService.java:119)
at org.jbpm.kie.services.impl.UserTaskServiceImpl.complete(UserTaskServiceImpl.java:189)
at org.jbpm.services.cdi.impl.UserTaskServiceCDIImpl$Proxy$_$$_WeldClientProxy.complete(Unknown Source)
at com.example.MyService.completeTask(MyService.java:272)
Resolution
Singleton strategy with JTA transactions (UserTransaction or CMT) would cause hibernate concurrent issues. If outer transaction is required for the application, change the strategy to PerProcessInstance or PerRequest.
Warning
Using the (runtime manager) Singleton strategy with JTA transactions (UserTransaction or CMT) is not recommended because of a race condition. It can result in an IllegalStateException with a message similar to "Process instance X is disconnected".
Avoid this condition by explicitly synchronizing around the KieSession instance when invoking the transaction in the user application code:
synchronized (ksession) {
try {
tx.begin();
// use ksession application logic
tx.commit();
} catch (Exception e) {
...
}
}
The "synchronized" approach is the only workaround if you have to use Singleton + outer transaction. But usually, there is no reason to stick to Singleton.
Diagnostic Steps
- Check RuntimeManager strategy
- Review application source codes to check if an outer transaction is spanned around jBPM API calls
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.