cancel
Showing results for 
Search instead for 
Did you mean: 

Blocking service tasks

jiddo
Champ in-the-making
Champ in-the-making
Hello!

I'm new to BPM frameworks and just recently found out about them (especially Activiti and jBPM5) when looking for a solution to a problem that I wanted to overcome in a project of mine (http://stackoverflow.com/questions/7859648/how-can-i-implement-a-request-response-protocol-without-b...).

I would like to be able to model my application logic using the Activiti Designer eclipse plugin and execute it as part of my application. Specifically, I will be using an asynchronious NIO framework such as Netty or Apache MINA as the backend for the networking. The protocol is however still very much of a request-response nature and as such there will potentially be long "blocking" periods between sending a request and receiving the corresponding response. Similar problems arise when awaiting incoming connections or incoming client requests.

I like the idea of modeling my network each of my request-response pairs as a "service task" in Activiti. The problem is that there might be many of these active at any one point in time and it would not be scalable for them to lock up neither the thread that is executing the Activiti process nor one of the worker/job executor threads in the thread pool.

After looking around a bit, I found that jBPM5 tasks use the separate "WorkItemManager.completeWorkItem" method to signal the completion of the task rather then ending it whenever the executor method returns (like Activiti seems to do). That would allow me to call that completion method from a separate thread, such as the asynchonious invocation from my NIO library, which would solve my problem.

Is there any feature in Activiti that would allow me to solve the problem in a similar way, or would it be convenient to add something like that? Or is there any other standard solution to this that I have overlooked?
9 REPLIES 9

trademak
Star Contributor
Star Contributor
Hi,

The receive task may be better suited for this.
There you can invoke a web service asynchrously and have the process signalled when the response comes back.

Best regards,

jiddo
Champ in-the-making
Champ in-the-making
Well, I have certainly considered that, but it seems a bit inconvenient to use receive tasks for this, for several reasons.

First of all, from what I can tell, there is no direct connection between a certain receive task and a specific execution path in the diagram. So, say I have multiple execution paths in my Activiti process, one for each connected client. I send the same request to multiple of these clients, and then I need to wait for a reply for all of them. The reply from client A arrives first. How would I be able to target the receive event for that client's execution path only, and having the other ones remain in wait for their respective replies?

There seems to be no way to send back any data in a receive event. Thus I'll need a separate data structure storing the reply/replies and some tasks for fetching them.

Also, from what I can tell it is kind of inconvenient to construct the necessary execution query and to perform the actual signalling from within a Java service task since the ProcessEngine or RuntimeService isn't actually available anywhere. I'd have to make those globally available or actually send them as variables into the process itself.

All in all it seems to be quite a hassle not only to code the implementation on the Java-side of things, but also to model it in BPMN since every such request-reply would require at least 3-4 unique tasks, not including any of the error handling.

Am I missing something? Is there some convenient (or at least a standard/preferred) way of doing this?

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
- (ab)use a usertask? (workitem in jbpm?)
- implement a custom task in java that is identical to a user task but isn't one

The issues regarding the reference/target is an issue even with other tasks, you always need to know what to signal. And the issue of setting variables is also omnipresent as is the issue of error handling, or do I miss something. So those are no differentiators.

Ronald

jiddo
Champ in-the-making
Champ in-the-making
I have considered using User tasks, and they seem to be the closest match to the functionality I'm after, but I'm worried about possible overhead. Isn't there a risk of them being slow when using them as frequently and heavily as my scenario would require?

I would be up for implementing a custom task. I'll look into that, assuming there is a straight forward way of adding support for it in the Designer.

Regarding referencing/targetting: Yes I do need to know what to signal, but with the receive tasks I cannot find any way of specifying that, even if I do know what I want to signal.

These problems are of course solveable, but I feel that it is a bit more complex then it should need to be. If you are saying that using these receive tasks and signalling is the intended way to handle these situations then I'm happy with that. I just wanted to make sure that I hadn't missed something. Perhaps it'll turn out to be less of an issue then I first through when I try to apply it in an actual project rather then just small test scenarios. Smiley Happy

Thanks!

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
Overhead of usertasks is a non issue and the custom task you would need to implement will be almost identical.

How would you be able to signal a user task? You'd use the task id, right? For the receive task you need the execution id. No difference, and you'd need to pass that to the service in the same way to be able to use it when ending the task.

And the 'complexity' you talk about is fairly low, but that is my opinion.

jiddo
Champ in-the-making
Champ in-the-making
Alright, in the following simple example, modeling the logic of what could be an echo server:

[img]http://jiddoserv.game-server.cc/jiddo/dev/MyProcess.png[/img]

Say two clients connect, call them A and B, resulting in three execution paths, two of them ending up waiting for a signal in the "Receive client request" stage and one going back into the "Accept client connection" stage (which probably should also be a receive task followed by a data-fetching task).

The server receives a request from client B, and wants to signal the process:

Execution e = runtimeService.createExecutionQuery()
     .processInstanceId(process.getId())
     .activityId("receivetask1")
     .singleResult();
   runtimeService.signal(e.getId());
Now, this uses the "process.getId()" and the name/id of the "receivetask1" in order to signal the process. However, both execution paths are in the same process and have the same "process.getId()". They are also waiting at the same task, "receivetask1". Thus, I do not see any way of distinguishing between the two client here. How would I specify which one I am trying to signal?

Did I miss something? Is there some other way of specifying this, or do I have to somehow create completely new processes for each client so that the process ID will be different?

ronald_van_kuij
Champ on-the-rise
Champ on-the-rise
or do I have to somehow create completely new processes for each client so that the process ID will be different?

A much better solution…or do something with subprocesses

jiddo
Champ in-the-making
Champ in-the-making
Oh, ok. That must be where I got stuck then. Do subprocesses get separate process IDs?

Thanks!