cancel
Showing results for 
Search instead for 
Did you mean: 

What's the best way to design a process which allows user to recall back to his task.

chenning007
Champ on-the-rise
Champ on-the-rise
Hi folks,

I am not sure this is the proper place to raise this question, if not please kindly let me know.

My question: is it possible for activiti engine to allow user to recall back to his task, for example

start -> task A -> task B -> task C -> end

if task A is completed by user A, process goes to task B and waits for user B's completeness, however, before user B performs to complete task B, user A would like to recall the task from task B back to A and complete the task A again with more information. Is there any good way to design the process and achieve the requirement, please advice, thank you.

Best Regards!

– Ning
25 REPLIES 25

chenning007
Champ on-the-rise
Champ on-the-rise
any comments please, I am waiting online

trademak
Star Contributor
Star Contributor
Hi,

You could use a signal boundary event on every task for example, that moves back to the previous task. You can then signal the process instance when necessary.

Best regards,

Tijs,

Thanks for your reply…

Your proposal sounds a good idea to me, now we meet another trouble – we would allow to recall a task to any tasks which previously had been completed, for example, users who completed task A, B, C, D would require to recall current task E back to one of their tasks which would be task A, B, C or D.

Our current solution is to draw flow lines from task E to task A, B, C, D, but it results in a very big process(many flow lines) which is hard to be maintained. Based on your proposal, can we send the jump-back task name within the signal, when the signal is replied by boundary event, an new implemented service task which can parse target task from the received signal and jump the process back to target task directly. What's your idea on this solution, if you have anything better, please also advise, thank you.

–Ning

martin_grofcik
Confirmed Champ
Confirmed Champ
Hi Ning,

Another possibility could be to do not cover return back in process definition, but support it in admin functionality. (Command to take execution end return it to the state where you want to. (It is easy to do in activiti).

Regards
Martin

Hi Martin,

I suppose the command you mentioned here is the internal implementation of xxxService classes(activiti API). Can these commands class be accessed by application directly, or I should implement my own customized API based on these command classes for this specific requirement?

Thanks!

–Ning

jbarrez
Star Contributor
Star Contributor
You can write custom Commands and pass these in the ManagementService.

tloomba
Champ in-the-making
Champ in-the-making
Hi Mr. Joram,

would you have an example of how to write a custom Command and use it for the above use case? I work in a company where the use case is similar. We have very large process models and our customer has the need to send the existing process instance upstream to a previous step, or downstream to a step that has not executed yet. Drawing transitions in the model will clutter them and not be scalable, especially when new models are created. If you could provide us with an example of using a custom Command, that would help as we have searched the forum and the web and did not find examples of creating custom Command.

Also, one of the customer's use case is to complete a process instance gracefully, as if it had ended as normal. If the instance is a sub-process created from a call activity of a parent process, the parent call activity should complete and instance should move to next step. We found the following example code from this forum, but it is throwing a null pointer exception at the "exec.end()" call. Would you be able to provide some information on why Activiti is throwing an NPE at this call? I would assume of ActivityExecution provides an end method, it should work.

This is the code we tested:
              
List<Execution> executions = runtimeService.createExecutionQuery().processDefinitionName("TestSendTo").list();
ActivityExecution exec = (ActivityExecution) executions.get(0);
exec.end();

Below is the exception:

org.activiti.rest.exception.ExceptionHandlerAdvice - Unhandled exception
java.lang.NullPointerException
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:633)
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:628)
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.end(ExecutionEntity.java:398)
at com.thomsonreuters.workflowservice.service.SendToServiceImpl.completeInstances(SendToServiceImpl.java:105)


Any information you provide would be helpful. Thank you in advance of your time!

Tavishi Loomba


martin_grofcik
Confirmed Champ
Confirmed Champ
Hi,

would you have an example of how to write a custom Command and use it for the above use case?

An example of the new command usage:

    public void setExecutionToActivity(String executionId, String activityId) {
        ProcessEngineConfigurationImpl processEngineConfiguration = …..
        processEngineConfiguration.getCommandExecutor().execute(new SetActivityCmd(executionId, activityId));
    }
….
    private static class SetActivityCmd implements Command<Void> {

        private final String executionId;
        private final String activityId;

        private SetActivityCmd(String executionId, String activityId) {
            this.executionId = executionId;
            this.activityId = activityId;
        }

        @Override
        public Void execute(CommandContext commandContext) {
            ExecutionEntity execution = commandContext.getExecutionEntityManager().findExecutionById(this.executionId);
            execution.setActivity(new ActivityImpl(this.activityId, execution.getProcessDefinition()));
            return null;
        }

    }

Regarding deleting process instances:

/**
   * Delete an existing runtime process instance.
   *
   * @param processInstanceId
   *          id of process instance to delete, cannot be null.
   * @param deleteReason
   *          reason for deleting, can be null.
   * @throws ActivitiObjectNotFoundException
   *           when no process instance is found with the given id.
   */
  void deleteProcessInstance(String processInstanceId, String deleteReason);

NPE stack trace does not make sense without activiti version (It is not Activiti6 master branch 🙂 ) Can you create simple jUnit test?
https://forums.activiti.org/content/sticky-how-write-unit-test

Regards
Martin

Hi,

I'm trying to use your code to skip a task in a process. For example, I have a process start-->userTask1-->userTask2-->userTask3-->end, so I'm checking if I completed userTask1 and after I'm using the command executor as you described above to jump to userTask3, skipping userTask2.

The thing is that whenever I execute the command I get the following error:

[main] ERROR org.activiti.engine.impl.interceptor.CommandContext  - Error while closing command context
java.lang.NullPointerException
    at org.activiti.engine.impl.persistence.entity.ExecutionEntity.signal(ExecutionEntity.java:414)
    at org.activiti.engine.impl.persistence.entity.TaskEntity.complete(TaskEntity.java:203)
    at org.activiti.engine.impl.cmd.CompleteTaskCmd.execute(CompleteTaskCmd.java:52)
    at org.activiti.engine.impl.cmd.CompleteTaskCmd.execute(CompleteTaskCmd.java:24)
    at org.activiti.engine.impl.cmd.NeedsActiveTaskCmd.execute(NeedsActiveTaskCmd.java:59)
    at org.activiti.engine.impl.interceptor.CommandInvoker.execute(CommandInvoker.java:24)
    at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:57)
    at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:31)
    at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:40)
    at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:35)
    at org.activiti.engine.impl.TaskServiceImpl.complete(TaskServiceImpl.java:178)
    at com.example.OnboardingRequest.main(OnboardingRequest.java:59)

I also downloaded the unit test on your github, but when I'm trying to transpose your code into mine, I get the same error.

Have you some ideas why is this happening? Probably I'm making some silly mistake because I'm a beginner with Activiti.

Thank you in advance.