Spring integration problem

Hi guys,
I faced the following problems while I was trying to integrate Camunda engine into my application.
I have a String application, so I added the following bean definitions into my spring config:

<bean id="processEngineConfiguration" class="org.camunda.bpm.engine.spring.SpringProcessEngineConfiguration">
    <property name="dataSource" ref="cubaDataSource"/>
    <property name="transactionManager" ref="transactionManager"/>
     <property name="databaseSchemaUpdate" value="false" />
    <property name="jobExecutorActivate" value="false" />
</bean>

<bean id="processEngine" class="org.camunda.bpm.engine.spring.ProcessEngineFactoryBean">
    <property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>

<bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />

I used existing datasource and transaction manager instances. When I started the application, the following happened:

  1. Spring context initialization started
  2. ProcessEngineFactoryBean invoked the ProcessEnginrConfiguration.buildProcessEngine() and it invoked the ProcessEngineImpl constructor
  3. Inside this constructor there are several operations that start spring transaction. That was the problem, because in my application an ORM listener is invoked on transaction start, and this listener expects that Spring context is fully initialized.

So I tried to fix it. The first idea was to create my own implementation of the ProcessEngine interface that doesn’t invoke any transaction releated code in the constructor, but does it later when Spring context is started. But I could not just implement the intarface because inside the engine you use not the interface (ProcessEngine), but its implementation (ProcessEngineImpl).

It turned out that my version of the ProcessEngine should extend the ProcessEngineImpl, but here I faced another problem: ProcessEngineImpl doesn’t have a default constructor, so I couldn’t override the init behavior.

As a result, in my app I cannot modify the ProcessEngine in the way I need and cannot use Spring integration.

Do you guys see any way I can do what I want (start the process engine without invoking any transactionManager-related code)? Of course, I could do it programmatically, but it would be great to be able to inject camunda services into other application beans.
Do you maybe have any plans to clean up the code and use ProcessEngine interface instead of implementation (ProcessEngineImpl) in the framework? Or just provide a default constructor in the ProcessEngineImpl?

Regards, Max

I believe you are out of luck here.

We only add (and test) code that contributes to API features. Freely instantiating ProcessEngineImpl and reimplementing the ProcessEngine interface are currently not features that we provide or plan to provide. So I believe your options are programmatic engine startup or trying to lift/work around the ORM listener’s restriction.

Thank you for the answer.

As I understand, with programmatic engine startup I will not be able to leverage Spring integration (transactions shared between the application and the process engine, ability to use application bean inside the process, etc.). Is this correct?

If there was a default non-argument constructor in the ProcessEngineImpl, it would solve my problem. I would have a MyProcessEngineImpl class:

public class MyProcessEngineImpl extends ProcessEngineImpl {
    public MyProcessEngineImpl(ProcessEngineConfigurationImpl processEngineConfiguration) {
        //here I will not execute the code, that makes my application fail
        //e.g. executeSchemaOperations() or cleaning up the history. I'll do it later
    }
}

An overriden version of the SpringProcessEngineConfiguration would create an instance of MyProcessEngineImpl:

public class MySpringProcessEngineConfiguration extends SpringProcessEngineConfiguration {
    @Override
    public ProcessEngine buildProcessEngine() {
        init();
        processEngine = new MyProcessEngineImpl(this);
        invokePostProcessEngineBuild(processEngine);
        return processEngine;
    }
    //...
}

And then I would just register the MySpringProcessEngineConfiguration:

<bean id="processEngineConfiguration" class="com.myapp.engine.MySpringProcessEngineConfiguration">
   <property name="dataSource" ref="myDataSource"/>
   <property name="transactionManager" ref="myTransactionManager"/>
</bean>

I tried this solution and it worked, but to achieve this I had to fork the camunda engine and build the patched version with the only modification: a non-argument constructor in the ProcessEngineImpl. But I don’t want to support a fork just because of this. That’s why I asked, whether you consider adding the non-argument constructor to the code. It wouldn’t break anything, but would allow instantiating modified versions of the ProcessEngine.

Sure you can. Just make sure to build the process engine after the Spring context is created, instantiate SpringProcessEngineConfiguration and invoke the relevant setters for application context, data source and transaction manager.

I’m very hesitant to do this as it does not seem to make sense outside of this very narrow use case. But as I am not in the team that maintains the codebase, this is not up to me to decide. Feel free to raise a pull request to camunda-bpm-platform with your changes.

Cheers,
Thorben

Yes, you’re right. That works. Thank you!