Saturday, September 20, 2008
When is NEVER ever ?
During one of today's NFJS sessions, Transaction Design Patterns by Mark Richards, the audience were asked when it would make sense to specify the transaction attribute NEVER in a real-life application.
My immediate answer to this was that if a method is known to never get involved in a transactional context, then specifying NEVER would allow the application to fail fast. But what would be the practical circumstances where a method should never get involved in a transaction, to the extent of potentially causing an exception in production ? And if there weren't really such circumstances, why not use the SUPPORTS attribute instead ? Asked Richard.
On second thought, maybe we can use the NEVER attribute a lot more often and useful than it now is. Let me explain.
Consider the transaction attribute REQUIRES_NEW, which basically creates a new transaction if one doesn't already exist. But what if there already exists a transaction ? Instead of throwing an exception, like NEVER, it would suspend the current transaction and creates a new one. However, suspending a transaction is both expensive and usually not the intended semantics, as Richard pointed out.
So wouldn't it be nice if there exists a transaction attribute
Here is what I think could achieve the NEVER_REQUIRES_NEW transaction semantics, assuming the service method name is M:
Is this yet another Transaction Design Pattern ? The use of NEVER could be forever changed :)
My immediate answer to this was that if a method is known to never get involved in a transactional context, then specifying NEVER would allow the application to fail fast. But what would be the practical circumstances where a method should never get involved in a transaction, to the extent of potentially causing an exception in production ? And if there weren't really such circumstances, why not use the SUPPORTS attribute instead ? Asked Richard.
On second thought, maybe we can use the NEVER attribute a lot more often and useful than it now is. Let me explain.
Consider the transaction attribute REQUIRES_NEW, which basically creates a new transaction if one doesn't already exist. But what if there already exists a transaction ? Instead of throwing an exception, like NEVER, it would suspend the current transaction and creates a new one. However, suspending a transaction is both expensive and usually not the intended semantics, as Richard pointed out.
So wouldn't it be nice if there exists a transaction attribute
NEVER_REQUIRES_NEWthat would both guarantee there is no pre-existing transaction when a method is invoked, and then proceed to always create a new transaction ? But there is no such transaction attribute either in JEE 5, nor in Spring.
Here is what I think could achieve the NEVER_REQUIRES_NEW transaction semantics, assuming the service method name is M:
- Split method M into M1 and M2, and move the implementation of M to M2;
- M1 is a no-op annotated with the transaction attribute NEVER, whereas M2 is annotated with REQUIRES_NEW;
- Provide a proxy service that always invokes M1 followed by M2, exposing in turn to the client only a service method M without any transactional annotation;
Is this yet another Transaction Design Pattern ? The use of NEVER could be forever changed :)