This week I’m delivering a BizTalk development class for my colleagues, and during my preparation of demonstrations, I spent a few extra minutes confirming the behavior of members variables and atomic transactions.
Atomic transactions in BizTalk don’t necessarily behave like some folks expect. For instance, if a BizTalk orchestration calls a component with ADO.NET code which updates a database, and then raises an error later in the atomic scope, this will NOT cause that database operation to be rolled back. In another example, if you place a “send” shape inside an atomic scope, and a later operation fails, BizTalk doesn’t roll back the send operation. It’s standard design to use BizTalk “compensation” to execute logic to roll back any operations performed in the atomic scope.
Darren’s excellent BizTalk book states that there are realistically three scenarios where a developer will use atomic transactions in a BizTalk orchestration:
- Using a class not marked as serializable
- Calling a COM+ component that’s participating in the orchestration transaction
- Minimizing persistence points
However, don’t assume that atomic transactions in BizTalk are completely neutered. There are cases that you would want to use an atomic transaction as a part of your actual process.
In this scenario, my orchestration has two variables. One references a custom .NET data object (Employee), and the other variable is a simple string. After receiving a message into the orchestration, I instantiate those variables with default values and print them out.
Next, I have an atomic transaction which changes the value of both variables, prints them, and then throws an error. Immediately after the atomic scope, I print the variable values once more. As you can see here, I’ve also wrapped the atomic scope inside a long-running scope so that I can swallow the error and move on gracefully.
What do you expect to happen? Does the orchestration reset the member variable only, or also the custom .NET object’s member value?
As you can see, both variables start off with values of “started up”, inside the atomic scope the value switches to “changed status”, and after the exception is thrown within the atomic scope, the values get reset to their pre-atomic scope values. It makes perfect sense since changes occurring within the atomic scope don’t commit until the transaction is complete, but, it’s always useful to test it.
Now, this scope behavior does not extend much beyond this. If I add a function to my “Employee” class which writes a file to disk, and I call that operation within the atomic scope, the exception does NOT cause that operation to roll back. The file stays on my drive even after the orchestration has completed. That’s a scenario where compensation would be needed.
Technorati Tags: BizTalk
“if you place a “send” shape inside an atomic scope, and a later operation fails, BizTalk doesn’t roll back the send operation” – I believe that doesn’t perform the send operation at all until the atomic scope is completed successfully?
I didn’t believe your statement, but I tried it out, and you’re right. If I threw a “send” shape in my above orchestration directly above the “throw exception”, no message was sent out. I also found Tomas’ article that mentions this (http://www.winterdom.com/weblog/CommentView,guid,450.aspx). I’ll have to try a few more scenarios, however. If I have a send + receive in the atomic scope, wouldn’t I HAVE to commit the send to the MessageBox in order to call the destination system and receive a response? These are questions that keep me up at night.
It’s also a question in the BizTalk 2004 exam. I have also wondered what happens if you have a send/receive in an atomic scope – it feels like the send must commit. Other questions that keep me up at night include: why can’t an atomic scope have an exception handler, but a non-transactional scope nested within an atomic scope can? Still, if BizTalk didn’t pose us at least one troublesome question a day, we might as well do Java 😉
Ok, you CAN’T have a send + receive inside an atomic scope. Doesn’t compile. After remembering that I even wrote about this a while back (http://blogs.msdn.com/richardbpi/archive/2005/07/14/438920.aspx), I do remember using delivery notification to handle the exception notification for a send port inside an atomic scope.
Hello another use of atomic transaction scope is to implement retries.
Exemple :
– in the atomic you put a non atomic scope with an exception handler.
– in the non atomic scope you call a .net object which may throw an exception.
– in the exception handler you throw a RetryTransactionException ( You can specify how many time to wait with the DelayFor property)
In case of exception it will retry the whole atomic scope up to 20 times
Thanks for putting this forward. The concepts are really clear.