cancel
Showing results for 
Search instead for 
Did you mean: 

Spring DB Transactions Not Rolled Back (ACT-1050)

tidetom
Champ in-the-making
Champ in-the-making
Hi all,

I just thought I'd see if there was any thought or traction on the below item created by JIRA member Vlastimil earlier this year:

http://codehaus01-new.managed.contegix.com/browse/ACT-1050

This issue is particularly troubling for Spring users, because default transaction management would dictate that the transactions made within a session be rolled back automatically when the exception gets propagated out of a flow.  As it is right now, since the exception gets caught by the AtomicOperationProcessEnd class and simply logged, so the default transaction manager will never have the opportunity to roll back the flow.

As it is now, the workaround is pretty complex, requiring explicit transaction commit and rollback in the Spring bean which invokes the flow (back to the old days … yuck!)

Is there a specific reason why the exceptions thrown out of a ServiceTask are caught and then logged rather than thrown up the stack?

I noticed that the item is marked as "Critical" (agreed!), but is not assigned to any release.  Given that there's a workaround posted, would it be possible to accelerate this into the 5.9 release?

Thanks in advance,
Tom
5 REPLIES 5

heymjo
Champ on-the-rise
Champ on-the-rise
Not into the details here, but if the exception would propagate up the callstack and the global tx is rolled back wouldn't that also mean that all records on the Activiti db itself will be rolled back ? And wouldn't that mean that Activiti would consider the service task as never executed ? Just wondering the impact on the engine database state after a global rollback.

tidetom
Champ in-the-making
Champ in-the-making
Hi Jorg,

Thank you for your quick reply.  I understand your concern that auditing and tracking behavior in Activiti would then not be able to commit, however doesn't following this paradigm mean that all application logic must then follow in the exact same path?  And that being the case, wouldn't it mean that we if we have ServiceTask (A) and ServiceTask (B) in a flow (where B follows A), changes in A are atomic and B are atomic, but we will never be able to have changes in both A and B be committed atomically?  This doesn't seem like it can be correct, because it would force all logic and commits to be placed in a single ServiceTask (defeating the visibility that Activiti otherwise provides).

Am I misunderstanding the situation?

Thanks again,
Tom

heymjo
Champ on-the-rise
Champ on-the-rise
Hi Tom,

IMO service tasks should execute atomic units of work, this means that executing A without B should lead to a valid, defined and acceptable business state. If this is not the case then A and B should not be separate service tasks. In terms of tx that means both A and B must execute in a separate transaction from each other, and each time the activiti engine state updates to the db should join the respective transaction of the service task.

My point was then if A rolls back there will be no trace of it in the activiti database. This would then require some sort of audit log that tracks progress independent of ongoing transactions. Does Activiti write its history and audit records in a separate transaction or not ?

tidetom
Champ in-the-making
Champ in-the-making
Hi Jorg,

I think the idea that each ServiceTask is atomic would be ok if Activiti is rarely used, or used at a very high level (i.e. similarly to the examples on the tutorial).  If, however, Activiti is used for more low-level business logic, or used for more complex flows, this idea would fail at providing what Activiti programmers need. 

To give you an idea of scope, we generally have over 100 service tasks in a flow with configurable paths through the flow, often times utilizing sub-flows to get what we need.  We chose Activiti because of the complexity and configurability of the business logic that we must provide, and utilize Activiti to give our developers and BAs insight into how the flows work.  About 10% of those service tasks perform Create, Update, and/or Delete operations in the database.  Some are done conditionally.  If we weren't able to carry a session across flows, what would that mean for our flows?  Well, essentially the "flow" would be "start" -> "serviceTask" (which does 100% of the complex logic in Java) -> "end".  Not much of a flow there anymore.

Taking it down a notch, imagine a very simple flow, wherein based we enter into the "startEvent", then perform a "create" operation on the database, then evaluate some conditional statement (xor).  If the condition is true, we update another database record.  If the condition is false, we end.  Per the model you propose, the create and the update happen as atomic operations, and thus the create would not be able to be rolled back.  This cannot possibly be how Activiti plans to handle this situation, it would be completely usable.

@Activiti, I'd be interested if the Activiti development team has any input into this conversation.  Are ServiceTasks meant to execute all CRUD operations atomically per ServiceTask, or are sessions allowed/expected to be carried between tasks?

heymjo
Champ on-the-rise
Champ on-the-rise
Hi,

It's an interesting discussion though. You are using Activiti to model and externalize (or orchestrate) the low-level call flow between service classes. I am not entirely sure this is what BPMN is good at, but then again i'm not a bpm expert by any means. Indeed we use it to model higher-level process with lots of user interaction, the low level business calls are collapsed into one or several service classes depending on where the (transactional) boundaries of the service call are.

In your example, if you want to rollback the create operation on the database if the xor statement is false then you could use a compensating transaction that does a delete.

Indeed it would be nice to have some input from the devs on how transactionality should / can be modelled in the engine.