cancel
Showing results for 
Search instead for 
Did you mean: 

TransactionManagement and async=true

rene
Champ in-the-making
Champ in-the-making
HI,

we are very puzzled about the transactions in Activiti. While testing we got other results than the documentation suggested when we use activiti:async="true".

By the documentation i understand that every time activiti:async="true" is configured the actual transaction is committed and a new one is created by the jobExecutor, right? That is true if you have two ServiceTask configured. In my test project i faced the following limitation to this behaviour.

1.) activiti:async="true" for a SubProcess is does not lead to a new transaction
2.) If you have more than one ServiceTask with activiti:async="true" in a row this only applies to the first activiti:async="true" configured.

Am I missing something? I hope you can help me on this. I faced the same issue in Version 5.12 and 5.14.

My config does look as follows:

    @Bean
    public SpringProcessEngineConfiguration processEngineConfiguration() {
        final SpringProcessEngineConfiguration engineConfiguration = new SpringProcessEngineConfiguration();
        final DataSource dataSource = activitiDataSource();

        engineConfiguration.setDataSource(dataSource);
        engineConfiguration.setTransactionManager(transactionManager);
        engineConfiguration.setDatabaseSchemaUpdate("drop-create");
        engineConfiguration.setJobExecutorActivate(true);

        return engineConfiguration;
    }

where the transaction manager is used for Activiti and my application db.

When needed I can provide a test project to verify my result.

Any help will be appreciate! thanks in advance,

Rene
3 REPLIES 3

martin_grofcik
Confirmed Champ
Confirmed Champ
Hi Rene.

Could you attach jUnit test (or project) please?

Regards
Martin

rene
Champ in-the-making
Champ in-the-making
Hi Martin,

thanks for you reply, I have created a simple project thats demonstrates the second "async" in a row issue. I hope you can help us with this issue.

If you have any questions about the project, let me know.

Thanks a lot,

Rene

PS: since i can attach only txt files, i added the extension to txt. 🙂

martin_grofcik
Confirmed Champ
Confirmed Champ
Hi Rene,

Thank you for very clearly defined problem.

I had a look on the de.wps.activiti.process.TransactionExceptionThrowingProcessTest2Async#transactionManagementTest test.
I found that there is no wait to finish asynchronous tasks. I changed test little bit.

@Test
@Deployment(resources = { PROCESS_BPMN })
public void transactionManagementTest() throws Exception {
  try {
   runtimeService.startProcessInstanceByKey(PROCESS_KEY, key);
  } catch (Exception ex) {
   LOGGER.error("#### Catched exception ####", ex);
  }
               TimeUnit.SECONDS.sleep(15);
  assertThat(countHistoricProcessesByBusinessKey(key), is(1L));
  List<Foo> findAll = fooRepository.findAll();
  assertThat(findAll, containsInAnyOrder(hasProperty("bar", is("FooBar1")), hasProperty("bar", is("FooBar2"))));

  assertThat(findAll.size(), is(2));
}

TimeUnit.SECONDS.sleep(15) waits for job executor to process all jobs. JobExecutor is invoked periodically, that's why we have to wait on it to be executed. 
There is 3 times retry set by default. That's why jobexecutor tries 3 times to execute changeDBValueTo3
Wait can be done in more elegant way - activiti tests use

  public void waitForJobExecutorToProcessAllJobs(long maxMillisToWait, long intervalMillis) {
    JobExecutor jobExecutor = processEngineConfiguration.getJobExecutor();
    jobExecutor.start();

    try {
      Timer timer = new Timer();
      InteruptTask task = new InteruptTask(Thread.currentThread());
      timer.schedule(task, maxMillisToWait);
      boolean areJobsAvailable = true;
      try {
        while (areJobsAvailable && !task.isTimeLimitExceeded()) {
          Thread.sleep(intervalMillis);
          try {
            areJobsAvailable = areJobsAvailable();
          } catch(Throwable t) {
            // Ignore, possible that exception occurs due to locking/updating of table on MSSQL when
            // isolation level doesn't allow READ of the table
          }
        }
      } catch (InterruptedException e) {
        // ignore
      } finally {
        timer.cancel();
      }
      if (areJobsAvailable) {
        throw new ActivitiException("time limit of " + maxMillisToWait + " was exceeded");
      }

    } finally {
      jobExecutor.shutdown();
    }
  }

Please let me know whether it helps.

Regards
Martin