4 Replies Latest reply on Jun 11, 2010 12:42 PM by mpradny

    Manual reroute in Jbpm 4.3

    mpradny

      Hi,

       

      I need to implement manual rerouting between tasks in jbpm4. I know that this is not the best thing to do in process world, but from time to time we get some exceptional state (e.g. wrong input in one of the steps), so the admin needs to move the instance back.

       

      I this forum I have found only solutions for Jbpm3. Has anyone working solution for Jbpm4.3. I have tried to use ExecutionImpl.moveTo(ActivityImpl), but with no luck. Before I try to look deeper in source codes, I would welcome any ideas and directions

       

      Thanks,

       

      Martin

        • 1. Re: Manual reroute in Jbpm 4.3
          rebody

          Hi Martin,

           

          Please try executionImpl.setActivity(activityImpl);

           

          As you know, we will never recommend operations like this.

          • 2. Re: Manual reroute in Jbpm 4.3
            mpradny

            Hi,

             

            still no luck. moveTo calls setActivity, so it probably not the issue. I think, I'm missing something in general here. The methods are called fine, but the state is not persisted. Here is my current test code - it looks to simple to work (Based on TaskCandidates test, because once the rerouting is working I want to make sure tasks are also correctly updated)

             

            public void testReroute() {

                ProcessInstance processInstance = executionService.startProcessInstanceByKey("TaskReroute");

                String pid = processInstance.getId();

             

                // both johndoe and joesmoe will see the task in their *group* task list

                List<Task> taskList = taskService.findGroupTasks("johndoe");

                assertEquals("Expected a single task in johndoe's task list", 1, taskList.size());

                Task task = taskList.get(0);

                assertEquals("review", task.getName());

                taskService.completeTask(task.getId());

             

                // verify that process moved to the next state

                processInstance = executionService.findProcessInstanceById(pid);

                assertTrue(processInstance.isActive("approve"));

             

                //reroute back to review

                ExecutionImpl execution=(ExecutionImpl) processInstance.findActiveExecutionIn("approve");

                ProcessDefinitionQuery pdquery = repositoryService.createProcessDefinitionQuery();

                pdquery.processDefinitionId(execution.getProcessDefinitionId());

                ProcessDefinitionImpl pd=(ProcessDefinitionImpl) pdquery.list().get(0);

                   ActivityImpl endActivity=pd.getActivity("review");

                execution.setActivity(endActivity);

             

                processInstance = executionService.findProcessInstanceById(pid);

                assertTrue(processInstance.isActive("review"));

             

              }

            • 3. Re: Manual reroute in Jbpm 4.3
              rebody

              Hi Martin,

               

              OK, I see the problem.  After you used execution.setActivity() or moveTo(), you should save the modifed execution into database.

               

              Generately, please do these operations in a Command, then jBPM 4 will commit the transaction automaticly.  Please refer this:

               

              processEngine.execute(new Command() {

                  public Object execute(Environment env) {

                      // ...

                      execution.setActivity(activityImpl)

                     //...

                  }
              });

              • 4. Re: Manual reroute in Jbpm 4.3
                mpradny

                THANK YOU This works.

                 

                In case anyone is looking for something similar, here si the code.

                 

                import org.jbpm.api.ProcessDefinitionQuery;
                import org.jbpm.api.ProcessEngine;
                import org.jbpm.api.ProcessInstance;
                import org.jbpm.api.cmd.Environment;
                import org.jbpm.api.model.Event;
                import org.jbpm.pvm.internal.client.ClientExecution;
                import org.jbpm.pvm.internal.cmd.AbstractCommand;
                import org.jbpm.pvm.internal.model.ActivityImpl;
                import org.jbpm.pvm.internal.model.ExecutionImpl;
                import org.jbpm.pvm.internal.model.ProcessDefinitionImpl;
                import org.jbpm.pvm.internal.model.TransitionImpl;
                import org.jbpm.pvm.internal.model.op.AtomicOperation;
                import org.jbpm.pvm.internal.processengine.ProcessEngineImpl;
                import org.jbpm.pvm.internal.session.DbSession;
                import org.jbpm.pvm.internal.task.TaskImpl;

                 

                public class RerouteCmd extends AbstractCommand<ProcessInstance> {
                    /**
                     *
                     */
                    private static final long serialVersionUID = 1L;
                    private static final String REROUTE = "#reroute#";
                    private String executionId;
                    private String newActivityName;
                    private String taskId;
                   
                    public RerouteCmd(String executionId, String newActivityName, String taskId){
                         this.executionId=executionId;
                         this.newActivityName=newActivityName;
                         this.taskId=taskId;
                    }
                   
                    @Override
                    public ProcessInstance execute(Environment environment) throws Exception {
                        ExecutionImpl execution = null;
                       
                        DbSession dbSession = environment.get(DbSession.class);
                        execution = (ExecutionImpl) dbSession.findExecutionById(executionId);

                 

                           ProcessDefinitionImpl pd=execution.getProcessDefinition();
                          
                        ActivityImpl endActivity=pd.getActivity(newActivityName);
                        ActivityImpl startActivity=execution.getActivity();
                        TransitionImpl trans=startActivity.createOutgoingTransition();
                        trans.setDestination(endActivity);
                        trans.setName(REROUTE);
                       
                        if (taskId==null){
                            execution.signal(REROUTE);
                        }else{
                            TaskImpl task=dbSession.get(TaskImpl.class, Long.parseLong(taskId));
                            if (task!=null){
                                task.complete(REROUTE);
                                dbSession.delete(task);
                            }
                        }
                        startActivity.removeOutgoingTransition(trans);
                       
                        return null;
                    }

                 

                }

                 

                 

                I have tried to casue minimal damage to existing logic. May be the signal and complete operations could be done again using commands, but I wasn't able to get processEngine (and didn't bother too much, since this works).