7 Replies Latest reply on Jul 9, 2010 11:29 PM by Zhangqi Xiao

    Using expression as process duedate value

    Zhangqi Xiao Newbie

      Hi all,

         When I configured process dudate as below,

      <?xml version="1.0" encoding="UTF-8"?>
      <process name="TimerRepeat" xmlns="http://jbpm.org/4.3/jpdl">
       <on event="timeout">
        <timer duedate="#{process_duedate}"/>
        <event-listener />
       </on>
      
       <start g="19,50,48,48">
        <transition to="guardedWait" />
       </start>
       <state name="guardedWait" g="98,46,127,52">
        <on event="timeout">
         <timer duedate="#{node_duedate}"/>
         <event-listener />
        </on>
        <transition name="go on" to="next step" g="-16,-17"/>
       </state>
      
       <state name="next step" g="283,46,83,53"/>
      </process>
      

                                                                                                  List 1

      And I started process as:

       Map<String, String> variables = new HashMap<String, String>(); 
       variables.put("process_duedate", "24 business minutes");
       variables.put("node_duedate", "12 business minutes");
       ProcessInstance processInstance = executionService.startProcessInstanceByKey("TimerRepeat", variables)
      

                                                                                                 List 2

      But an exception happend as below:

      javax.script.ScriptException: javax.el.PropertyNotFoundException: Cannot find property process_duedate
       at org.jbpm.pvm.internal.script.JuelScriptEngine.evalExpr(JuelScriptEngine.java:180)
       at org.jbpm.pvm.internal.script.JuelScriptEngine.eval(JuelScriptEngine.java:64)
       at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:247)
       at org.jbpm.pvm.internal.script.ScriptManager.evaluate(ScriptManager.java:126)
       at org.jbpm.pvm.internal.script.ScriptManager.evaluate(ScriptManager.java:118)
       at org.jbpm.pvm.internal.script.ScriptManager.evaluateExpression(ScriptManager.java:90)
       at org.jbpm.pvm.internal.job.TimerImpl.setDueDateDescription(TimerImpl.java:76)
       at org.jbpm.pvm.internal.model.ScopeInstanceImpl.createTimer(ScopeInstanceImpl.java:303)
       at org.jbpm.pvm.internal.model.ScopeInstanceImpl.initializeTimers(ScopeInstanceImpl.java:323)
       at org.jbpm.pvm.internal.model.ExecutionImpl.initializeScopes(ExecutionImpl.java:238)
       at org.jbpm.pvm.internal.model.ExecutionImpl.start(ExecutionImpl.java:213)
       at org.jbpm.pvm.internal.cmd.StartProcessInstanceCmd.execute(StartProcessInstanceCmd.java:61)
       at org.jbpm.pvm.internal.cmd.StartProcessInstanceCmd.execute(StartProcessInstanceCmd.java:37)
       at org.jbpm.pvm.internal.svc.DefaultCommandService.execute(DefaultCommandService.java:42)
       at org.jbpm.pvm.internal.tx.SpringCommandCallback.doInTransaction(SpringCommandCallback.java:45)
       at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:128)
       at org.jbpm.pvm.internal.tx.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:55)
       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.ExecutionServiceImpl.startProcessInstanceById(ExecutionServiceImpl.java:58)
      

                                                                                               List 3

      In order to find the reason for this issue, I removed process duedate part from List 1, this resulting is:

      <?xml version="1.0" encoding="UTF-8"?>
      <process name="TimerRepeat" xmlns="http://jbpm.org/4.3/jpdl">
       <start g="19,50,48,48">
        <transition to="guardedWait" />
       </start>
       <state name="guardedWait" g="98,46,127,52">
        <on event="timeout">
         <timer duedate="#{node_duedate}"/>
         <event-listener />
        </on>
        <transition name="go on" to="next step" g="-16,-17"/>
       </state>
      
       <state name="next step" g="283,46,83,53"/>
      </process>
      

                                                                                                 List 4

      Then I started process as below :

       Map<String, String> variables = new HashMap<String, String>(); 
       variables.put("node_duedate", "12 business minutes");
       ProcessInstance processInstance = executionService.startProcessInstanceByKey("TimerRepeat", variables)

                                                                                                List 5

      To my surprised is there was no any error happened and the timer of guardedWait was correctly initialized. why?  After my investigating,I found that

      when ScriptManger caculate expression value, it search from some context scopes,such as excution context,process engine context transactioon, spring context and so on.  but when initialize the process timer duedate,the excution context has not been added to Environment, the source code from class ExecutionImpl as:

      public void start() {
        if (!STATE_CREATED.equals(state)) {
         throw new JbpmException(toString() + " is already begun: " + state);
        }
        this.state = STATE_ACTIVE_ROOT;
        ExecutionImpl scopedExecution = initializeScopes();
        fire(Event.START, getProcessDefinition());
        if (getActivity() != null) {
         scopedExecution.performAtomicOperation(AtomicOperation.EXECUTE_ACTIVITY);
        }
       }
      

                                                                                                List 6

      This " initializeScopes()" method is excuted before "scopedExecution.performAtomicOperation(AtomicOperation.EXECUTE_ACTIVITY);"  if enter accitiy it is ok, but when start process,it is wrong. so I changed method "initializeProcessInstance" from class "ExecutionImpl" as below:

       

      public void initializeProcessInstance(ProcessDefinitionImpl processDefinition, String key) {
        setProcessDefinition(processDefinition);
        setActivity((ActivityImpl) processDefinition.getInitial());
        this.processInstance = this;
        this.state = STATE_CREATED;
        this.key = key;
        save();
        composeIds();
      
        //Added by me to add excution context to environment
        ExecutionContext originalExecutionContext = null;
        ExecutionContext executionContext = null;
        EnvironmentImpl environment = EnvironmentImpl.getCurrent();
        if (environment != null) {
         originalExecutionContext = (ExecutionContext) environment.getContext(Context.CONTEXTNAME_EXECUTION);
         if ((originalExecutionContext != null) && (originalExecutionContext.getExecution() == this)) {
          originalExecutionContext = null;
         } else {
          executionContext = new ExecutionContext(this);
          environment.setContext(executionContext);
         }
        //ended add
      
        }
        HistoryEvent.fire(new ProcessInstanceCreate(), this);
       }
      
      

                                                                                                List 7
      By doing so,when I configured process duedate as list1 and start process as list 2.it was ok!

      I konw the way  I used is not the best one! but can any one tell me the best way or is it a bug need to be fixed?