cancel
Showing results for 
Search instead for 
Did you mean: 

JTA and starting processes

tdtappe
Confirmed Champ
Confirmed Champ
I just started using Activiti. So my question(s) might be a bit "strange". Anyway…

I am using Activiti embedded in my app in a JTA context. When I for instance create a new order I start an order process via API.
The problem: the process starts right away without my order data having been committed yet. So in case the process initiates a service (REST) to do something
with the order it won't find the data. The same problem occurs when my order data is updated. In this case I "trigger" the process to see if it can proceed.
So I am looking for a way to kind of "defer" the start/triggering of the process to the point when the data has been committed - namely the end/commit of
the JTA transaction. Is there anything like this for Activiti?

Some workaround that comes to my mind is using suspension of processes combined with some Quartz scheduler. So in case of an order being updated I suspend
the process and the scheduler is looking for suspended processes every 5 seconds or so and activates them. This won't work for new processes though.
For this to work I need some additional dummy task right at the beginning of the/each process definition. Now the process can be started and will wait
at the dummy task. Then I can suspend the process and it will be activated by the scheduler and can proceed - able to read the committed data.

As you can see this very tedious and I don't like it at all.

So any help is highly appreciated.

–Heiko
7 REPLIES 7

p4w3l
Champ in-the-making
Champ in-the-making
Why not commit tx then start a process with :

runtimeService.startProcessInstanceByKey( pKey, variables );
?

tdtappe
Confirmed Champ
Confirmed Champ
Because it runs in a JTA context. The "container" handles the transactions. And there might be more stuff to do after creating an order for instance. And it should be an "all or nothing" approach.

frederikherema1
Star Contributor
Star Contributor
Activiti allows you to participate in a JTA-transaction, effectively not committing changes manually but relying on the container to do this. You'll have to use the JPAProcessEngineConfiguration instead of the normal one and hook in the transaction manager.

tdtappe
Confirmed Champ
Confirmed Champ
I know. And that's what I do already: the process engine is configured to use JTA. But the problem is that obviously the process starts immediately and reaches for instance a point in the process where it's necessary to get some information. This information (for a conditional flow) is "fetched" via a CDI function that in turn calls some REST function to get the desired information. But this REST call won't find the current data as the transaction that initiated all this isn't committed yet.

1) Container starts transaction
2) The application creates some data which is persisted (but of course not committed) to the database
3) The application then starts a process for this new data object
4) Container commits transaction

In the context of 3) a REST function call (initiated by the process) reaches the app which then tries to find the object in the database. But of course it isn't there yet => BANG

frederikherema1
Star Contributor
Star Contributor
That's not an activiti-specific problem, that is a generic problem where you try to combine non-transactional calls (REST) with transactional things. A solution would be to make the ServiceTask that is performing the REST-call, asynchronous. This way, when the process is started and reaches that serviceTask, it will be persisted/comitted to the database and the job executor will execute the REST-operation asynchronously in a new transaction. Since the process is now persisted, the REST can access it.

tdtappe
Confirmed Champ
Confirmed Champ
Ok. So "async" could be a solution. But also in this case where I use a CDI object inside a sequence flow expression to get the information on how to proceed?
Or what else can I do?

frederikherema1
Star Contributor
Star Contributor
Make sure the CDI-object in the sequence-flow is AFTER the async-tasks to make sure the REST-call won't fail due to uncommitted data…