Adding a Timer Intermediate Throw event causes Hibernate issue

Hello,

I am trying to implement a simple model that saves a value to the database, waits for 3 seconds and retrieves the value from the database.

Here is what my model looks like:
diagram_5

The timer is set to duration PT1M

In my SimpleSaveDelegate I have:

class SimpleSaveDeletegate implements JavaDelegate {

    @Override
    void execute(DelegateExecution execution) throws Exception {
        println("Saving to DB")
        SimpleSave simpleSave = new SimpleSave(name: "test")
        simpleSave.save(flush: true, failOnError: true)
        execution.setVariable("dbId", simpleSave.id)
        execution.setVariable("timeNow", System.currentTimeSeconds())
        println("Saved to DB")
    }
}

In my retrieve:

class SimpleSaveRetrieveDelegate implements JavaDelegate {

    @Override
    void execute(DelegateExecution execution) throws Exception {
        println("Retrieving from Database:")
        SimpleSave simpleSave = SimpleSave.get((Long) execution.getVariable("dbId"))
        println((Long) System.currentTimeSeconds() - execution.getVariable("timeNow"))
    }
}

This works fine for me when I do not use the Intermediate Timer Catch Event.

When I add the timer, I get the following stacktrace:

Saving to DB
Saved to DB
Retrieving from Database:
2018-10-30T00:45:12.090Z  ERROR  [org.camunda.bpm.engine.context]  ENGINE-16006 BPMN Stack Trace:
	Task_030y079 (activity-execute, ProcessInstance[5001])
	Task_030y079, name=Simple retrieve from database
	  ^
	  |
	IntermediateThrowEvent_14eosof

2018-10-30T00:45:12.098Z  ERROR  [org.camunda.bpm.engine.context]  ENGINE-16004 Exception while closing command context: Could not obtain current Hibernate Session; nested exception is org.hibernate.HibernateException: No Session found for current thread
org.springframework.dao.DataAccessResourceFailureException: Could not obtain current Hibernate Session; nested exception is org.hibernate.HibernateException: No Session found for current thread
	at org.grails.orm.hibernate.GrailsHibernateTemplate.getSession(GrailsHibernateTemplate.java:227)
	at org.grails.orm.hibernate.GrailsHibernateTemplate.doExecute(GrailsHibernateTemplate.java:183)
	at org.grails.orm.hibernate.GrailsHibernateTemplate.get(GrailsHibernateTemplate.java:256)
	at org.grails.orm.hibernate.AbstractHibernateGormStaticApi.get(AbstractHibernateGormStaticApi.groovy:59)
	at org.grails.datastore.gorm.GormEntity$Trait$Helper.get(GormEntity.groovy:514)

Has anyone encountered this before?

I was able to get past this error by using a new session when retrieving the information from the database like:

class SimpleSaveRetrieveDelegate implements JavaDelegate {

    @Override
    void execute(DelegateExecution execution) throws Exception {
        println("Retrieving from Database:")
        SimpleSave.withNewSession {
            SimpleSave simpleSave = SimpleSave.get((Long) execution.getVariable("dbId"))
        }
        println((Long) System.currentTimeSeconds() - execution.getVariable("timeNow"))
    }
}

But that gives me another stacktrace:

Saving to DB
Saved to DB
Retrieving from Database:
60
2018-10-30T00:51:33.394Z  ERROR  [org.springframework.transaction.support.TransactionSynchronizationUtils]  TransactionSynchronization.beforeCompletion threw exception
org.hibernate.SessionException: Session is closed!
	at org.hibernate.internal.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:133)
	at org.hibernate.internal.SessionImpl.disconnect(SessionImpl.java:467)
	at org.springframework.orm.hibernate4.SpringSessionSynchronization.beforeCompletion(SpringSessionSynchronization.java:122)
	at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCompletion(TransactionSynchronizationUtils.java:106)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCompletion(AbstractPlatformTransactionManager.java:945)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:787)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
	at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:150)
	at org.camunda.bpm.engine.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:40)
	at org.camunda.bpm.engine.impl.interceptor.ProcessApplicationContextInterceptor.execute(ProcessApplicationContextInterceptor.java:66)
	at org.camunda.bpm.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:30)
	at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobHelper.executeJob(ExecuteJobHelper.java:36)
	at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobHelper.executeJob(ExecuteJobHelper.java:29)
	at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobsRunnable.executeJob(ExecuteJobsRunnable.java:88)
	at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobsRunnable.run(ExecuteJobsRunnable.java:57)
	at java.lang.Thread.run(Thread.java:748)
2018-10-30T00:51:33.397Z  ERROR  [org.springframework.transaction.support.TransactionSynchronizationUtils]  TransactionSynchronization.afterCompletion threw exception
org.hibernate.SessionException: Session is closed!
	at org.hibernate.internal.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:133)
	at org.hibernate.internal.SessionImpl.clear(SessionImpl.java:332)
	at org.springframework.orm.hibernate4.SpringSessionSynchronization.afterCompletion(SpringSessionSynchronization.java:143)
	at org.springframework.transaction.support.TransactionSynchronizationUtils.invokeAfterCompletion(TransactionSynchronizationUtils.java:168)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.invokeAfterCompletion(AbstractPlatformTransactionManager.java:1001)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerAfterCompletion(AbstractPlatformTransactionManager.java:976)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.doRollbackOnCommitException(AbstractPlatformTransactionManager.java:919)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:789)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
	at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:150)
	at org.camunda.bpm.engine.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:40)
	at org.camunda.bpm.engine.impl.interceptor.ProcessApplicationContextInterceptor.execute(ProcessApplicationContextInterceptor.java:66)
	at org.camunda.bpm.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:30)
	at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobHelper.executeJob(ExecuteJobHelper.java:36)
	at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobHelper.executeJob(ExecuteJobHelper.java:29)
	at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobsRunnable.executeJob(ExecuteJobsRunnable.java:88)
	at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobsRunnable.run(ExecuteJobsRunnable.java:57)
	at java.lang.Thread.run(Thread.java:748)

Would someone be able to tell me what I am doing wrong or point me in the right direction?

Thank you

Hi,

You may want to share your SimpleSave codeā€¦There is reference to Hibernate session management which is not part of Camunda code and thus must be in your SimpleSaveā€¦ Something is going on within resource management in SimpleSaveā€¦

regards

Rob

Hi @Webcyberrob

Thank you for looking! SimpleSave.groovy is a simple grails domain class. Looks as follows:

class SimpleSave {

    String name

    static constraints = {
        name(nullable: false, blank: false)
    }
}

Thanks,

The exception still looks like a Hibernate exception. Hence it appears that somewhere in your code base you are injecting Hibernate sessions. As I said, Camunda does not use Hibernate, so look through your code to identify where Hibernate transactions are being injectedā€¦

The reason a timer makes a difference is the timer introduces a wait state. Hence the first part of the process will occur in a separate thread of control to the second part. Hence this could explain why the hibernate resource is not available across the different thread contexts.

Have a read of async continuations or wait sates in the user guideā€¦

regards

Rob

1 Like

Thank you @Webcyberrob!
I was using a DataSourceTransactionManager bean for my ProcessEngineConfiguration. I changed this to just use a PlatformTransactionManager and it works fine. I did not have to start a new session either to retrieve information from the database.
I am not entirely sure why this works. I will look into async continuations - but that is in case of errors right?

Thank you for your input.