Hello everyone!
I have a problem with multithreaded process execution.
When one process is running then all works correct. But when I start multiple processes (ex. 1 per each 200 milliseconds or 1 per each 1 second - interval isn’t matter) then in logs I see an exception like this:
org.camunda.bpm.engine.OptimisticLockingException: ENGINE-03005 Execution of ‘UPDATE ExecutionEntity[553]’ failed. Entity was updated by another transaction concurrently.
at org.camunda.bpm.engine.impl.db.EnginePersistenceLogger.concurrentUpdateDbEntityException(EnginePersistenceLogger.java:125)
at org.camunda.bpm.engine.impl.db.entitymanager.DbEntityManager.handleOptimisticLockingException(DbEntityManager.java:328)
at org.camunda.bpm.engine.impl.db.entitymanager.DbEntityManager.flushDbOperationManager(DbEntityManager.java:300)
at org.camunda.bpm.engine.impl.db.entitymanager.DbEntityManager.flush(DbEntityManager.java:283)
at org.camunda.bpm.engine.impl.interceptor.CommandContext.flushSessions(CommandContext.java:321)
at org.camunda.bpm.engine.impl.interceptor.CommandContext.close(CommandContext.java:249)
at org.camunda.bpm.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:113)
at org.camunda.bpm.engine.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:42)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
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.ExecuteJobsRunnable.executeJob(ExecuteJobsRunnable.java:79)
at org.camunda.bpm.engine.impl.jobexecutor.ExecuteJobsRunnable.run(ExecuteJobsRunnable.java:57)
at org.springframework.cloud.sleuth.instrument.async.SpanContinuingTraceRunnable.run(SpanContinuingTraceRunnable.java:52)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
My environment
- Database Postgresql 9.6
- Spring-Boot: (v1.5.6.RELEASE)
- Camunda BPM: (v7.5.0)
- Camunda BPM Spring Boot Starter: (v1.3.0)
There are simplified description of a bpmn processes that i used
DataSourceModule.bpmn (2.6 KB) TestProcess.bpmn (4.8 KB).
- Process starts from call in java code
processEngine.getRuntimeService().startProcessInstanceByKey(“TestProcess”, parameters)
Process starts with some variables. that not matter here.
-
When “TestProcess” process has fired, execution checks some information via call diagram “DataSourceModule”.
-
Diagram “DataSourceModule” calls java class DataSourceModule that implements JavaDelegate class. After that execeution stopping until message “moduleResponse” will be recevied.
-
Message “moduleResponse” sends later (usually after 1-5 seconds later) with saving process variables via next code:
RuntimeService runtimeService = processEngine.getRuntimeService(); processEngine.getRuntimeService().setVariables(processInstanceId, variables); ProcessInstance pi = runtimeService .createProcessInstanceQuery() .processInstanceId(processInstanceId) .singleResult(); EventSubscription subscription = runtimeService .createEventSubscriptionQuery() .processInstanceId(pi.getId()) .eventType(MESSAGE_EVENT_TYPE) .singleResult(); if (subscription != null) { runtimeService.messageEventReceived(subscription.getEventName(), subscription.getExecutionId()); }
OptimisticLockingException always occurs in line where I save process variables or where I send event.
There is class that configure camunda for spring
@Slf4j
@Configuration
@RequiredArgsConstructor
public class CamundaConfiguration implements ProcessEnginePlugin {private final ApplicationContext applicationContext; private final CamundaDatasourceConfiguration camundaDatasourceConfiguration; `@Override` public void preInit(ProcessEngineConfigurationImpl config) { config.setJobExecutorActivate(true); config.setDefaultSerializationFormat("application/json"); config.getJobExecutor().setWaitTimeInMillis(500); config.getJobExecutor().setMaxWait(1000); initArtifactFactory(config); config.setDataSource(camundaDatasourceConfiguration.secondaryDataSource()); if (StringUtils.isNotEmpty(camundaDatasourceConfiguration.getSchema())) { config.setDatabaseSchema(camundaDatasourceConfiguration.getSchema()); config.setDatabaseTablePrefix(String.format("%s.", camundaDatasourceConfiguration.getSchema())); } config.setDbHistoryUsed(false); if (config.getHistoryLevels() == null) { config.initHistoryLevel(); } config.setHistoryLevel(HistoryLevel.HISTORY_LEVEL_NONE); log.debug("Camunda configuration: [{}]", config); } private void initArtifactFactory(ProcessEngineConfigurationImpl config) { config.setArtifactFactory(new ArtifactFactory() { final ArtifactFactory defaultArtifactFactory = new DefaultArtifactFactory(); `@Override` public <T> T getArtifact(Class<T> clazz) { T instance; try { instance = applicationContext.getBean(clazz); } catch (NoSuchBeanDefinitionException ex) { // fall back to using newInstance() instance = defaultArtifactFactory.getArtifact(clazz); } return instance; } }); } `@Bean` public ThreadPoolTaskExecutor threadPoolTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(7); executor.setMaxPoolSize(42); executor.setQueueCapacity(11); executor.setThreadNamePrefix("cmd-executor-"); executor.initialize(); return executor; } `@Override` public void postInit(ProcessEngineConfigurationImpl processEngineConfiguration) { log.trace("Call postInit CamundaConfiguration"); } `@Override` public void postProcessEngineBuild(ProcessEngine processEngine) { log.trace("Call postProcessEngineBuild CamundaConfiguration"); }
}
Can someone help me with this problem?