12 Replies Latest reply on Apr 4, 2010 1:46 PM by tunmang

    jBPM 4.3 starting a sub-process after a state node will fail

    tunmang

      Hi :

       

      I got a db constrain failure when call executionService.signalExecutionById(executionId) for the "check_id" state node as shown below.

       

      ================================

      <?xml version="1.0" encoding="UTF-8"?>
      <process name="SubDocument" xmlns="http://jbpm.org/4.3/jpdl">
        <start g="36,109,48,48">
          <transition to="check_id" >
         <event-listener>
              <field name="msg"><string value="(start) go to state (check_id)."/></field>
            </event-listener>      
          </transition>   
        </start>
        <state name="check_id" g="256,106,88,52" >   
          <transition to="review" g="167,200:7,3">
         <event-listener>
              <field name="msg"><string value="(check_id) go to (sub-process)."/></field>
            </event-listener>         
          </transition>     
        </state>
        <sub-process name="review" sub-process-key="SubProcTasks" g="118,106,99,52">              
          <transition to="ok" g="167,67:6,-19">     
         <event-listener>
              <field name="msg"><string value="(sub-process) go to parent (ok)."/></field>
            </event-listener>      
          </transition>   
        </sub-process>
       
        <state name="ok"     g="255,41,88,52">   
          <transition to="end" g="167,67:6,-19">     
         <event-listener>
              <field name="msg"><string value="(parent-process) go to (end)."/></field>
            </event-listener>
          </transition>           
        </state> 
        <end name="end" g="254,19,88,52" >
          <on event="start">
         <event-listener>
              <field name="msg"><string value="(parent-process) entered (end) node."/></field>
            </event-listener>      
          </on>  
        </end> 
      </process>

       

      ======================

      The exception is listed below:

       

      16:38:55,249 WRN | [JDBCExceptionReporter] SQL Error: 1452, SQLState: 23000

      16:38:55,249 SEV | [JDBCExceptionReporter] Cannot add or update a child row:

      a foreign key constraint fails (`jbpm_4_3/jbpm4_execution`, CONSTRAINT `FK_EXEC_SUBPI` FOREIGN KEY (`SUBPROCINST_`) REFERENCES `jbpm4_execution` (`DBID_`))

       

      ### EXCEPTION ###########################################

      16:38:55,249 SEV | [AbstractFlushingEventListener] Could not synchronize database state with session

      org.hibernate.exception.ConstraintViolationException: could not update: [org.jbpm.pvm.internal.model.ExecutionImpl#240001]

      at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)

      at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)

      at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2425)

      at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2307)

      at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2607)

      at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:92)

      at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)

      at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)

      at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)

      at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)

      at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)

      at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)

      at org.jbpm.pvm.internal.id.AcquireDbidBlockCmd.execute(AcquireDbidBlockCmd.java:35)

      at org.jbpm.pvm.internal.id.AcquireDbidBlockCmd.execute(AcquireDbidBlockCmd.java:10)

      at org.jbpm.pvm.internal.svc.DefaultCommandService.execute(DefaultCommandService.java:42)

      ....

       

      ===============================

      But if I remove the "check_id" state node and make the start node's transition directly go to the sub-process, everything goes fine.

       

      Can someone help me about this one? Thanks a lot in advance.

       

       

       

        • 1. Re: jBPM 4.3 starting a sub-process after a state node will fail
          swiderski.maciej

          Hi,

           

          to me it looks like you have incomplete process definition - you should provide more information into your event listeners, class attribute for instance.

           

          I tried to run your case but deployment fails with:

           

          error: element 'object' must have one of {attribute 'class', attribute 'expr', attribute 'factory' or element 'factory'}: <event-listener xmlns="http://jbpm.org/4.3/jpdl">
                  <field name="msg"><string value="(start) go to state (check_id)."/></field>
          

          If I correct event listener configuration the whole process works fine. I have used my own subprocess.

           

          HTH

          Maciej

          • 2. Re: jBPM 4.3 starting a sub-process after a state node will fail
            tunmang

            Hi Maciej :

             

            Thanks for your help. The event listener is just for my own transition visibility. After I removed all the event listeners in the process definition (as shown below), re-deploy, re-start the process instance. When the "token" reached the state node, I call executionService.signalExecutionById("SimSubProc.290001"), and it throws the same exceptions.

             

            I get the executionService by calling processEngine.getExecutionService(). Is there something I missed ?

             

            The puzzle I cannot figure out is why if I remove the "check_id" state node and make the start node's transition directly go to the sub-process, everything goes fine.

             

            Thanks a lot for your help again.

             

            Tun Mang

             

            =================================

            <?xml version="1.0" encoding="UTF-8"?>
            <process name="SimSubProc" xmlns="http://jbpm.org/4.3/jpdl">
              <start > 
                <transition to="check_id" ></transition>   
              </start>
              <state name="check_id"  >   
                <transition to="review" ></transition>     
              </state>
              <sub-process name="review" sub-process-key="SubProcTasks" >              
                <transition to="ok" ></transition>   
              </sub-process>
             
              <state name="ok" >   
                <transition to="end" ></transition>           
              </state> 
              <end name="end" ></end> 
            </process>

             

            ===================================

            09:03:17,937 INF | [CheckDbCmd] jBPM version info: library[4.3], schema[4.3]

            Process Engine Identity Hash Code: 4781685

            09:03:18,765 WRN | [JDBCExceptionReporter] SQL Error: 1452, SQLState: 23000

            09:03:18,765 SEV | [JDBCExceptionReporter] Cannot add or update a child row: a foreign key constraint fails (`jbpm_4_3/jbpm4_execution`, CONSTRAINT `FK_EXEC_SUBPI` FOREIGN KEY (`SUBPROCINST_`) REFERENCES `jbpm4_execution` (`DBID_`))

            ### EXCEPTION ###########################################

            09:03:18,765 SEV | [AbstractFlushingEventListener] Could not synchronize database state with session

            org.hibernate.exception.ConstraintViolationException: could not update: [org.jbpm.pvm.internal.model.ExecutionImpl#290001]

            at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)

            at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)

            at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2425)

              ....

            at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)

            at org.jbpm.pvm.internal.id.AcquireDbidBlockCmd.execute(AcquireDbidBlockCmd.java:35)

            at org.jbpm.pvm.internal.id.AcquireDbidBlockCmd.execute(AcquireDbidBlockCmd.java:10)

            at org.jbpm.pvm.internal.svc.DefaultCommandService.execute(DefaultCommandService.java:42)

            ....

            at org.jbpm.pvm.internal.svc.ExecutionServiceImpl.signalExecutionById(ExecutionServiceImpl.java:84)

            ... 37 more

            ### EXCEPTION ###########################################

            ### EXCEPTION ###########################################

            09:03:18,781 INF | [DefaultCommandService] exception while executing command org.jbpm.pvm.internal.cmd.SignalCmd@c017e9

            org.jbpm.api.JbpmException: couldn't acquire block of ids

            at org.jbpm.pvm.internal.id.DatabaseDbidGenerator.getNextId(DatabaseDbidGenerator.java:65)

            at org.jbpm.pvm.internal.model.ExecutionImpl.save(ExecutionImpl.java:194)

            at org.jbpm.pvm.internal.model.ExecutionImpl.initializeProcessInstance(ExecutionImpl.java:187)

            at org.jbpm.pvm.internal.model.ProcessDefinitionImpl.createProcessInstance(ProcessDefinitionImpl.java:106)

            at org.jbpm.jpdl.internal.activity.SubProcessActivity.execute(SubProcessActivity.java:70)

            at org.jbpm.pvm.internal.model.op.ExecuteActivity.perform(ExecuteActivity.java:60)

            at org.jbpm.pvm.internal.model.ExecutionImpl.performAtomicOperationSync(ExecutionImpl.java:656)

            at org.jbpm.pvm.internal.model.ExecutionImpl.performAtomicOperation(ExecutionImpl.java:616)

            at org.jbpm.pvm.internal.model.ExecutionImpl.signal(ExecutionImpl.java:417)

            at org.jbpm.pvm.internal.cmd.SignalCmd.execute(SignalCmd.java:61)

            at org.jbpm.pvm.internal.cmd.SignalCmd.execute(SignalCmd.java:35)

            at org.jbpm.pvm.internal.svc.DefaultCommandService.execute(DefaultCommandService.java:42)

            at org.jbpm.pvm.internal.tx.StandardTransactionInterceptor.execute(StandardTransactionInterceptor.java:54)

            at org.jbpm.pvm.internal.svc.EnvironmentInterceptor.executeInNewEnvironment(EnvironmentInterceptor.java:53)

            at org.jbpm.pvm.internal.svc.EnvironmentInterceptor.execute(EnvironmentInterceptor.java:40)

            at org.jbpm.pvm.internal.svc.RetryInterceptor.execute(RetryInterceptor.java:55)

            at org.jbpm.pvm.internal.svc.SkipInterceptor.execute(SkipInterceptor.java:43)

            at org.jbpm.pvm.internal.svc.ExecutionServiceImpl.signalExecutionById(ExecutionServiceImpl.java:84)

            ....

             

            • 3. Re: jBPM 4.3 starting a sub-process after a state node will fail
              swiderski.maciej

              Hi,

               

              I tested it once again and everything seems to work (as unit test).

               

              Attached complete package with process definitions and unit test.

               

              HTH

              Maciej

              • 4. Re: jBPM 4.3 starting a sub-process after a state node will fail
                tunmang

                Hi Maciej :

                 

                Thanks a lot for your sample code. And by that, I finally figured out why my call does not work. The way we call the "deploy process definition", and "start process instance", and "signal execution" is by 3 persons (or 3 stages) to simulate a business facility. So my work is providing a utility for them to execute and call. But your sample code is doing all of them in one-shot (from deploy PD, to signal execution). My utility is like the following and got executed by parameters such as (-deploy, -start, -signal, etc):

                 

                 

                private synchronized void initJbpmEngine()
                  {
                    //
                    // got called when this utility class instantiated.
                    //
                    if (processEngine != null)
                      return;
                    configuration = new Configuration();
                   
                    processEngine = configuration.buildProcessEngine();    
                    out("Process Engine Identity Hash Code: " + System.identityHashCode(processEngine));
                    repositoryService = processEngine.get(RepositoryService.class);
                    executionService  = processEngine.getExecutionService();
                    historyService    = processEngine.getHistoryService();
                    managementService = processEngine.getManagementService();
                    taskService       = processEngine.getTaskService();
                    identityService   = processEngine.getIdentityService();       
                  }
                public void deployProcessDefinition(String fileName)
                {
                  ....
                }

                 

                public void startProcessInstance(String processDefinitionName)

                {

                  ....

                }

                 

                public void signalExecution(String executionId)

                {

                  executionService.signalExecutionById( executionId );

                }

                 

                Once calling those operations in stages, the executionService.signalExecutionById( ... ) will throw the "a foreign key constraint fails" exception. But my problem is I can not find a jBPM API to pass (or fill in) the required information to executionService to execute the  signalExecutionById(...) if we are doing thing in stages.

                 

                Thanks a lot for your help and time in advance again.

                 

                Tun Mang

                • 5. Re: jBPM 4.3 starting a sub-process after a state node will fail
                  swiderski.maciej

                  HI

                   

                  I did the execution like that to test whole flow, so it was just a unit test.

                   

                  What you are describing (at least as far as I understood it) is the normal way jBPM works. If you deploy your process to data base and then execute it via bpm console you will do it in three stages:

                  1. start process - will go to wait state

                  2. signal from wait state - will go to subprocess

                  3. wait state after subprocess execution

                  4. signal from wait state again and go to end node

                   

                  All of them will be triggered separately. I am not sure about your execution context - is it a test case or is it a standalone application or running in a container. Please elaborate a bit or even post you classes so I could test it a bit more.

                   

                  Cheers,

                  Maciej

                  • 6. Re: jBPM 4.3 starting a sub-process after a state node will fail
                    tunmang

                    Hi Maciej:

                     

                    Thanks a lot for your prompt assistance.

                     

                    Attached is our standalone utility application's source code (we're not running from bpm console). Our test results are

                     

                      (1) If run the utility with the following steps, it is OK (the sub-process started OK):

                     

                          %> ....WfeUtility -deploy SubZzA.jpdl.xml

                          %> ....WfeUtility -all SimSubProc

                     

                      (2) But if run it with the following steps, it throws exceptions:

                     

                          %> ....WfeUtility -deploy SubZzA.jpdl.xml

                          %> ....WfeUtility -start SimSubProc

                          %> ....WfeUtility -signal SimSubProc.420001

                     

                    14:59:10,564 SEV | [JDBCExceptionReporter] Cannot add or update a child row:
                    a foreign key constraint fails (`jbpm_4_3/jbpm4_execution`,
                    CONSTRAINT `FK_EXEC_SUBPI` FOREIGN KEY (`SUBPROCINST_`)
                    REFERENCES `jbpm4_execution` (`DBID_`))
                    ### EXCEPTION ###########################################
                    14:59:10,564 SEV | [AbstractFlushingEventListener]
                    Could not synchronize database state with session
                    org.hibernate.exception.ConstraintViolationException:
                    could not update: [org.jbpm.pvm.internal.model.ExecutionImpl#420001]
                    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
                    ......

                     

                    Is it something related to our jBPM's configuration file(s) ? Or something else ? Please remove the package name (at the first line) in my source code when you try it.

                    Thanks a lot in advance.

                     

                    Tun Mang

                    • 7. Re: jBPM 4.3 starting a sub-process after a state node will fail
                      swiderski.maciej

                      hi,

                       

                      I did run your use case and it worked. Only thing is that I created Subprocess since it was not included in the zip file.

                       

                      1. WfeUtility -deploy SubZzA.jpdl.xml (this should return deployment id to have a reference in case of need for clean up)

                      2. WfeUtility -deploy SubProcTasks.jpdl.xml (this should return deployment id  to have a reference in case of need for clean up)

                      3. WfeUtility -start SimSubProc - this should return process instance id

                      ------ so now we have process started and it is in check_id node

                      4. WfeUtility -signal PROC_INST_ID returned by step 3 - this should return process instance id after signal

                      --------- now we are in sub process state1 - here is my simple sub process with just one state within it

                      5. WfeUtility -signal SUBPROCESS_INST_ID - had to look it up in db

                      ---- now we left sub process and went to state ok

                      WfeUtility -signal PROC_INS_ID returned by step 4

                      ----- process is finished

                       

                      Attached is complete set of files of process definitions

                       

                      Cheers,

                      Maciej

                      • 8. Re: jBPM 4.3 starting a sub-process after a state node will fail
                        tunmang

                        Hi Maciej :

                         

                        Because of your working attachment, so I think it is worth of debugging it in my environment this time.

                         

                        So now I run the following command:
                           %> WfeUtility -start SimSubProc
                        In my database, now I have a new data row :
                          DBID_ ... ACTIVITYNAME_ ... ID_                        ... SUBPROCINST_  
                          50001     check_id                  SimSubProc.50001
                        Now I run the following command:
                            %> WfeUtility -signal SimSubProc.50001

                        Now it dumps the following exceptions :

                         

                            10:24:27,736 SEV | [JDBCExceptionReporter] Cannot add or update a child row:

                            a foreign key constraint fails (`jbpm_4_3/jbpm4_execution`, CONSTRAINT

                            `FK_EXEC_SUBPI` FOREIGN KEY (`SUBPROCINST_`) REFERENCES `jbpm4_execution` (`DBID_`))

                         

                            10:24:27,736 SEV | [AbstractFlushingEventListener] Could not synchronize database state with session

                             org.hibernate.exception.ConstraintViolationException: could not update:

                            [org.jbpm.pvm.internal.model.ExecutionImpl#50001]

                         

                        After debug and comment out only one line in "AcquireDbidBlockCmd.java" as shown below :

                         

                            "org.jbpm.pvm.internal.id.AcquireDbidBlockCmd" :

                            ....

                            session.update(property);
                            //  session.flush(); // <-- only comment out here
                            return nextId;
                            ....
                        Now re-run the command "WfeUtility -signal SimSubProc.50001", it works all fine and in my database is :
                          DBID_ ... ACTIVITYNAME_ ... ID_                        ... SUBPROCINST_  
                          50001     check_id                  SimSubProc.50001     60001
                          60001     get-approval              SubProcTasks.60001    
                        So the results of the data rows indicates the exceptions (thrown by session.flush()) are somehow related to when the "SUBPROCINST_" field of data row "50001" wants to refer to ID "60001".
                        So I wonder :
                        (1) There are some patches of fixes for jBPM 4.3 required, but I don't have them in my jBPM ? (did you ever patch your jBPM 4.3 ?)
                        (2) My jbpm.default.cfg.xml has something wrong ? (then how come other 99% of user cases works, only this one does not.)
                        Thanks a lot for your help.
                        Tun Mang
                        • 9. Re: jBPM 4.3 starting a sub-process after a state node will fail
                          rebody

                          Hi Tun,

                           

                            I have tried Maciej's example and also can't see any exception as you said.

                           

                            I went back to see your original Exception again, and found a possibility.

                           

                            When you execute SignalExecutionById() method, pvm invoke the AcquireDbidBlockCmd to get next dbid from Database, it is not happened in my unit test. I think it maybe cause all of above, I will keep digging.

                          • 10. Re: jBPM 4.3 starting a sub-process after a state node will fail
                            rebody

                            Hi Tun,

                             

                              I think I have found the reason of this problem. In fact, I just know the possible reason, still don't know why it appeared.

                             

                              As I said at above, I found in my test case there is no invoking operation to get next id for SUB process. So I guess that because I invoke both startProcessIntanceByKey() and signalExecutionById() methods in the same JVM, the id cache in DatabaseDbidGenerator could supply for both of them.

                             

                              Next step, I seperate these two methods, first invok startProcessInstanceByKey(), then shutdown the jvm and create ProcessEngine again, then invoke signalExecutionById(). At this time I can see AcquireDbidBlockCmd have bean invoked, but there is still no exception occured.

                             

                              Now I can tell the reason that caused this problem. When we use 'sub-process' activity, it will create a ProcessInstance and let it begin to run. This step, the Super ProcessInstance and Sub ProcessInstance will create bi-direction relationship, we should note, at this time, the Sub ProcessInstance still have no ID, so next step pvm will try to generate a id for Sub ProcessInstance. PVM will execute the AcquireDbidBlockCmd to get the next id. It will invoke the DatabaseDbidGenerator to get the next id, DatabaseDbidGenerator at first will check the cache, if the cache still have enough id, it will increment cache and return next id directly. Otherwise it will try to get next id from Database.

                             

                              This is the point, it will create a new session and start a new transaction to do this. So whether it execute flush() won't cause exception. The cause of exception is you are using a same session both outside and inside when DatabaseDbidGenerator try to fetch next id from Database, at that time, outside session still hold Super ProcessInstance and Sub ProcessInstance, and Sub ProcessInstance still have no ID, if the flush() being invoked, hibernate will try to store unsaved Super ProcessInstance and Sub ProcessInstance into Database, but as we know, the Sub ProcessInstance have no ID and can't save in database at this time, So an exception has been thrown.

                             

                              I try this test case in both ProcessEngine and SpringEngine, both of them were successful. So I can tell you that "the default configuration in jBPM distribution is correct." You can find two CommandService in jbpm.tx.hibernate.xml and jbpm.tx.spring.xml. The CommandService named newTxRequiredCommandService is used to create a new session when the DatabaseDbidGenerator try to get next id from database.

                             

                              I guest maybe you ever changed the default configuration and remove the newTxRequiredCommandService, it caused the exception. I suggest you recheck your configuration, make sure there is newTxRequiredCommandService configured correctly. If the problem still can't sovled, you could look for logging to find whether the new session is created normally when DatabaseDbidGenerator try to get next id from Database.

                             

                            cheers.


                            • 11. Re: jBPM 4.3 starting a sub-process after a state node will fail
                              swiderski.maciej

                              Tun Mang wrote:

                              So I wonder :
                              (1) There are some patches of fixes for jBPM 4.3 required, but I don't have them in my jBPM ? (did you ever patch your jBPM 4.3 ?)
                              (2) My jbpm.default.cfg.xml has something wrong ? (then how come other 99% of user cases works, only this one does not.)

                              1. no, I did not patch my jbpm at all, running with default configuration

                              2. it depends if you altered it in any way that could be the issue.

                               

                              Please try what Huisheng wrote. He did a really nice investigation and most likely hit the spot.

                               

                              In case of further issues with it please post your complete configuration set.

                               

                              Cheers,

                              Maciej

                              • 12. Re: jBPM 4.3 starting a sub-process after a state node will fail
                                tunmang

                                Hi Maciej Swiderski and Huisheng Xu :

                                 

                                Thank all of you so much. My problem is finally resolved after changing the settings to "newTxRequiredCommandService" in "jbpm.default.cfg.xml" :

                                 

                                  <process-engine-context>

                                  ....

                                      <object class="org.jbpm.pvm.internal.id.DatabaseIdComposer" init="eager" />
                                      <object class="org.jbpm.pvm.internal.id.DatabaseDbidGenerator">
                                        <field name="commandService">
                                         <ref object="newTxRequiredCommandService" />
                                       </field>
                                     </object>   
                                    <id-generator />
                                  ....
                                  </process-engine-context>
                                Your help is very appreciated.
                                Tun Mang