4 Replies Latest reply on May 27, 2010 11:40 AM by swiderski.maciej

    Subprocess wait state signal handling not working from parent process (jBPM 4.3)

      Following is our main jPDL xml

       

      <?xml version="1.0" encoding="UTF-8"?>

       

       

      <process name=

      "PresenceWorkflow" xmlns="http://jbpm.org/4.3/jpdl">

       

      <start g="-9,225,80,40">

       

      <transition to="wait for presence of user" />

       

      </start>

       

       

      <sub-process name="wait for presence of user" sub-process-key="waitForPresence" g="603,195,177,70">

       

      <parameter-in subvar="userDetailsInstance" var="user"/>

      <parameter-in subvar="timeoutPeriod" var="timeoutPeriodMain"/>

       

      <parameter-out subvar="userDetailsInstance" var="user"/>

      <parameter-out subvar="subinstanceid" var="subinstanceidMain"/>

       

       

      <transition name="timeout" to="state1" g="-47,-20"/>

       

      <transition name="success" to="state1" g="369,51:-28,-24"/>

       

      </sub-process>

       

      <end g="220,486,48,48" name="end1"/>

       

      <end-error g="140,488,80,40" name="internal error"/>

       

       

       

      <state g="649,418,92,52" name="state1" state="naas-wait">

       

      </state>

      </process>

       

       

       

       

      xml version="1.0" encoding="UTF-8"?>

       

      <

       

      process name="waitForPresence" xmlns=http://jbpm.org/4.3/jpdl>

       

      <

       

      start g="8,103,80,40">

       

       

           <transition to="wait for presence"/>

      </

       

      start>

       

       

      <

       

      custom class="com.task.WaitForPresenceTask" g="121,105,100,52" name="wait for presence">

       

       

       

      <transition to="task completion check for wait presnce"/>

      </

       

      custom>

       

      <

       

      decision expr="#{TaskCompletionStatus}" name="task completion check for wait presence" g="287,117,110,92">

       

       

      <transition name="Success" to="wait for presence update" g="-46,-20"/>

       

       

      <transition name="Failure" to="failure" g="-40,-20"/>

      </

       

      decision>

       

      <

       

      state name="wait for presence update" g="482,114,210,40">

       

       

      <on event="timeout">

       

       

      <timer duedate="5 seconds"/>

       

       

      <event-listener class="com.task.WaitStateTimeoutListener">

       

       

      </on>

       

       

       

       

      <on event="start">

       

       

      <event-listener class="com.eventlistener.WaitForPresenceStartEventListener">

       

       

      <field name="subscriberVariableName"><object expr="#{userDetailsInstance}"/></field>

       

       

      </event-listener>

       

       

      </on>

       

       

       

      <on event="end">

       

       

      <event-listener class="com.eventlistener.WaitForPresenceCompletionEndEventListener">

       

       

      <field name="subscriberVariableName"><object expr="#{userDetailsInstance}"/></field>

       

       

      </event-listener>

       

       

      </on>

       

       

      <transition name="WAIT_STATE_TIMED_OUT" to="timeout" g="-142,-20"/>

       

       

      <transition name="AVAILABLE" to="test" g="-64,-9"/>

       

      </

       

      state>

       

       

      <

       

      end name="success" g="666,410,80,40"/>

      <end name="failure" g="277,415,80,40"/>

      <

       

      end name="timeout" g="445,414,48,84"/>

       

      </

       

      process>

       

      Sample test case extract:

       

      // start the main process

      final ProcessInstance processInstance =   executionService.startProcessInstanceByKey("PresenceWorkflow", variables,processInstanceKey);

       

      //  send signal to  subprocess to get out of "wait for presence update" state.

      executionService.signalExecutionById(processInstance.getId(),"AVAILABLE");

       

      Problem faced:

       

      1) Once execution resumes after sending the above signal workflow exists the subprocess without executing any subsequent tasks. For example, the end event listener is not invoked.

       

      2) Unable to get the subprocess execution id. Even if we get the execution id via a hack, we get an exception sending the signal.

       

      Any help would be very much appreciated.

      Following is the subprocess jPDL

        • 1. Re: Subprocess wait state signal handling not working from parent process (jBPM 4.3)
          swiderski.maciej

          Hi,

           

          In general, you need to signal sub process execution using its id instead of signaling main process. Unfortunately there is no API way to get hold of sub process instance but you can do this casting to ExecutionImpl:

           

          ((ExecutionImpl)processInstance).getSubProcessInstance()
          

           

          Then use this process instance when signaling. You can find working example in attachment.

           

          BTW, next time please attach your complete process definition with all custom classes (for custom activity, event listeners, etc) and a test case. Will make it easier and faster for others to look into your case.

           

          P.S.

          Will create issue in jira to provide a way to get hold of sub process instance.

           

          HTH
          Maciej

          • 2. Re: Subprocess wait state signal handling not working from parent process (jBPM 4.3)

            Thanks...it worked.Your example code was of great help.

            • 3. Re: issue with event timer inside the subprocess.

              In the same subprocess as above we are trying to use timer as well but as soon as the timer is added in subprocess xml i get following error irrespective of whether signal to the activity in subprocess(from main process) is given before or after timer due time(I am making the parent execution thread to sleep so as to signal execute whithin/after timer fire time).:-

               

              May 27, 2010 7:23:30 PM org.hibernate.util.JDBCExceptionReporter logExceptions

              WARNING: SQL Error: 2292, SQLState: 23000

              May 27, 2010 7:23:30 PM org.hibernate.util.JDBCExceptionReporter logExceptions

              SEVERE: ORA-02292: integrity constraint (JBPM.FK_EXEC_SUBPI) violated - child record found

               

              May 27, 2010 7:23:30 PM org.hibernate.event.def.AbstractFlushingEventListener performExecutions

              SEVERE: Could not synchronize database state with session

              org.hibernate.exception.ConstraintViolationException

               

              : could not delete: [org.jbpm.pvm.internal.model.ExecutionImpl#46]

              at org.hibernate.exception.SQLStateConverter.convert(

              SQLStateConverter.java:94)

              at org.hibernate.exception.JDBCExceptionHelper.convert(

              JDBCExceptionHelper.java:66)

              at org.hibernate.persister.entity.AbstractEntityPersister.delete(

              AbstractEntityPersister.java:2569)

              at org.hibernate.persister.entity.AbstractEntityPersister.delete(

              AbstractEntityPersister.java:2725)

              at org.hibernate.action.EntityDeleteAction.execute(

              EntityDeleteAction.java:97)

              at org.hibernate.engine.ActionQueue.execute(

              ActionQueue.java:279)

              at org.hibernate.engine.ActionQueue.executeActions(

              ActionQueue.java:263)

              at org.hibernate.engine.ActionQueue.executeActions(

              ActionQueue.java:172)

              at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(

              AbstractFlushingEventListener.java:321)

              at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(

              DefaultAutoFlushEventListener.java:64)

              at org.hibernate.impl.SessionImpl.autoFlushIfRequired(

              SessionImpl.java:996)

              at org.hibernate.impl.SessionImpl.list(

              SessionImpl.java:1141)

              at org.hibernate.impl.QueryImpl.list(

              QueryImpl.java:102)

              at org.jbpm.pvm.internal.hibernate.DbSessionImpl.deleteProcessDefinitionHistory(

              DbSessionImpl.java:168)

              at org.jbpm.pvm.internal.cmd.DeleteDeploymentCmd.execute(

              DeleteDeploymentCmd.java:78)

              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.repository.RepositoryServiceImpl.deleteDeploymentCascade(

              RepositoryServiceImpl.java:73)

              at org.jbpm.test.JbpmTestCase.deleteRegisteredDeployments(

              JbpmTestCase.java:166)

              at org.jbpm.test.JbpmTestCase.tearDown(

              JbpmTestCase.java:95)

              at junit.framework.TestCase.runBare(

              TestCase.java:140)

              at junit.framework.TestResult$1.protect(

              TestResult.java:110)

              at junit.framework.TestResult.runProtected(

              TestResult.java:128)

              at junit.framework.TestResult.run(

              TestResult.java:113)

              at junit.framework.TestCase.run(

              TestCase.java:124)

              at junit.framework.TestSuite.runTest(

              TestSuite.java:232)

              at junit.framework.TestSuite.run(

              TestSuite.java:227)

              at org.junit.internal.runners.JUnit38ClassRunner.run(

              JUnit38ClassRunner.java:79)

              at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(

              JUnit4TestReference.java:46)

              at org.eclipse.jdt.internal.junit.runner.TestExecution.run(

              TestExecution.java:38)

              at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(

              RemoteTestRunner.java:467)

              at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(

              RemoteTestRunner.java:683)

              at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(

              RemoteTestRunner.java:390)

              at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(

              RemoteTestRunner.java:197)

              Caused by:

              java.sql.SQLException: ORA-02292: integrity constraint (JBPM.FK_EXEC_SUBPI) violated - child record found

               

              at oracle.jdbc.driver.DatabaseError.throwSqlException(

              DatabaseError.java:125)

              at oracle.jdbc.driver.T4CTTIoer.processError(

              T4CTTIoer.java:305)

              at oracle.jdbc.driver.T4CTTIoer.processError(

              T4CTTIoer.java:272)

              at oracle.jdbc.driver.T4C8Oall.receive(

              T4C8Oall.java:623)

              at oracle.jdbc.driver.T4CPreparedStatement.doOall8(

              T4CPreparedStatement.java:181)

              at oracle.jdbc.driver.T4CPreparedStatement.execute_for_rows(

              T4CPreparedStatement.java:543)

              at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(

              OracleStatement.java:1028)

              at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(

              OraclePreparedStatement.java:2888)

              at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(

              OraclePreparedStatement.java:2960)

              at org.hibernate.persister.entity.AbstractEntityPersister.delete(

              AbstractEntityPersister.java:2551)

               

               

               

               

               

               

               

               

              my timerlistener code is as below :-

               

              import org.jbpm.api.listener.EventListener;
              import org.jbpm.api.listener.EventListenerExecution;

              public class WaitStateTimeoutListener implements EventListener{

              /**
                *
                */
              private static final long serialVersionUID = 1L;

              @Override
              public void notify(EventListenerExecution arg0) throws Exception {
               
                System.out.println("WaitStateTimeoutListener called");
               
                // TODO Auto-generated method stub
               
               
               
              }

              }

              • 4. Re: issue with event timer inside the subprocess.
                swiderski.maciej

                Hi,

                 

                what are you trying to achieve with timer? Is it used to signal wait state after particular period of time? If so it should look like this:

                 

                     <transition name="toGetStatus" to="get status">
                           <timer duedate="2 minutes"/>
                      </transition>
                

                 

                Please remember that when you use timer in your process then while testing it there are two ways of triggering it:

                1. use ManagmentService.executeJob

                 

                     Job job = managementService.createJobQuery()
                      .processInstanceId(processInstance.getId())
                      .uniqueResult();
                    managementService.executeJob(job.getId());
                

                2. enable job executor in your jbpm.cfg.xml (uncomment <import resource="jbpm.jobexecutor.cfg.xml" />)

                and remember to put the main thread to sleep to be able to wait for job executor to trigger your timer.

                 

                HTH

                Maciej