cancel
Showing results for 
Search instead for 
Did you mean: 

Thread Safeness of Java Service Task

timo_rohrberg
Champ in-the-making
Champ in-the-making
Hello everybody,

we're using the Activiti engine for a while now in our enterprise application. Some of our Java Service Tasks are completely identical from the perspective of the source code. Their particular behavior just depends on the expressions injected via the <extensionElements> mechanism. We created a sample project available under the following link to simulate the setup we have:
https://drive.google.com/open?id=0B1Mh4R0LVb41YnZTVWZYaEVUdHc

Now, in the Activiti user guide, you can find the following sub-section in the section about Java Service Task implementation:

"Note: there will be only one instance of that Java class created for the serviceTask it is defined on. All process-instances share the same class instance that will be used to call execute(DelegateExecution). This means that the class must not use any member variables and must be thread-safe, since it can be executed simultaneously from different threads. This also influences the way Field injection is handled."

With that we're a bit concerned that we might run into a threading problem since we're re-using the same class for several Java Service Task in the workflow. Can it happen that one expression injection overrides another one from another execution of the same Java Service Task class?

When debugging into the source code, we noticed that several instances are created of the same Java Service Task class. Sometimes, the same instance is re-used, sometimes, it is instanciated again. We simply cannot identify the exact behavior of Activiti of when it instanciates the class and when not. However, is a private member variable of type Expression always thread-safe?

We highly appreciate any comment on this topic.

Thank you very much.

Regards
Timo Rohrberg
5 REPLIES 5

sankalpn
Champ in-the-making
Champ in-the-making
We ran into a similar issue. We worked around it by moving these private variables out to workflow variables. After that JavaDelegates might as well become spring beans and they'll be perfectly thread safe.

timo_rohrberg
Champ in-the-making
Champ in-the-making
Hello,

well, moving the one variable out to workflow variables is not an option for us since the value of those variable is injected as a fixed value from the workflow model bpmn and not when actually starting the workflow.

Background: We're using Activiti in an OSGi-based application and provide the actual operations to be executed as Service Tasks as OSGi services. Since Activiti does not know anything about OSGi an cannot execute OSGi services directly, we built a bridge as a Java Service Task which gets the actual OSGi service to execute injected from the workflow model bpmn. That Bridge is then used as the Java Service Task class in all our Java Service Tasks. We now have to make sure that there are no race conditions on the injected variable holding the actual OSGi service to be executed since that would lead to the execution of the wrong OSGi service.

Furthermore, are workflow variables always really thread safe? We encountered a situation in which we diagnosed a race condition on the workflow variables, but were not able to reproduce that situation reliably. Is it absolutely sure to assume that all workflow variables are 100% thread safe?

We appreciate any further comment.

Regards
Timo Rohrberg

jbarrez
Star Contributor
Star Contributor
Yes, using Expressions is thread safe. The Expression is actually only set once, on delegate instantiation. In the method, the expression.getValue(execution) is used later on, which can happen concurrently without problems.

Variables are thread safe only if you are not doing any async steps. Otherwise, regular async rules apply and the order can be anything.

timo_rohrberg
Champ in-the-making
Champ in-the-making
Hello,

thank you for your further explanation. That helps us a lot to be sure that we don't have a sleeping problem of race conditions through threading issues. I just have to further questions on that issue…

1) When examining the source code of Activiti, I noticed that there are actually two implementations of the org.activiti.engine.delegate.Expression, the org.activiti.engine.impl.el.FixedValue, and the org.activiti.engine.impl.el.JuelExpression. While the latter one seems to really do something with the passed VariableScope in the getValue() method, the first one does not use it at all. That appeared somehow weired to me related to the consideration of having thread issues. But then I figured that the name actually already suggests how it is handled. Since it's a fixed value, instances of org.activiti.engine.impl.el.FixedValue probably exists only once per workflow deployment and are shared amongst all process instances. Is that right?

2) In our class implementing the Java Service Task, which is shared amongst almost all Service Task elements in our workflow models, we are passing the map of process variables (retrieved from the DelegateExecution via the method getVariables()) to the OSGi service actually implementing the according task. Is that passing thread-safe, too? It should be right, because it's just a passing of a reference to a map and that map should exist per execution… Can you please confirm that thinking?

Thanks again for your hints.

Best regards
Timo Rohrberg

jbarrez
Star Contributor
Star Contributor
@Timo: did you see this issue https://github.com/Activiti/Activiti/issues/890? I think it is exactly what you're talking about

1) The one with .delegate in it is the one you should use. The other one will be removed in the future (and is already removed in v6)

2) That is thread-safe, but it could be that you have multiple nodes working on the same variables of course … in that case it's not really 'safe'