添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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:

  • Spring context initialization started
  • ProcessEngineFactoryBean invoked the ProcessEnginrConfiguration.buildProcessEngine() and it invoked the ProcessEngineImpl constructor
  • 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

    max_g:

    Do you guys see any way I can do what I want (start the process engine without invoking any transactionManager-related code)?

    I believe you are out of luck here.

    max_g:

    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?

    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.

    max_g:

    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?

    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.

    max_g:

    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.

    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