Hi everyone,
We are executing a Camunda batch process in 4 parallel threads at the same time, sometimes we get the following exception:
2021-10-22 02:10:21.294 ERROR 15934 --- [ calculating-3] org.camunda.bpm.engine.context : ENGINE-16004 Exception while closing command context: null
java.lang.NullPointerException: null
at org.camunda.bpm.engine.impl.batch.BatchEntity.createBatchJobDefinition(BatchEntity.java:279) ~[camunda-engine-7.14.0.jar!/:7.14.0]
at org.camunda.bpm.extension.batch.CustomBatchBuilder.lambda$create$0(CustomBatchBuilder.java:142) [camunda-bpm-custom-batch-core-1.5.1.jar!/:1.5.1]
at org.camunda.bpm.engine.impl.interceptor.CommandExecutorImpl.execute(CommandExecutorImpl.java:28) ~[camunda-engine-7.14.0.jar!/:7.14.0]
at org.camunda.bpm.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:110) ~[camunda-engine-7.14.0.jar!/:7.14.0]
at org.camunda.bpm.engine.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:46) [camunda-engine-spring-7.14.0.jar!/:7.14.0]
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) [spring-tx-5.3.9.jar!/:5.3.9]
at org.camunda.bpm.engine.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:44) [camunda-engine-spring-7.14.0.jar!/:7.14.0]
at org.camunda.bpm.engine.impl.interceptor.ProcessApplicationContextInterceptor.execute(ProcessApplicationContextInterceptor.java:70) [camunda-engine-7.14.0.jar!/:7.14.0]
at org.camunda.bpm.engine.impl.interceptor.CommandCounterInterceptor.execute(CommandCounterInterceptor.java:35) [camunda-engine-7.14.0.jar!/:7.14.0]
at org.camunda.bpm.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:33) [camunda-engine-7.14.0.jar!/:7.14.0]
at org.camunda.bpm.extension.batch.CustomBatchBuilder.create(CustomBatchBuilder.java:133) [camunda-bpm-custom-batch-core-1.5.1.jar!/:1.5.1]
at org.camunda.bpm.extension.batch.CustomBatchBuilder.create(CustomBatchBuilder.java:155) [camunda-bpm-custom-batch-core-1.5.1.jar!/:1.5.1]
at com.opessoftware.fatca.duediligence.service.DueDiligenceServiceBase.customBatchBuilderIndividuals(DueDiligenceServiceBase.java:233) [fatca-duediligence-3.0.0-RELEASE-plain.jar!/:na]
at com.opessoftware.fatca.duediligence.service.DueDiligenceServiceBase.calculateInitialStatusIndividuals(DueDiligenceServiceBase.java:206) [fatca-duediligence-3.0.0-RELEASE-plain.jar!/:na]
at com.opessoftware.fatca.backend.service.CalculationAsyncServiceBasic.calculateIndividuals(CalculationAsyncServiceBasic.java:969) [classes!/:na]
at com.opessoftware.fatca.backend.service.CalculationAsyncServiceBasic.executeCalculationBatchForIndividuals(CalculationAsyncServiceBasic.java:811) [classes!/:na]
at com.opessoftware.fatca.backend.service.CalculationAsyncServiceBasic.executeCalculrationBatch(CalculationAsyncServiceBasic.java:783) [classes!/:na]
at com.opessoftware.fatca.backend.service.CalculationAsyncServiceBasic.calculateAccountHoldersList(CalculationAsyncServiceBasic.java:222) [classes!/:na]
at com.opessoftware.fatca.backend.service.CalculationAsyncServiceBasic$$FastClassBySpringCGLIB$$e76bca01.invoke(<generated>) [classes!/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) [spring-core-5.3.9.jar!/:5.3.9]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) [spring-aop-5.3.9.jar!/:5.3.9]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) [spring-aop-5.3.9.jar!/:5.3.9]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) [spring-aop-5.3.9.jar!/:5.3.9]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) [spring-tx-5.3.9.jar!/:5.3.9]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) [spring-tx-5.3.9.jar!/:5.3.9]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) [spring-tx-5.3.9.jar!/:5.3.9]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) [spring-aop-5.3.9.jar!/:5.3.9]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) [spring-aop-5.3.9.jar!/:5.3.9]
at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115) [spring-aop-5.3.9.jar!/:5.3.9]
at org.springframework.aop.interceptor.AsyncExecutionAspectSupport.lambda$doSubmit$3(AsyncExecutionAspectSupport.java:276) ~[spring-aop-5.3.9.jar!/:5.3.9]
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1604) ~[na:1.8.0_265]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_265]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_265]
at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_265]
2021-10-22 02:10:21.300 ERROR 15934 --- [ calculating-3] c.o.f.b.s.CalculationAsyncServiceBasic : ERROR ID: 9c081d2d-c556-4033-bf9f-3796df157951 | EXCEPTION: NullPointerException | STACKTRACE: [java.lang.NullPointerException
at org.camunda.bpm.engine.impl.batch.BatchEntity.createBatchJobDefinition(BatchEntity.java:279)
at org.camunda.bpm.extension.batch.CustomBatchBuilder.lambda$create$0(CustomBatchBuilder.java:142)
at org.camunda.bpm.engine.impl.interceptor.CommandExecutorImpl.execute(CommandExecutorImpl.java:28)
at org.camunda.bpm.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:110)
at org.camunda.bpm.engine.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:46)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
at org.camunda.bpm.engine.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:44)
at org.camunda.bpm.engine.impl.interceptor.ProcessApplicationContextInterceptor.execute(ProcessApplicationContextInterceptor.java:70)
at org.camunda.bpm.engine.impl.interceptor.CommandCounterInterceptor.execute(CommandCounterInterceptor.java:35)
at org.camunda.bpm.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:33)
at org.camunda.bpm.extension.batch.CustomBatchBuilder.create(CustomBatchBuilder.java:133)
at org.camunda.bpm.extension.batch.CustomBatchBuilder.create(CustomBatchBuilder.java:155)
at com.opessoftware.fatca.duediligence.service.DueDiligenceServiceBase.customBatchBuilderIndividuals(DueDiligenceServiceBase.java:233)
at com.opessoftware.fatca.duediligence.service.DueDiligenceServiceBase.calculateInitialStatusIndividuals(DueDiligenceServiceBase.java:206)
at com.opessoftware.fatca.backend.service.CalculationAsyncServiceBasic.calculateIndividuals(CalculationAsyncServiceBasic.java:969)
at com.opessoftware.fatca.backend.service.CalculationAsyncServiceBasic.executeCalculationBatchForIndividuals(CalculationAsyncServiceBasic.java:811)
at com.opessoftware.fatca.backend.service.CalculationAsyncServiceBasic.executeCalculationBatch(CalculationAsyncServiceBasic.java:783)
at com.opessoftware.fatca.backend.service.CalculationAsyncServiceBasic.calculateAccountHoldersList(CalculationAsyncServiceBasic.java:222)
at com.opessoftware.fatca.backend.service.CalculationAsyncServiceBasic$$FastClassBySpringCGLIB$$e76bca01.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
at org.springframework.aop.interceptor.AsyncExecutionAspectSupport.lambda$doSubmit$3(AsyncExecutionAspectSupport.java:276)
at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1604)
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)
]
Can we know why sometimes is thrown this exception?
It seems like the engine can’t find de custom batch handler by type in the BatchEntity class line:
batchJobHandler = Context.getCommandContext().getProcessEngineConfiguration().getBatchHandlers().get(type);
We going to show the custom batch implementation:
public class CalculationIndividualBatchJobHandler extends CustomBatchJobHandler<BatchAccountHolder> {
private Logger logger = LoggerFactory.getLogger(CalculationIndividualBatchJobHandler.class);
private static final String TYPE = "calculation-individual-batch-handler";
private RuntimeService runtimeService;
private List<BatchAccountHolder> dataProcessed = new ArrayList<>();
@Override
public String getType() {
return TYPE + "-" + Integer.toHexString(hashCode());
}
@Override
public void execute(final List<BatchAccountHolder> data,
@SuppressWarnings("unused") CommandContext commandContext) {
// call engine APIs
data.forEach(batchAccountHolder -> {
String processDefinitionKey = batchAccountHolder.getProcessDefinitionKey();
Individualable individual = batchAccountHolder.getIndividual();
Accountable account = batchAccountHolder.getAccount();
Map<String, Object> variables = batchAccountHolder.getVariables();
this.logger.debug("Initiating camunda process for {}: {} and account: {}", processDefinitionKey,
individual.getId(), account.getId());
try {
// declare new Process Engine Context
ProcessEngineContext.requiresNew();
// call engine APIs
this.runtimeService.startProcessInstanceByKey(processDefinitionKey,
individual.getId() + account.getId(), variables);
} finally {
// clear declaration for new Process Engine Context
ProcessEngineContext.clear();
}
this.logger.debug("Finished camunda process for {}: {} and account: {}", processDefinitionKey,
individual.getId(), account.getId());
});
setDataProcessed(data);
}
}
And this is the way that we set the custom batch to be executed:
CalculationIndividualBatchJobHandler calculationIndividualBatchJobHandler = new CalculationIndividualBatchJobHandler();
calculationIndividualBatchJobHandler.setRuntimeService(this.runtimeService);
// Add the new custom batch handler to the process engine plugin
this.processEngineFactoryBean.getProcessEngineConfiguration().getProcessEnginePlugins()
.add(new CustomBatchHandlerPlugin(calculationIndividualBatchJobHandler));
// Set the batch handlers to custom processEngineConfiguration
this.processEngineFactoryBean.getProcessEngineConfiguration().getBatchHandlers()
.put(calculationIndividualBatchJobHandler.getType(), calculationIndividualBatchJobHandler);
// Set the job handlers to custom processEngineConfiguration
this.processEngineFactoryBean.getProcessEngineConfiguration().getJobHandlers()
.put(calculationIndividualBatchJobHandler.getType(), calculationIndividualBatchJobHandler);
// Execute a custom camunda batch
CustomBatchBuilder.of(batchAccountHolders)
.configuration(this.processEngineFactoryBean.getProcessEngineConfiguration())
.jobHandler(calculationIndividualBatchJobHandler).create();
we hope you can help us find what is generating this error.
Best,
Juan