14 Replies Latest reply on Jan 11, 2010 5:41 AM by Joram Barrez

    how to use Timers on <custom> in jBPM 4.2

    M Porter Newbie

      Hi,

       

      I have a custom task that I wish to exit on a timer event. The issue is that the custom event implements a execution.waitForSignal() in the execute method. So this custom state could exit on a signal or else should exit on a timer fired. The signalling was working fine but now I am trying to also add the timer event. In order to do this I added the notify() to the custom class and this does get called. There is a default transition out of the custom event to a decision node which evaluates a process variable 'result' to work out the next transition to take (i.e timeout, success etc). However the timer is fired and the event handler gets invoked but the process does not exit the state. What I am I missing ?.

       

      <custom
              class="de.o2.sebula.BusinessServiceResponseHandler"
              continue="async" g="647,168,217,52" name="Business Service Response Handler">
              <on event="timeout">
                  <timer duedate="10 seconds" />
                  <event-listener
              class="de.o2.sebula.BusinessServiceResponseHandler"/>
              </on>
              <transition name="check-response-status" to="check-response-status"
                  g="-45,-30" />
      </custom>

       

      BusinessServiceResponseHandler Class (relevant parts):-

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

       

      public void execute(ActivityExecution execution) throws Exception {

              execution.waitForSignal();
      }

       

      public void signal(ActivityExecution execution, String signalName,
                  Map<String, ?> parameters) throws Exception {

       

              execution.setVariable("result", signalName);
              execution.take("check-response-status");
      }

       

      public void notify(EventListenerExecution execution) throws Exception {
              execution.setVariable("result", "timeout");

      }

        • 1. Re: how to use Timers on <custom> in jBPM 4.2
          M Porter Newbie

          And the decision code that should be executed when the custom state is exited:-

           

              <decision g="961,172,48,48" name="check-response-status">
                  <transition g="1182,276:-119,-10" name="error-cancel" to="end-cancel">
                    <condition expr="#{result==&quot;error-cancel&quot;}" />
                  </transition>
                  <transition g="-4,-22" name="success" to="end-success">
                    <condition expr="#{result==&quot;success&quot;}" />
                  </transition>
                  <transition g="-67,-17" name="error-fail" to="end-error">
                    <condition expr="#{result==&quot;error-fail&quot;}" />
                  </transition>
                  <transition g="-55,-5" name="timeout" to="response-retry-decider">
                    <condition expr="#{result==&quot;timeout&quot;}" />
                  </transition>
              </decision>

          • 2. Re: how to use Timers on <custom> in jBPM 4.2
            Ronald van Kuijk Master
            have you tried adding an explicit transition to the timer?
            • 3. Re: how to use Timers on <custom> in jBPM 4.2
              M Porter Newbie

              Hi Ronald,

               

              I cant add a transition to the timer inside the <on> element. It seems that timer behaviour is modelled differently in <state> and <custom>. For <state> tags I have that working with:-

               

              <state g="339,316,117,52" name="Request Timeout">
                      <transition g="18,-2" name="req timeout"
                          to="Business Service Request Invoker">
                          <timer duedate="5 seconds" />
                      </transition>
              </state>

               

              But for custom the only way I can see of doing it is having the timer in the <on> tag:-

               

                      <on event="timeout">
                          <timer duedate="5 seconds" />
                          <event-listener
                              class="de.o2.sebula.BusinessServiceResponseHandler">
                              <field name="logMessage">
                                  <string value="Business Service Response - TIMER EXPIRED" />
                              </field>
                          </event-listener>
                          <event-listener
                      class="de.o2.sebula.BusinessServiceResponseHandler"/>
                      </on>

              • 4. Re: how to use Timers on <custom> in jBPM 4.2
                Ronald van Kuijk Master

                Sorry, I meant timer on the transition (the other way around) but you probably need the event-listener.

                 

                But what about:

                 

                public void notify(EventListenerExecution execution) throws Exception {
                        execution.setVariable("result", "timeout");
                        execution.take();
                }
                

                 

                maybe in combination with the transition name (which you can also pass in as a parameter I think)

                • 5. Re: how to use Timers on <custom> in jBPM 4.2
                  M Porter Newbie

                  This is how I had expected it to work but there is no ability to execute takeXXXXX() on the EventListenerExecution that is passed into the notify method so thats not possible !.

                   

                  I must be missing something simple ! I guess I could use the executionService to signal myself but that cant really be the right way to implement this...

                  • 6. Re: how to use Timers on <custom> in jBPM 4.2
                    Ronald van Kuijk Master

                    You know, jBPM is so flexible... So many things are possible. I was curious so I gave it a try and succeeded...

                     

                    If you take the xsd, change the ref for the transition in the custom element to what is in the state, you can do things like

                     

                        public void testTimerTimeoutCustom() {
                            deployJpdlXmlString("<process name='Insurance claim' key='ICL2'>" +
                                    "  <start>" +
                                    "    <transition to='a' />" +
                                    "  </start>" +
                                    "  <custom name='a' class='" + MyCustomWait.class.getName() + "'>" +
                                    "    <transition to='b' />" +
                                    "    <transition name='timeout' to='escalate'>" +
                                    "      <event-listener class='" + MyCustomWait.class.getName() + "'/>" +
                                    "      <timer duedate='2 minutes' />" +
                                    "    </transition>" +
                                    "  </custom>" +
                                    "  <state name='b' />" +
                                    "  <end name='escalate' />" +
                                    "</process>");
                    
                            ProcessInstance processInstance = executionService
                                    .startProcessInstanceByKey("ICL2", "82436");
                    
                            Job job = managementService.createJobQuery().processInstanceId(
                                    processInstance.getId()).uniqueResult();
                    
                            managementService.executeJob(job.getId());
                    
                            assertProcessInstanceEnded(processInstance);
                        }
                    
                        public static class MyCustomWait implements ExternalActivityBehaviour,
                                EventListener {
                    
                            private static final long serialVersionUID = 1L;
                    
                            public void execute(ActivityExecution execution) throws Exception {
                                execution.waitForSignal();
                            }
                    
                            public void signal(ActivityExecution execution, String signalName,
                                    Map<String, ?> parameters) throws Exception {
                                execution.take(signalName);
                            }
                    
                            public void notify(EventListenerExecution execution) throws Exception {
                                log.debug("Timer went off, taking transition");
                            }
                        }
                    

                     

                    Keep in mind that this is a test for 4.3, but the same should work for 4.2.

                    • 7. Re: how to use Timers on <custom> in jBPM 4.2
                      M Porter Newbie

                      Hi Ronald,

                       

                      Actually 4.3 is fine as I had updated to that anyway in order to solve this issue !. I am now done until 4th January but I will give it a try when I get onsite and see if it works. The issue would be then that I am not sure O2 would be happy to make that XSD change unless it was agreed as part of the jBPM roadmap for 4.4 for example as otherwise it would cause upgrade issues and (well I am sure you know the rest !).....If it was something that would be included (supported) in the 4.4 release then we could use it.

                       

                      I had created a JIRA JBPM-2712 feature request for this today so maybe if the developers take a look at it and agree then I can take that approach. However without their support I do not think we could implement it !.

                       

                      Thanks for your help !!!.

                       

                      Regards

                      Martin

                      • 8. Re: how to use Timers on <custom> in jBPM 4.2
                        Ronald van Kuijk Master

                        Since it is

                        - just an xsd change

                        - including a test (which is already made)

                        - something logical to have (same behaviour)

                         

                        I do not think it will not be included. (or without the double negation: I think it will be included ;-))

                        • 9. Re: how to use Timers on <custom> in jBPM 4.2
                          M Porter Newbie

                          Hi Ronald,

                           

                          I tried the xsd change today and as you say it works !. So thanks for your work on that !!. I thought we were there but then I tried the signalling the waiting custom state and it still fails with the 'inactive-state' error that I created as JIRA JBPM-2711. And this was literally the last part to get working. If you get 5 mins maybe you can figure out from the trace on that JIRA if it looks obvious ?. Not sure if you know much about how the process state is modified but all we are doing is querying for the child process and signalling it. Maybe there is something wrong with the process query and we are doing something wrong ?.

                           

                          Thanks

                          Martin

                          • 10. Re: how to use Timers on <custom> in jBPM 4.2
                            M Porter Newbie

                            Hi Roland,

                             

                            I looked more into this yesterday and my findings are that having made the xsd change both the <state> and <custom> both work ok when the timer is fired on the transition but then the signalling fails (as per the JIRA I mentioned above). Hence it seems the addition of <timer> on the transition is the cause. When i remove it then the signalling works just fine. So its a bug by the look of it but at least the behaviour is consitent !. Will have to see now if someone will look into it. The testcase is attached to the JIRA.

                             

                            Regards

                            Martin

                            • 11. Re: how to use Timers on <custom> in jBPM 4.2
                              Ronald van Kuijk Master
                              I did not add a timer on the transition in the sense that I changed the TransitionType. I changed the way a transition is defined in the custom to the same thing that is used in in state. So that changes should *not* influence the state at all.
                              • 12. Re: how to use Timers on <custom> in jBPM 4.2
                                M Porter Newbie

                                Hi Ronald,

                                 

                                I know what you meant. I didnt mean that adding the xsd change has influenced the timer operration on the state. I meant that if I use the <state> with the timer on the plain vanilla 4.3 version (without the xsd modification) then the timer works but causes the signalling issues (i.e if I try to signal the state before the timer fires it fails 'inactive-scope'). If i then make the xsd change and replace the <state> with the <custom> we have the same issue. So its the same in 4.3 and the 4.3 with xsd patch whether using <custom> or <state> they both behave the same way (which you would expect !).

                                 

                                So the issue is not related to <custom> at all. It appears in 4.3 on the <state>. If I do not have the <timer> inside the transition from that <state> then I can signal the waiting state no problem. Just by simply adding the <timer> on a timeut transition puts the state activity in a state which cant be signalled (inactive-scope). But the timer does work and fires correctly. However you cannot signal the activity before the timer fires. Remove the timer and I can signal the state again.

                                 

                                processInstance.isActive() returns true and I can get the active activity name but I cant signal it.

                                 

                                Regards

                                Martin

                                • 13. Re: how to use Timers on <custom> in jBPM 4.2
                                  Ronald van Kuijk Master

                                  Martin,

                                   

                                  Have a look at JBPM-2711 again. I think the error is because you signal in a way that is not valid when having a timer on it. So it's not that having a timer on a state transition causes this error, it's the combination of how you signal and having a timer or not. In your testcase you do not signal the state (activity/execution) but the processinstance, The state of a processinstance and the ability to signal it explicitly or not can be different by having child executions (timers!!!) active or not.

                                   

                                  The relation of activity, execution, processinstance and whether they are active or what 'state' they have, can be confusing. I'll try to find some more info in this area and blog about it, or ask others to provide some more information.

                                  • 14. Re: how to use Timers on <custom> in jBPM 4.2
                                    Joram Barrez Master
                                    Ronald is 100% correct. I've added Ronalds test case to the jBPM testsuite and adapted the XSD as needed.