Sync process start behaviour in process engine

I want to start with assumptions. As far as I know flowable 5 engine was first having only sync process execution and because of the bottlenecks async process execution is also added to framework. Since the results from the async process execution was much way better than the sync execution, flowable 6 engine is only using async process execution now.

I write a spring-boot application has only one responsibility which is starting a process via the down call.

runtimeService.startProcessInstanceById

The problem is, I am having some custom beans in the process definition and when I start the process, process engine is expecting these custom beans in the class path of the my spring boot app that started the process and if they dont exist in the classpath I am getting exception as you all expect. I put a timer job which is 30 sec after the start node of process definition and set flowable.async-executor-activate flag to false and I saw that this time process is executed by the task-service(which has all custom beans) and I didn’t get any exception about the missing custom beans in classpath.

However It is said that there is no sync behavior in flowable 6 engine, I believe that process is starting in sync behavior and then switching to async mode. I need to be sure about this because I want to know where to deploy my custom beans and I dont want to deploy my all custom beans to every flowable instance. Can you guys englighten me about this issue :slight_smile:

Thanks.

No, that assumption is incorrect. in v5 and v6, whether to make something async has always been a choice when creating the process model: you can say in a fine-grained way which steps needs to be asyc and which shouldn’t.

But I assume you’re talking about the async executor (for async steps in a process)?

I’m reading from this that you don’t have the same classpath everywhere?

What seems to be happening is that the nodes where you have async steps have a need for certain classes on the classpath. For Spring Boot, the default is indeed to activate the async executor: flowable-engine/modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/FlowableProperties.java at main · flowable/flowable-engine · GitHub

Hi @joram,

I am aware of the things you have mentioned in your post. What I want to achieve is whether my process model has async or sync execution steps, I want that process to be executed on a particular flowable instance. Since flowable-task, even flowable-rest and my custom spring-boot applications(which have flowable-spring-boot-starter as dependency) have process engine in their classpath, all engines race to execute that particular process. I tried to set asyncExecutorActivate to false that you mentioned in your post and what I saw is if a process definition has a sync step(which is my custom bean) it still tries to execute that step, that parameter is effective only if a step is async.

I just want one and only one instance(which is flowable-task and have my custom beans in its class path) to execute a process because this will help me to deploy my custom beans to only one instance. How can I dictate a flowable instance to not execute a process?

Thanks.

Typically, you’d have a different database for that particular engine (or multiple engines).

The async executor indeed only applies for async steps. I assumed your goal was to execute async steps on a different instance? But if they still interfere with each other, doesn’t that mean that some sync steps should be async (or vice-versa) depending on what classpath?

Thanks @joram for your explanations. I think my problem seems to be a bug.

I defined some of my custom tasks in stencilset and I have my own stencilsetX.json.

The problem is; I defined my ServiceTask in my XTaskJsonConverter.java as asynchrous by simply setting task.setAsynchrous(true) but after I debug the source code I see that in ContinueProcessOperation class at this line

else if (forceSynchronousOperation || !flowNode.isAsynchronous()) {
executeSynchronous(flowNode);

Here,

flowNode.isAsynchronous()

returns false and thus that element is being executed synchrous .Since this ServiceTask is the first element after the startEvent, engine whichs starts the process was expecting that ServiceTask class to be in the class path.

I solved this problem by modifying my stencilSetX.json by using asynchronousdefinitionpackage in that service task which means I forced it to be async.

But in my point of view, if I set asynchrous flag of that ServiceTask in my java code as true it should run async, whether I define it in stencilsetX.json or not.

May be this can be a improvement.

That indeed explains what you’re seeing wrt classpath.

Agreed and in fact, it should. The converter converts json (which gets properties from the stencilset) to java and then later that gets converted to deployable xml. So in theory setting it in the converter should override any stencilset settings.

Do you maybe can post a bit of your converter code?

@joram

public class MyCompanyCustomVaultGetValueTaskJsonConverter extends BaseBpmnJsonConverter{

    public static void fillTypes(Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap, Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap) {

        fillJsonTypes(convertersToBpmnMap);
        fillBpmnTypes(convertersToJsonMap);
    }

    public static void fillJsonTypes(Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap) {

    	
        convertersToBpmnMap.put(STENCIL_VAULTGETVALUETASK, MyCompanyCustomVaultGetValueTaskJsonConverter.class);
    }

    public static void fillBpmnTypes(Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap) {
    }

    @Override
    protected String getStencilId(BaseElement baseElement) {
        return STENCIL_VAULTGETVALUETASK;
    }

    @Override
    protected void convertElementToJson(ObjectNode propertiesNode, BaseElement baseElement) {
        // done in service task
    }

    @Override
    protected FlowElement convertJsonToElement(JsonNode elementNode, JsonNode modelNode, Map<String, JsonNode> shapeMap) {
        ServiceTask task = new ServiceTask();
        task.setType("CustomVaultGetValue");
        task.setAsynchronous(true);
        addField("key", PROPERTY_VAULTTASKKEY, elementNode, task);
        addField("resultvariable", PROPERTY_VAULTTASKRESULTVARIABLE, elementNode, task);
        task.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_CLASS);

        task.setImplementation("com.mycompany.robot.vault.VaultGetValueTask");
        return task;
    }

}

Thanks, now it’s clear. The reason is that the superclass BaseBpmnJsonConverter changes the asynchronous after calling your #convertJsonToElement method. See https://github.com/flowable/flowable-engine/blob/master/modules/flowable-json-converter/src/main/java/org/flowable/editor/language/json/converter/BaseBpmnJsonConverter.java#L323 where it gets set.

One way to work around it is to add the asynchronous property in the JsonNode elementNode that gets passed and is read in the superclass later:

activity.setAsynchronous(getPropertyValueAsBoolean(PROPERTY_ASYNCHRONOUS, elementNode));

If that elementNode has true, you don’t need to add the package to the stencilset.