|
From: Rod J. <rod...@in...> - 2003-05-02 21:18:45
|
JP, Dmitriy,
Juergen has described the callback template. I've just finished the first
usable cut of the AOP declarative tx management. I'm very excited about
this. It still has some limitations, but I think it's ready to try to anger.
Here's a summary of how it works. Also see the tests for
com.interface21.aop.interceptor.transaction. BeanFactoryTransactionTests and
the XML file, from which I've pasted the following.
The mechanism behind it is AOP. This means that we have an interface, a set
of interceptors in a chain, invoked in a given order, and (usually) a target
object, that actually implements the interface. (The InvokerInterceptor
invokes the target reflectively. A target isn't required if the last
interceptor in the chain wants to do something else.)
The developer's responsibility is to configure the target, interceptors and
AOP proxy as beans. So in the XML format it will be something like this:
Define the target. Just an ordinary bean definition:
<bean name="target" class="com.interface21.beans.TestBean">
<property name="name">Rod</property>
<property name="age">32</property>
</bean>
Define any interceptors you want. Of course the bean definitions can be in
any order, as usual. The interceptors must implement the
org.aopalliance.MethodInterceptor interface. I've included a debug
interceptor, which logs to the console:
<bean name="debugInterceptor"
class="com.interface21.aop.interceptor.misc.DebugInterceptor">
</bean>
You'll need to configure a transaction interceptor. These are threadsafe, so
all AOP proxies can share one singleton instance. The most interesting thing
here is the transactionAttributeSource, which can be a string representation
of the transaction rules. See the TransactionAttributeSourceEditor class and
tests for descriptions. The format is
FQN.methodName=PROPAGATION_CODE,[ISOLATION_CODE,rollback_rules*]
where codes are the constant names in PLATFORM_TRANSACTION_MANAGER. For
example:
<bean name="txInterceptor"
class="com.interface21.aop.interceptor.transaction.TransactionInterceptor">
<property name="transactionAttributeSource">
com.interface21.beans.ITestBean.setAge=PROPAGATION_REQUIRED
</property>
</bean>
Here I've only described one method, but other methods can be on separate
lines. Rollback rules look like
+ServletException,-MyException
This means commit on ServletException or subclasses, but rollback on
MyException and subclasses. With no explicit rollback rules it behaves like
EJB, with rollback on unchecked. Configurable rollback is the one thing that
the AOP approach can do that the TransactionTemplate can't (besides the
transparent declarative model). And it's a capability that EJB doesn't have.
I've always been disappointed to have to explicitly rollback on checked
exceptions, as I typically want these to cause transaction rollback.
Now you declare the factory bean from which you'll get references. Note that
you specify the proxy interfaces, and the interceptor names. These are the
names of beans. Note that the last one is the target bean: an
InvokerIntercepter will be created automatically. I added the FactoryBean
functionality: see the tests to understand this, as it's not AOP specific.
<bean name="txtest"
class="com.interface21.aop.framework.ProxyFactoryBean"
>
<property
name="proxyInterfaces">com.interface21.beans.ITestBean</property>
<property
name="interceptorNames">debugInterceptor,txInterceptor,target</property>
</bean>
And that's that. You ask for beans from the FactoryBean, not the target, but
the proxying and interception is completely transparent. Like this:
ITestBean tb = (ITestBean) beanFactory.getBean("txtest");
When the transaction interceptor finds a method with a tx descriptor, it
creates a transaction. It commits on success, and rolls back if the user
sets rollback only (see TransactionInterceptorTests for how to do this) or
if it throws an exception that its rollback rules say should cause rollback.
Rollback only on runtime exceptions if no explicit rollback rules.
The transaction and other interceptors do not change any exceptions thrown.
Whether or not the tx interceptor rolls back, it will return exactly the
same exception to the client. The transaction interceptor does nothing but
pass through to the next interceptor if there's no transaction descriptor.
I've done some profiling and the performance overhead seems small.
It should be solid now--the tests are pretty thorough. The limitations are:
- must use fully qualified class name
- no support for method overloading
- no wildcards
Ultimately I think the best approach is transaction descriptors in source
files, as metadata attributes, as in .NET. I've partially implemented this
using Attrib4j, but Attrib4j still lacks some features I need. You'll need
Attrib4j jar to get the example to work as it's referenced by the
TransactionAttribute.
If you want to customize transaction management, you can set the
platformTransactionManager property of the TransactionTemplate. Default is
JtaTransactionManager.
I'd encourage you to try it, and appreciate any feedback on both usability
and functionality.
Regards,
Rod
----- Original Message -----
But a main topic rests unclear to me apart certain parts: the
transactions.
Could anyone (I think especially to Jüergen or Rod), give a roadmap or a
tiny example of their use. If possible, for the two ways, programmatic
and declarative.
For the programmatic way, the question could simply be : if a
TransactionTemplate.execute() method throws an exception, are the RDBMS
operations in earlier execute() calls with the same template or earlier
executed in the same execute call rollbacked ?
-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
Springframework-developer mailing list
Spr...@li...
https://lists.sourceforge.net/lists/listinfo/springframework-developer
|