cancel
Showing results for 
Search instead for 
Did you mean: 

How to implement long-running tasks in Activiti?

zlatan316
Champ on-the-rise
Champ on-the-rise
Hi,

My process is a simple model with 2 service tasks. ServiceTask1 can take over 15 minutes to run in the execute() method, and ServiceTask2 completes in mere seconds. What happens is that ServiceTask1 will cause the Activiti database to timeout as the transaction has remained open longer than 5 minutes.

I want to instead run this ServiceTask so that it can run for however long it wants until it then tells the process to continue with ServiceTask2. I understand in Activiti 5:17(and 5.18), there is a new JobExecutor which can help with executing a long running task but I can find any code examples of its use, or a diagram example of how to model the execution of these longer running Service Tasks.

Can anyone assist?
10 REPLIES 10

martin_grofcik
Confirmed Champ
Confirmed Champ
Hi Zlatan,

asynchronous tasks won't help you in this case. Asynchronous task splits the transaction, but still one transaction takes 15 mins in your case.

I would say that you need to make your service task execution asynchronous:
  1. call your service
  2. get response immediately that processing has started
  3. wait for message or signal from your service that processing has finished and process instance can continue in execution.
Regards
Martin

Thanks Martin,

How do i implement using this approach? I have set the Service Task to Asynchronous, with Exclusive also enabled. I imagine this is setting the ServiceTask1 to Asynchronous execution? What do I need to implement within ServiceTask1 to run without the timeout limitation and signal to the process that it can now continue to ServiceTask2?

martin_grofcik
Confirmed Champ
Confirmed Champ
Hi Zlatan,

15 mins DB transaction does not make sense.
How to implement
You have to change your service implementation too. Implement service in the following way:
  1. call service from the process. Service should return the result immediately. The return  should only inform process engine that service has started to work.
  2. process execution and get return values.
  3. Service calls activiti message/signal events which informs process instance that results are ready and instance can continue in execution.
  4. Regards
    Martin

What is meant exactly by the 'Service', as I imagine this is something which is not provided by Activiti 5.17? Would appreciate a code example of how to use it as i've only really delved into activiti specific Tasks.

martin_grofcik
Confirmed Champ
Confirmed Champ
Hi Zlatan.

let's take simple message intermediate catching event example org.activiti.engine.test.bpmn.event.message.MessageIntermediateEventTest#testSingleIntermediateMessageEventin the file org/activiti/engine/test/bpmn/event/message/MessageIntermediateEventTest.testSingleIntermediateMessageEvent.bpmn20.xml put service call (to call your external system, with executionId param) between start and message event. This external service call can send a message to process instance with execution id:

    runtimeService.messageEventReceived(messageName, execution.getId());
line 49.

Regards
Martin

Thanks Martin.  I have managed to trigger the diagram's MessageIntermediateCatchEvent with the above line of code running in an external JAR. Thanks for the help MartinSmiley Happy

The only issue that remains is how to trigger an external JAR from ServiceTask1 to run code outside of Activiti. I am trying to use the below code, but it doesnt actually trigger the jar, and hence the diagram just waits at the IntermediateMessageCatchEvent. Is there something wrong with my command? This code works fine when triggered from a command line, as it then triggers the messagecatchevent which is waiting in activiti.

<code>
public void execute(DelegateExecution execution) {
 
        String s;
        Process p;
       
  try {
  
            p = Runtime.getRuntime().exec("java -cp StandaloneRunner.jarSmiley FrustratedtandaloneRunner_lib/* conceptclasses.StandaloneRunner " + execution.getId());
            System.out.println("Execution command triggered");
            BufferedReader br = new BufferedReader(
                new InputStreamReader(p.getInputStream()));
            while ((s = br.readLine()) != null)
                System.out.println("line: " + s);
            p.waitFor();
            System.out.println ("exit: " + p.exitValue());
            p.destroy();
  
  } catch (Exception e) {
   e.printStackTrace();
  }
}

vasile_dirla
Star Contributor
Star Contributor
Hi,
Make sure your jar is visible, maybe your current path where the command is executed is not the proper one. (I guess it is your tomcat's bin folder)

try to specify the full path to the jar file not only the name.

Thanks Vasile, placing it in the bin folder allows the JAR to runSmiley Happy

One point to note is that the process instance id that is passed to the jar isnt the id that triggers the messagecatchevent. I needed to add a separate step to interrogate the database for child messagecatchevent1 id's in order to trigger the element itself to continue.

I also second the notion that this sort of functionality should be part of Activiti, as there will always be a case where we want a Service Task to last a while before it moves on, just like any real business task, they can take time. I suggest the database timeout is either increased, or its scope to be public so it can be changed easily in the Explorer or through Java.

pmsevestre
Champ in-the-making
Champ in-the-making
Hi,

This kind of question seems to appear quite regularly here at the forums. Maybe the "shell task" could be extended so it behaves more or less like the "java receive" task. One could use a custom job executor  that picks shell commands, executes them in a separate thread and then signals the engine when the external program completes.

More complex scenarios can also be addressed simply by using a different job executor (eg, using an external job scheduler like UC4, Control-M, etc)