How to migrate an existing CDI configuration from flowable5?

I have updated our activiti dependency from “5.18” to “flowable-6.4.1”. After changing all imports and generally following https://flowable.org/docs/userguide/migration.html everythings seems to work fine. At least on an empty database.

Last step is to enable flowable5Compatibility and here I’m stuck…

processEngineConfiguration.setFlowable5CompatibilityEnabled(true);

<dependency>
        <groupId>org.flowable</groupId>
        <artifactId>flowable5-compatibility</artifactId>
        <version>${flowable.version}</version>
        <scope>provided</scope>
</dependency>

Error on deployment:

Caused by: org.activiti.engine.ActivitiException: Unsupported process engine configuration
at  xxxx//org.flowable.compatibility.DefaultProcessEngineFactory.buildProcessEngine(DefaultProcessEngineFactory.java:47)

In https://github.com/flowable/flowable-engine/blob/flowable-6.4.1/modules/flowable5-compatibility/src/main/java/org/flowable/compatibility/DefaultProcessEngineFactory.java#L47 it seems that only StandaloneProcessEngineConfiguration is supported. Is that right?

We are using CdiJtaProcessEngineConfiguration.

Ok. I added a custom CompatibilityHandler and now it seems to work:

public class CdiFlowable5CompatibilityHandler extends DefaultFlowable5CompatibilityHandler {

    public CdiFlowable5CompatibilityHandler() {
        this.processEngineFactory = new CdiProcessEngineFactory();
    }

}


public class CdiProcessEngineFactory extends DefaultProcessEngineFactory {

    @Override
    public ProcessEngine buildProcessEngine(ProcessEngineConfigurationImpl flowable6Configuration) {
        org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl flowable5Configuration = null;
        if (flowable6Configuration instanceof CdiJtaProcessEngineConfiguration) {
            flowable5Configuration = new org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration();
            copyConfigItems(flowable6Configuration, flowable5Configuration);
            return flowable5Configuration.buildProcessEngine();
        } else {
            throw new ActivitiException("Unsupported process engine configuration");
        }
    }

}

processEngineConfiguration.setFlowable5CompatibilityHandlerFactory(CdiFlowable5CompatibilityHandler::new);

Is that the indented way to go?

I realized that I have to copy additional config items:

public class JtaProcessEngineFactory extends DefaultProcessEngineFactory {

    @Override
    public ProcessEngine buildProcessEngine(ProcessEngineConfigurationImpl flowable6Configuration) {
        org.activiti.engine.impl.cfg.JtaProcessEngineConfiguration flowable5Configuration = null;
        if (flowable6Configuration instanceof JtaProcessEngineConfiguration) {
            flowable5Configuration = new org.activiti.engine.impl.cfg.JtaProcessEngineConfiguration();
            copyConfigItems(flowable6Configuration, flowable5Configuration);
            copyJtaConfigItems((JtaProcessEngineConfiguration) flowable6Configuration, flowable5Configuration);
            return flowable5Configuration.buildProcessEngine();
        } else {
            throw new ActivitiException("Unsupported process engine configuration");
        }
    }

    private void copyJtaConfigItems(JtaProcessEngineConfiguration flowable6Configuration, org.activiti.engine.impl.cfg.JtaProcessEngineConfiguration flowable5Configuration) {
        flowable5Configuration.setTransactionsExternallyManaged(flowable6Configuration.isTransactionsExternallyManaged());
        flowable5Configuration.setTransactionManager(flowable6Configuration.getTransactionManager());
    }

}

Also I need the right flowable5 process engine. I can only find org.activiti.engine.impl.cfg.JtaProcessEngineConfiguration(). There is no CDI version…

What else can I do?

Is it possible to use flowable5-compatibility with CdiJtaProcessEngineConfiguration?

Any hints?

Current status with my JtaProcessEngineFactory: When executing a v5 process instance at some point I get Cannot resolve identifier 'someNamedBean'

Alright. After some more digging I added a custom flowable5 expression manager:

import org.activiti.engine.impl.el.ExpressionManager;
import org.flowable.cdi.impl.el.CdiResolver;
import org.flowable.common.engine.impl.javax.el.CompositeELResolver;
import org.flowable.common.engine.impl.javax.el.ELResolver;
import org.flowable.variable.api.delegate.VariableScope;

public class CdiFlowable5ExpressionManager extends ExpressionManager {

    @Override
    protected ELResolver createElResolver(VariableScope variableScope) {
        CompositeELResolver elResolver = new CompositeELResolver();
        elResolver.add(super.createElResolver(variableScope));
        elResolver.add(new CdiResolver());
        return elResolver;
    }
}

And add this to the configuration:

processEngineConfiguration.setFlowable5ExpressionManager(new CdiFlowable5ExpressionManager());

Maybe this helps others…

Now it fails with

Caused by: org.flowable.common.engine.impl.javax.el.ELException: java.util.EmptyStackException
 	at org.flowable.common.engine.impl.javax.el.BeanELResolver.invoke(BeanELResolver.java:518)
	at org.flowable.common.engine.impl.javax.el.CompositeELResolver.invoke(CompositeELResolver.java:400)
 	at org.flowable.common.engine.impl.de.odysseus.el.tree.impl.ast.AstMethod.eval(AstMethod.java:98)
...
 Caused by: java.util.EmptyStackException
 	at java.base/java.util.Stack.peek(Stack.java:102)
 	at org.flowable.cdi.impl.context.ExecutionContextHolder.getExecutionContext(ExecutionContextHolder.java:28)
 	at org.flowable.cdi.impl.context.DefaultContextAssociationManager.getExecutionFromContext(DefaultContextAssociationManager.java:223)
 	at org.flowable.cdi.impl.context.DefaultContextAssociationManager.getExecution(DefaultContextAssociationManager.java:192)
 	at org.flowable.cdi.BusinessProcess.getExecution(BusinessProcess.java:470)