Skip to content

Commit

Permalink
Don't run call-activities asynchronously
Browse files Browse the repository at this point in the history
  • Loading branch information
stephanpelikan committed Sep 19, 2023
1 parent 68df160 commit 5a8b9dc
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.vanillabp.camunda7.deployment.Camunda7DeploymentAdapter;
import io.vanillabp.camunda7.service.Camunda7ProcessService;
import io.vanillabp.camunda7.service.jobs.startprocess.StartProcessJobHandler;
import io.vanillabp.camunda7.wiring.Camunda7AdapterProperties;
import io.vanillabp.camunda7.wiring.Camunda7TaskWiring;
import io.vanillabp.camunda7.wiring.Camunda7TaskWiringPlugin;
Expand All @@ -28,11 +29,10 @@
import org.springframework.context.annotation.Lazy;
import org.springframework.data.repository.CrudRepository;

import javax.annotation.PostConstruct;
import java.math.BigInteger;
import java.util.function.Function;

import javax.annotation.PostConstruct;

@AutoConfigurationPackage(basePackageClasses = Camunda7AdapterConfiguration.class)
@AutoConfigureBefore(CamundaBpmAutoConfiguration.class)
@EnableProcessApplication("org.camunda.bpm.spring.boot.starter.SpringBootProcessApplication")
Expand Down Expand Up @@ -207,5 +207,11 @@ public <DE> Camunda7ProcessService<?> newProcessServiceImplementation(
return result;

}


@Bean
public StartProcessJobHandler startProcessJobHandler() {

return new StartProcessJobHandler();
}

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package io.vanillabp.camunda7.service;

import io.vanillabp.camunda7.Camunda7AdapterConfiguration;
import io.vanillabp.camunda7.service.jobs.startprocess.StartProcessCommand;
import io.vanillabp.springboot.adapter.AdapterAwareProcessService;
import io.vanillabp.springboot.adapter.ProcessServiceImplementation;
import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.exception.NullValueException;
import org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEventPublisher;
Expand Down Expand Up @@ -51,7 +53,7 @@ public Camunda7ProcessService(
this.isNewEntity = isNewEntity;
this.getWorkflowAggregateId = getWorkflowAggregateId;
this.parseWorkflowAggregateIdFromBusinessKey = parseWorkflowAggregateIdFromBusinessKey;

}

@Override
Expand Down Expand Up @@ -139,16 +141,20 @@ public DE startWorkflow(
.toString();

wakeupJobExecutorOnActivity();

processEngine
.getRuntimeService()
.createProcessInstanceByKey(parent.getPrimaryBpmnProcessId())
.businessKey(id)
.processDefinitionTenantId(parent.getWorkflowModuleId())
.execute();

return workflowAggregateRepository
.save(attachedAggregate);

// Start workflow asynchronously by Camunda's job-executor
// Hint: this is not done by setting "async-before" on the start-event
// since we don't know which process is used as a call-activity which
// has to be started synchronously.
((ProcessEngineConfigurationImpl) processEngine
.getProcessEngineConfiguration())
.getCommandExecutorTxRequired()
.execute(new StartProcessCommand(
parent.getWorkflowModuleId(),
parent.getPrimaryBpmnProcessId(),
id));

return attachedAggregate;

}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package io.vanillabp.camunda7.service.jobs.startprocess;

import org.camunda.bpm.engine.impl.interceptor.Command;
import org.camunda.bpm.engine.impl.interceptor.CommandContext;
import org.camunda.bpm.engine.impl.persistence.entity.MessageEntity;

public class StartProcessCommand implements Command<String> {

static final String TYPE = "VBP_StartProcess";

private final StartProcessJobHandlerConfiguration configuration;

public StartProcessCommand(
final String workflowModuleId,
final String bpmnProcessId,
final String businessKey) {

this.configuration = new StartProcessJobHandlerConfiguration(
workflowModuleId,
bpmnProcessId,
businessKey);

}

@Override
public String execute(
final CommandContext commandContext) {

final var entity = new MessageEntity();

entity.init(commandContext);
entity.setJobHandlerType(TYPE);
entity.setJobHandlerConfiguration(configuration);

commandContext.getJobManager().send(entity);

return entity.getId();

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.vanillabp.camunda7.service.jobs.startprocess;

import org.camunda.bpm.engine.impl.interceptor.CommandContext;
import org.camunda.bpm.engine.impl.jobexecutor.JobHandler;
import org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity;
import org.camunda.bpm.engine.impl.persistence.entity.JobEntity;

import java.util.regex.Pattern;

public class StartProcessJobHandler implements JobHandler<StartProcessJobHandlerConfiguration> {

private static final Pattern SPLITTER = Pattern.compile("([^\n]+)\n([^\n]+)\n(.*)");

@Override
public String getType() {
return StartProcessCommand.TYPE;
}

@Override
public void execute(
final StartProcessJobHandlerConfiguration configuration,
final ExecutionEntity execution,
final CommandContext commandContext,
final String tenantId) {

commandContext
.getProcessEngineConfiguration()
.getProcessEngine()
.getRuntimeService()
.createProcessInstanceByKey(configuration.getBpmnProcessId())
.businessKey(configuration.getBusinessKey())
.processDefinitionTenantId(configuration.getWorkflowModuleId())
.execute();

}

@Override
public StartProcessJobHandlerConfiguration newConfiguration(
final String canonicalString) {

if (canonicalString == null) {
return null;
}

final var splitter = SPLITTER.matcher(canonicalString);
if (!splitter.matches()) {
return null;
}

return new StartProcessJobHandlerConfiguration(
splitter.group(1),
splitter.group(2),
splitter.group(3));

}

@Override
public void onDelete(
final StartProcessJobHandlerConfiguration configuration,
final JobEntity jobEntity) {
// nothing to do
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package io.vanillabp.camunda7.service.jobs.startprocess;

import org.camunda.bpm.engine.impl.jobexecutor.JobHandlerConfiguration;

public class StartProcessJobHandlerConfiguration implements JobHandlerConfiguration {

private final String businessKey;

private final String workflowModuleId;

private final String bpmnProcessId;

public StartProcessJobHandlerConfiguration(
final String workflowModuleId,
final String bpmnProcessId,
final String businessKey) {

this.businessKey = businessKey;
this.workflowModuleId = workflowModuleId;
this.bpmnProcessId = bpmnProcessId;

}

@Override
public String toCanonicalString() {

return workflowModuleId + "\n" + bpmnProcessId + "\n" + businessKey;

}

public String getWorkflowModuleId() {
return workflowModuleId;
}

public String getBpmnProcessId() {
return bpmnProcessId;
}

public String getBusinessKey() {
return businessKey;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -465,12 +465,20 @@ private void resetAsyncBeforeAndAsyncAfter(

@Override
public void parseStartEvent(
final Element element,
final Element startElement,
final ScopeImpl scope,
final ActivityImpl activity) {

resetAsyncBeforeAndAsyncAfter(element, activity, Async.SET_ASYNC_BEFORE_ONLY);


final var isEventBasedStartEvent = startElement.element("messageEventDefinition") != null;
if (isEventBasedStartEvent) {
resetAsyncBeforeAndAsyncAfter(startElement, activity, Async.SET_ASYNC_BEFORE_ONLY);
} else {
// plain start events need to be handled synchronously in cases of call-activities.
// in cases of starting an independent process the Camunda7ProcessService is
// responsible for running this asynchronously.
removeAsyncBeforeAndAsyncAfter(startElement, activity);
}

}

@Override
Expand Down

0 comments on commit 5a8b9dc

Please sign in to comment.