| By Peter Holditch | Article Rating: |
|
| March 26, 2002 12:00 AM EST | Reads: |
7,879 |
As we've discussed over the past few issues, JTA-style transactions provide a way for multiple data updates to be tied together so application logic can operate safely in the assumption that it will succeed or fail consistently, even in the face of technical failures along the road.
There are, however, times when you do not want all the work you do to succeed or fail in one big lump.
Among the scenarios that may lead you to want to break work up into smaller chunks are:
- Progress/error logging
- Long-running operations
- Wide-spanning operations
The first point, about logging, is more of a business logicdriven consideration. Many people use databases to record events in their systems. Take the example of an audit log. Imagine a banking application that logs all fund movements. Imagine also a teller trying to fraudulently withdraw $10,000 from some account. In order to track the fraud, the application users are likely to want to look through the audit log. If the fraudster had tried 1,000 withdrawals, then the auditors would want to see 1,000 pieces of evidence. They would be pretty ticked off if they only saw 900 records, since 100 withdrawals failed, and the writing of the log records rolled back with the failed withdrawals. Clearly, the log record cannot be written in the same transaction as the withdrawal.
Transactions: Where Do They Live?
When you write the code to start an XA transaction, it's associated with the thread of execution, and irrespective of what methods in whatever classes you call, any database connections that you get and use will inherit the transaction context from the thread. Thus, when the transaction is finally committed, all the work that you've caused to be done whether or not it was in utility classes that you don't even know the contents of will complete as a transactional atomic unit. Given that the transaction lives in the thread and is so pervasive, how do you break up the work done by your thread of control into multiple transactions?
Transactions, What A State!
The answer to this problem is that transactions can be in more states than simply active or inactive. They can also be suspended. A suspended transaction is still not complete the timer controlling the timeouts etc. is still running, and can roll back of its own accord if the timeout is exceeded but it's no longer associated with the current thread of execution.
Now, you're at liberty to start a new one, if you like (in our example above it's this transaction that would be responsible for the audit-log writing) This new transaction is quite independent of the old one it can commit or abort as required by its own business semantics and after whatever logic it represents has completed, the old transaction can be resumed and carry on where it left off (provided it didn't time out behind your back, as previously noted).
Anyone For Tennis?
In fact, for the real rocket scientist, a transaction can be suspended in one thread and resumed in a different one, which means that your code can play "transaction tennis," passing transaction objects back and forth as it pleases. This is, however, a very bad idea. For maximum reuse, code should leave the transactional state as it found it. If you're writing a class that is making all kinds of assumptions about the state of the current transaction, then the chances of it being useful in another future situation are pretty limited. It's a basic rule of encapsulation that you shouldn't expose your inner workings through your interfaces, and transactions fall firmly into the category of inner workings. By all means, write code that suspends the current transaction (if any) before performing operations that need to be self-contained, so long as the transaction is resumed again afterwards. Because transactions are omnipresent in a thread, you need to make sure you don't code any nasty surprises for yourself. As we all know, there is no more difficult bug to track than one that involves the operating environment changing unexpectedly. That, after all, is why the Java language excommunicated the concept of the pointer.
Published March 26, 2002 Reads 7,879
Copyright © 2002 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Peter Holditch
Peter Holditch is a senior presales engineer in the UK for Azul Systems. Prior to joining Azul he spent nine years at BEA systems, going from being one of their first Professional Services consultants in Europe and finishing up as a principal presales engineer. He has an R&D background (originally having worked on BEA's Tuxedo product) and his technical interests are in high-throughput transaction systems. "Of the pitch" Peter likes to brew beer, build furniture, and undertake other ludicrously ambitious projects - but (generally) not all at the same time!
- Transactions, Suspension, and the Ticking Clock
- Transactions: Driving You to Distraction?
- WebLogic Performance: Pursuit of Speed Isn't Everything
- Transactions: How Distributed Are Yours?
- Measuring the Value of Software Infrastructure
- And Now for Something Completely Different
- Avoiding Middle-Aged Spread for Your WebLogic Infrastructure
- Notes from a Small Place
- Is the Glass Half Full or Half Empty?
- Transaction Not Supported? Just Say No!
- How Loose is Your Coupling?
- Transactions for the Next Generation























