12 Replies Latest reply on Jul 11, 2006 11:13 AM by cpob

    re : Decision Hanlder

      Hello,

      In my junit code, I constructed a decision node and added transitions to it. But I do not know how to add the decision handlers. The purpose of this unit test is to prove all node classes can be created programmatically. Here is my junit test code. The AmountDecisionHandler is a DecisionHandler and always returns "forwardTo" value on decision method.
      Please help me.



      ProcessDefinition processDefinition = ProcessDefinition.createNewProcessDefinition();
      StartState startState = new StartState();
      startState.setName("start");
      processDefinition.addNode(startState);


      Decision amountcheck = new Decision();
      amountcheck.setName("amountcheck");
      processDefinition.addNode(amountcheck);

      State reenter = new State();
      reenter.setName("reenter");
      processDefinition.addNode(reenter);

      State increase = new State();
      increase.setName("increase");
      processDefinition.addNode(increase);

      EndState endState = new EndState();
      endState.setName("end");
      processDefinition.addNode(endState);


      Transition amountCheckTxns = new Transition();
      amountCheckTxns.setTo(amountcheck);


      Transition successTxns = new Transition();
      successTxns.setName("success");
      successTxns.setTo(increase);


      Transition failTxns = new Transition();
      failTxns.setName("fail");
      failTxns.setTo(reenter);

      Transition endTrans = new Transition();
      endTrans.setTo(endState);

      //bind transitions to node
      startState.addLeavingTransition(amountCheckTxns);
      amountcheck.addLeavingTransition(successTxns);
      amountcheck.addLeavingTransition(failTxns);
      reenter.addLeavingTransition(amountCheckTxns);
      increase.addLeavingTransition(endTrans);


      ProcessInstance processInstance = new ProcessInstance(processDefinition);
      AmountDecisionHandler.forwardTo ="success";
      // after the first signal the AmountDecisionHandler of amountcheck
      // would be called. The handler forwards to increase node imediately.
      processInstance.signal();

      assertSame(processDefinition.getNode("increase"), processInstance.getRootToken().getNode());

      processInstance.signal();

      assertSame(processDefinition.getNode("end"), processInstance.getRootToken().getNode());

      processInstance = new ProcessInstance(processDefinition);

      //now forward to "fail" state
      AmountDecisionHandler.forwardTo ="fail";
      // after the first signal the AmountDecisionHandler of amountcheck
      // would be called. The handler forwards to reenter node imediately.
      processInstance.signal();

      assertSame(processDefinition.getNode("reenter"), processInstance.getRootToken().getNode());

      AmountDecisionHandler.forwardTo ="success";
      processInstance.signal();

      assertSame(processDefinition.getNode("increase"), processInstance.getRootToken().getNode());

        • 1. Re: re : Decision Hanlder
          cpob

          You have to add the Handler to the decision node for it to work.

          Look at the API for Decision.

          There's a setAction method. Create a new action and set it to the decision object using that method.

          You'll have to investigate what creating a new action involves (you have to create a new Action Delegation).

          • 2. Re: re : Decision Hanlder

            Hi cpob,

            Thanks for your response. The Action allows to set up handler?s trap one of the below event type. I don't think you can use it for setting up Decision handler. I think API for setting up decision handler in "Decision" class is missing or may be I am missing something here. Also I have modified my code to create an action and associate with Decision but my handler wasn't called.

            Decision amountcheck = new Decision();
            amountcheck.setName("amountcheck");
            processDefinition.addNode(amountcheck);

            Delegation delegation = new Delegation();
            delegation.setClassName("com.mycomp.test.AmountDecisionHandler");
            Action action = new Action();
            action.setActionDelegation(delegation);
            amountcheck.setAction(action);

            Action events types :

            public static final String EVENTTYPE_TRANSITION = "transition";
            public static final String EVENTTYPE_BEFORE_SIGNAL = "before-signal";
            public static final String EVENTTYPE_AFTER_SIGNAL = "after-signal";
            public static final String EVENTTYPE_PROCESS_START = "process-start";
            public static final String EVENTTYPE_PROCESS_END = "process-end";
            public static final String EVENTTYPE_NODE_ENTER = "node-enter";
            public static final String EVENTTYPE_NODE_LEAVE = "node-leave";
            public static final String EVENTTYPE_SUPERSTATE_ENTER = "superstate-enter";
            public static final String EVENTTYPE_SUPERSTATE_LEAVE = "superstate-leave";
            public static final String EVENTTYPE_SUBPROCESS_CREATED = "subprocess-created";
            public static final String EVENTTYPE_SUBPROCESS_END = "subprocess-end";
            public static final String EVENTTYPE_TASK_CREATE = "task-create";
            public static final String EVENTTYPE_TASK_ASSIGN = "task-assign";
            public static final String EVENTTYPE_TASK_START = "task-start";
            public static final String EVENTTYPE_TASK_END = "task-end";
            public static final String EVENTTYPE_TIMER = "timer";

            • 3. Re: re : Decision Hanlder
              cpob

              That is how you define actions... almost. Actions do not always have to be with events. An action can be defined inside a Node (or Decision) as well.

              You're on the right path, but don't be too quick to give up. You gotta make sure all the elements are set up properly

              Try doing a

              .setProcessDefinition(processDefinition);
              on both your action and your delegation in addition to what you have.

              • 4. Re: re : Decision Hanlder

                Thanks for your help. I am copying the implementation of execute method code in Decision class. This code checks the private decisionDelegation list for handlers if there is one defined then it calls the handler. If you notice it doesn't look for decision handlers in action list (If that is expected behavior then this Decision implementation has broken the contract). So I guess that's why the decision handlers were not called. I do not know if there is any other alternative way to initialize the decisionDelegation. Please help me.

                public void execute(ExecutionContext executionContext) {
                String transitionName = null;

                try {
                if (decisionDelegation!=null) {
                DecisionHandler decisionHandler = (DecisionHandler) decisionDelegation.instantiate();
                transitionName = decisionHandler.decide(executionContext);

                } else if (decisionExpression!=null) {
                Object result = JbpmExpressionEvaluator.evaluate(decisionExpression, executionContext);
                if (result==null) {
                throw new JbpmException("decision expression '"+decisionExpression+"' returned null");
                }
                transitionName = result.toString();

                } else {

                Iterator iter = decisionConditions.iterator();
                while (iter.hasNext() && (transitionName==null)) {
                DecisionCondition decisionCondition = (DecisionCondition) iter.next();
                Object result = JbpmExpressionEvaluator.evaluate(decisionCondition.getExpression(), executionContext);
                if (Boolean.TRUE.equals(result)) {
                transitionName = decisionCondition.getTransitionName();
                }
                }

                if (transitionName==null) {
                getDefaultLeavingTransition().getName();
                }
                }
                } catch (Throwable exception) {
                raiseException(exception, executionContext);
                }

                Transition transition = null;
                if (transitionName!=null) {
                log.debug("selected transition name '"+transitionName+"'");
                transition = getLeavingTransition(transitionName);
                } else {
                log.debug("no transition name selected: taking default leaving transition");
                transition = getDefaultLeavingTransition();
                }

                if (transition==null) {
                throw new JbpmException("decision '"+name+"' selected non existing transition '"+transitionName+"'" );
                }
                executionContext.leaveNode(transition);
                }

                • 5. Re: re : Decision Hanlder
                  cpob

                  You're right... It looks like decision doesn't allow you to programmatically create the decision handler.

                  My suggestion is to build jBPM yourself, and add in a method in Decision that allows you to set the decisionDelegation.

                  Building jBPM yourself is easy, I'm doing it currently for some issue w/ Timers not getting their execution context set properly.

                  • 6. Re: re : Decision Hanlder

                    Thanks! In order to be complaint with all other Node implementations I think the Decision class must also call the actions. So that way I don't have to add new API to set decisionDelegation. Please let me know your thoughts. BTW I have not committed code to Jboss before so any pointers to the right directions would be appreciated.

                    • 7. Re: re : Decision Hanlder
                      cpob

                      I disagree that the decision class must call actions.

                      - Nodes call actions because that's what nodes do.
                      - Decisions call their decision handlers, because that's what decision nodes do.

                      When you specify the handler on a decision node (in the XML/pdl), you do not use an action, or event. You just give it a handler. This is what is missing from the programmatic way to build a decision node.

                      Also, since it is open source, you don't *have* to worry about committing the code to JBoss. You can just change it for your install, and then have a JIRA issue for it.

                      • 8. Re: re : Decision Hanlder
                        cpob

                        I just made the change to the Decision class, and it works

                        I simply added this method to Decision.java:

                        public void setDecisionDelegation( Delegation del ) {
                         this.decisionDelegation = del;
                        }


                        And then I programmatically added it to an existing decision node.
                        Delegation d = new Delegation();
                        d.setClassName("test.TestDecisionHandler");
                        d.setProcessDefinition(proDef);
                        decisionNode.setDecisionDelegation(d);


                        It called my handler no problem when going through the process.

                        This was good I came across this, since this is something we needed anyway. :)

                        • 9. Re: re : Decision Hanlder
                          cpob
                          • 10. Re: re : Decision Hanlder

                            Thanks!

                            • 11. Re: re : Decision Hanlder
                              kukeltje

                              Can you elaborate on why you think decisions should not call actions (e.g. on a 'decide' event?) Not that I disagree with you, I'm just curious to the why instead of 'that's what it does' ;-)

                              • 12. Re: re : Decision Hanlder
                                cpob

                                I was all ready to spout a list of 'why', but then my argument just kinda fell apart, so my reasoning is rather weak now. I can see how decisions could be implemented just like nodes w/ actions.

                                Assigning a delegation straight to a decision node, instead of creating an action, and a delegation, and all the hoops you'd have to jump through is just nicer :)

                                The decision has a handler (the delegation), which even has a separate column in the Node table for it, so it avoids the action middleman.