4 Replies Latest reply on Apr 13, 2010 8:51 PM by rebody

    How to provide my own transaction to jBPM?

    helmers

      Hi,

       

      we're using jBPM 4.3, the jBPM tables are part of a bigger database schema, also containing our own tables.

       

      Our transactional service method looks like this:

       

          @Transactional

          public String create(Issue issue) {

              // 1. own stuff

              issueDao.persist(issue);

       

              Map<String, Object> variables = new HashMap<String, Object>();

              variables.put("ISSUE_ID", issue.getId());

       

              // 2. jBPM stuff

              ProcessInstance processInstance = executionService.startProcessInstanceByKey("PROCESS_KEY", variables);

              // 3. jBPM stuff

              List<Task> list = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list();

       

              // ... etc

          }

       

      First we write some stuff to our own tables, then we tell jBPM to start a process. This is all done within one transactional method (I was hoping...).

       

      jbpm.cfg.xml:

      <jbpm-configuration>

          <import resource="jbpm.default.cfg.xml" />

          <import resource="jbpm/tx.hibernate.cfg.xml" />

          <import resource="jbpm.jpdl.cfg.xml" />

      </jbpm-configuration>

       

      tx.hibernate.cfg.xml:

      <jbpm-configuration>

          <process-engine-context>

              <command-service name="txRequiredCommandService">

                  <skip-interceptor />

                  <retry-interceptor />

                  <environment-interceptor />

                  <standard-transaction-interceptor />

              </command-service>

       

              <command-service name="newTxRequiredCommandService">

                  <retry-interceptor />

                  <environment-interceptor policy="requiresNew" />

                  <standard-transaction-interceptor />

              </command-service>

       

              <hibernate-configuration>

                  <!-- Changed file name -->

                  <cfg resource="hibernate.cfg.xml" />

              </hibernate-configuration>

       

              <hibernate-session-factory />

          </process-engine-context>

       

          <transaction-context>

              <transaction />

              <hibernate-session />

          </transaction-context>

      </jbpm-configuration>

       

      The problem...

      The problem is that jBPM creates its own transaction, and does not take part in the transaction started by our own application (as you can see by writing an integration test that succeeds on steps [1] and [2], but uses a mockTaskService to throw an exception at [3] - what you see then is that our own tables are emptied (top-level transaction is rolled-back), but JBPM4_HIST_PROCINST is still filled, in other words [2] is executed in its own transaction and is not rolled back).

       

      I tried to remove the "standard-transaction-interceptor" from tx.hibernate.cfg.xml hoping that jBPM would magically participate in my own transaction, but that doesn't make jBPM very happy.

       

      Does anyone have an idea how I can tell jBPM to use my transaction, instead of starting its own?

       

      I read in the jBPM 4 developer's guide:

      http://docs.jboss.org/jbpm/v4/devguide/html_single/#d0e2216

      that "User provided transasctional resources such as JDBC connections or hibernate connections" is not yet available in jBPM4. I guess this feature is what I need... is it already implemented or in the pipeline? Does anyone know when this feature will be available, or if there is a workaround for it?

       

      This post is related to my earlier post on the fact that jbpm4 does not use the hibernate SessionFactory injected into it:

      https://community.jboss.org/thread/150549?tstart=0

      In the test project attached to that issue, you can also see how transaction management in our application works... Perhaps the problem is solved as soon as the SessionFactory injection issue is solved?

       

      Cheers,

       

      Guido

        • 1. Re: How to provide my own transaction to jBPM?
          rebody

          Hi Guido,

           

            You have two way to make transaction atomicity.

           

            1). You could intergration jBPM4 with Spring, then Spring will manage the whole transaction.

           

            2). You could create a Command, the operatoin in a Command will execute in a transaction that managed by jBPM4.

           

           

            By the way, there is the development forum, you should post these contents in the user forum. Thanks.

          • 2. Re: How to provide my own transaction to jBPM?
            helmers

            Hi Huisheng,

             

            thanks for your reply.

             

            Integration with Spring is not really an option for us; our DI standard is Guice.

             

            Option 2. doesn't sound optimal either because it introduces an ugly dependency on jBPM; ideally we have dependencies on jBPM services but not on the internals (I think the Command is not really part of the jBPM API?). Apart from that we would end up using different transaction mechanisms for service calls that happen to have a dependency on jBPM (they're wrapped in a Command), and services without jBPM dependency (those don't need to be executed in a Command).

             

            I was hoping for a cleaner solution...

             

            Anyway, as for the other issue: https://community.jboss.org/message/537176

            Although I now have got one hibernate SessionFactory shared by my app and jBPM (not sure if this is a proper fix though), things still seem to be running in different transactions. With the standard jbpm.tx.hibernate.cfg.xml (which configures a standard-transaction-interceptor for every command), when I roll back my top-level transaction, the jBPM stuff (executed inside the transaction created by the StandardTransactionInterceptor) is not rolled back.

             

            So what I did was create my own tx.hibernate.cfg.xml, and remove the standard-transaction-interceptors from it. That doesn't really work either (now suddenly calls to "repositoryService.createDeployment().addResourceFromClasspath("myProcess.jpdl.xml").deploy()" seem to not properly insert process definitions in the database; it does insert into JBPM4_DEPLOYMENT, but 3 out of the 4 records from JBPM4_DEPLOYPROP are missing).

             

            Before I dive into the deep, can someone let me know if this is the way to go? What's the way to have jBPM use my own transactions? Should it be possible to remove the standard-transaction-interceptor from the interceptor stack? Or is it strictly forbidden; if so, why?

            • 3. Re: How to provide my own transaction to jBPM?
              swiderski.maciej

              Hi,

               

              are you executing your process inside container?! If so perhaps you could use JTA and enlist both sessions to transaction manager.

               

              jBPM will look up for JTA transaction inside container and if your policy is not REQUIRES_NEW it will execute all its stuff under that transaction.

               

              HTH

              Maciej

              • 4. Re: How to provide my own transaction to jBPM?
                rebody

                Hi Guido,

                  Maciej are right. You could try JTA. It is already provied by jBPM4.