diff --git a/spring-framework-reference/src/aop-api.xml b/spring-framework-reference/src/aop-api.xml index c75afa077c1..eaf125e0d95 100644 --- a/spring-framework-reference/src/aop-api.xml +++ b/spring-framework-reference/src/aop-api.xml @@ -1,29 +1,28 @@ - +"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> Spring AOP APIs
Introduction - The previous chapter described the Spring 2.0 support for AOP using - @AspectJ and schema-based aspect definitions. In this chapter we discuss - the lower-level Spring AOP APIs and the AOP support used in Spring 1.2 applications. - For new applications, we recommend the use of the Spring 2.0 AOP support - described in the previous chapter, but when working with existing applications, - or when reading books and articles, you may come across Spring 1.2 style examples. - Spring 2.0 is fully backwards compatible with Spring 1.2 and everything described - in this chapter is fully supported in Spring 2.0. - - + The previous chapter described the Spring 2.0 and later version's + support for AOP using @AspectJ and schema-based aspect definitions. In + this chapter we discuss the lower-level Spring AOP APIs and the AOP + support used in Spring 1.2 applications. For new applications, we + recommend the use of the Spring 2.0 and later AOP support described in the + previous chapter, but when working with existing applications, or when + reading books and articles, you may come across Spring 1.2 style examples. + Spring 3.0 is backwards compatible with Spring 1.2 and everything + described in this chapter is fully supported in Spring 3.0.
Pointcut API in Spring - Let's look at how Spring handles the crucial pointcut concept. + Let's look at how Spring handles the crucial pointcut + concept.
Concepts @@ -36,40 +35,40 @@ is the central interface, used to target advices to particular classes and methods. The complete interface is shown below: - public interface Pointcut { ClassFilter getClassFilter(); MethodMatcher getMethodMatcher(); -}]]> +} - Splitting the Pointcut interface into two parts - allows reuse of class and method matching parts, and fine-grained - composition operations (such as performing a "union" with another method - matcher). + Splitting the Pointcut interface + into two parts allows reuse of class and method matching parts, and + fine-grained composition operations (such as performing a "union" with + another method matcher). - The ClassFilter interface is used to restrict - the pointcut to a given set of target classes. If the + The ClassFilter interface is used + to restrict the pointcut to a given set of target classes. If the matches() method always returns true, all target classes will be matched: - public interface ClassFilter { boolean matches(Class clazz); -}]]> +} - The MethodMatcher interface is normally more - important. The complete interface is shown below: + The MethodMatcher interface is + normally more important. The complete interface is shown below: - public interface MethodMatcher { boolean matches(Method m, Class targetClass); boolean isRuntime(); boolean matches(Method m, Class targetClass, Object[] args); -}]]> +} The matches(Method, Class) method is used to test whether this pointcut will ever match a given method on a target @@ -86,11 +85,11 @@ isRuntime() method returns false. In this case, the 3-argument matches method will never be invoked. - - If possible, try to make pointcuts static, allowing the AOP - framework to cache the results of pointcut evaluation when an AOP proxy - is created. - + + If possible, try to make pointcuts static, allowing the AOP + framework to cache the results of pointcut evaluation when an AOP + proxy is created. +
@@ -99,25 +98,28 @@ Spring supports operations on pointcuts: notably, union and intersection. - - - Union means the methods that either pointcut matches. - - - Intersection means the methods that both pointcuts match. - - - Union is usually more useful. - - - Pointcuts can be composed using the static methods in the - org.springframework.aop.support.Pointcuts class, or - using the ComposablePointcut class in the same - package. However, using AspectJ pointcut expressions is usually a - simpler approach. - - + + + Union means the methods that either pointcut matches. + + + Intersection means the methods that both pointcuts + match. + + + + Union is usually more useful. + + + + Pointcuts can be composed using the static methods in the + org.springframework.aop.support.Pointcuts + class, or using the ComposablePointcut class in + the same package. However, using AspectJ pointcut expressions is + usually a simpler approach. + +
@@ -125,12 +127,11 @@ Since 2.0, the most important type of pointcut used by Spring is org.springframework.aop.aspectj.AspectJExpressionPointcut. - This is a pointcut that uses an AspectJ supplied library to parse an AspectJ - pointcut expression string. + This is a pointcut that uses an AspectJ supplied library to parse an + AspectJ pointcut expression string. - See the previous chapter for a discussion of supported AspectJ pointcut - primitives. - + See the previous chapter for a discussion of supported AspectJ + pointcut primitives.
@@ -145,10 +146,10 @@ Static pointcuts are based on method and target class, and cannot take into account the method's arguments. Static pointcuts are - sufficient - and best - for most usages. It's possible for Spring to - evaluate a static pointcut only once, when a method is first invoked: - after that, there is no need to evaluate the pointcut again with each - method invocation. + sufficient - and best - for most usages. It's + possible for Spring to evaluate a static pointcut only once, when a + method is first invoked: after that, there is no need to evaluate the + pointcut again with each method invocation. Let's consider some static pointcut implementations included with Spring. @@ -188,8 +189,8 @@ also reference an Advice (remember that an Advice can be an interceptor, before advice, throws advice etc.). Behind the scenes, Spring will use a JdkRegexpMethodPointcut. Using - RegexpMethodPointcutAdvisor simplifies wiring, - as the one bean encapsulates both pointcut and advice, as shown + RegexpMethodPointcutAdvisor simplifies wiring, as + the one bean encapsulates both pointcut and advice, as shown below: <bean id="settersAndAbsquatulateAdvisor" @@ -236,17 +237,18 @@ Spring control flow pointcuts are conceptually similar to AspectJ cflow pointcuts, although less powerful. (There is currently no way to specify that a pointcut - executes below a join point matched by another pointcut.) - A control flow pointcut matches - the current call stack. For example, it might fire if the join point - was invoked by a method in the com.mycompany.web - package, or by the SomeCaller class. Control flow - pointcuts are specified using the + executes below a join point matched by another pointcut.) A control + flow pointcut matches the current call stack. For example, it might + fire if the join point was invoked by a method in the + com.mycompany.web package, or by the + SomeCaller class. Control flow pointcuts are + specified using the org.springframework.aop.support.ControlFlowPointcut class. Control flow pointcuts are significantly more expensive to - evaluate at runtime than even other dynamic pointcuts. In Java 1.4, - the cost is about 5 times that of other dynamic pointcuts. + evaluate at runtime than even other dynamic pointcuts. In Java + 1.4, the cost is about 5 times that of other dynamic + pointcuts.
@@ -284,10 +286,10 @@ language is recommended if possible. - Later versions of Spring may offer support for "semantic - pointcuts" as offered by JAC: for example, "all methods that change - instance variables in the target object." - + Later versions of Spring may offer support for "semantic + pointcuts" as offered by JAC: for example, "all methods that change + instance variables in the target object." + @@ -299,11 +301,10 @@
Advice lifecycles - Each advice is a Spring bean. An advice instance can be shared across all - advised objects, or unique - to each advised object. This corresponds to - per-class or per-instance - advice. + Each advice is a Spring bean. An advice instance can be shared + across all advised objects, or unique to each advised object. This + corresponds to per-class or + per-instance advice. Per-class advice is used most often. It is appropriate for generic advice such as transaction advisors. These do not depend on the state of @@ -341,10 +342,10 @@ } The MethodInvocation argument to the - invoke() method exposes the method being invoked; - the target join point; the AOP proxy; and the arguments to the method. - The invoke() method should return the - invocation's result: the return value of the join point. + invoke() method exposes the method being + invoked; the target join point; the AOP proxy; and the arguments to + the method. The invoke() method should return + the invocation's result: the return value of the join point. A simple MethodInterceptor implementation looks as follows: @@ -361,21 +362,23 @@ Note the call to the MethodInvocation's proceed() method. This proceeds down the - interceptor chain towards the join point. Most interceptors will invoke - this method, and return its return value. However, a + interceptor chain towards the join point. Most interceptors will + invoke this method, and return its return value. However, a MethodInterceptor, like any around advice, can return a different value or throw an exception rather than invoke the proceed method. However, you don't want to do this without good reason! - MethodInterceptors offer interoperability with other AOP - Alliance-compliant AOP implementations. The other advice types - discussed in the remainder of this section implement common AOP - concepts, but in a Spring-specific way. While there is an advantage in - using the most specific advice type, stick with MethodInterceptor - around advice if you are likely to want to run the aspect in another - AOP framework. Note that pointcuts are not currently interoperable - between frameworks, and the AOP Alliance does not currently define - pointcut interfaces. + + MethodInterceptors offer interoperability with other AOP + Alliance-compliant AOP implementations. The other advice types + discussed in the remainder of this section implement common AOP + concepts, but in a Spring-specific way. While there is an advantage + in using the most specific advice type, stick with MethodInterceptor + around advice if you are likely to want to run the aspect in another + AOP framework. Note that pointcuts are not currently interoperable + between frameworks, and the AOP Alliance does not currently define + pointcut interfaces. +
@@ -401,14 +404,14 @@ void before(Method m, Object[] args, Object target) throws Throwable; } - Note the return type is void. Before - advice can insert custom behavior before the join point executes, but - cannot change the return value. If a before advice throws an - exception, this will abort further execution of the interceptor chain. - The exception will propagate back up the interceptor chain. If it is - unchecked, or on the signature of the invoked method, it will be - passed directly to the client; otherwise it will be wrapped in an - unchecked exception by the AOP proxy. + Note the return type is void. Before advice + can insert custom behavior before the join point executes, but cannot + change the return value. If a before advice throws an exception, this + will abort further execution of the interceptor chain. The exception + will propagate back up the interceptor chain. If it is unchecked, or + on the signature of the invoked method, it will be passed directly to + the client; otherwise it will be wrapped in an unchecked exception by + the AOP proxy. An example of a before advice in Spring, which counts all method invocations: @@ -426,7 +429,9 @@ } } - Before advice can be used with any pointcut. + + Before advice can be used with any pointcut. +
@@ -447,27 +452,28 @@ method is interested in the method and arguments. The following classes are examples of throws advice. - The advice below is invoked if a RemoteException - is thrown (including subclasses): + The advice below is invoked if a + RemoteException is thrown (including + subclasses): - public class RemoteThrowsAdvice implements ThrowsAdvice { public void afterThrowing(RemoteException ex) throws Throwable { - ]]>// Do something with remote exception// Do something with remote exception } -}]]> +} The following advice is invoked if a - ServletException is thrown. Unlike the above - advice, it declares 4 arguments, so that it has access to the invoked - method, method arguments and target object: + ServletException is thrown. Unlike the + above advice, it declares 4 arguments, so that it has access to the + invoked method, method arguments and target object: - public class ServletThrowsAdviceWithArguments implements ThrowsAdvice { public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) { - ]]>// Do something with all arguments// Do something with all arguments } -}]]> +} The final example illustrates how these two methods could be used in a single class, which handles both @@ -486,15 +492,20 @@ } } - Note: If a throws-advice method throws an exception itself, - it will override the original exception (i.e. change the exception thrown to the user). - The overriding exception will typically be a RuntimeException; this is compatible with - any method signature. However, if a throws-advice method throws a checked exception, - it will have to match the declared exceptions of the target method and is hence to some - degree coupled to specific target method signatures. Do not throw an undeclared - checked exception that is incompatible with the target method's signature! + Note: If a throws-advice method throws an + exception itself, it will override the original exception (i.e. change + the exception thrown to the user). The overriding exception will + typically be a RuntimeException; this is compatible with any method + signature. However, if a throws-advice method throws a checked + exception, it will have to match the declared exceptions of the target + method and is hence to some degree coupled to specific target method + signatures. Do not throw an undeclared checked exception + that is incompatible with the target method's + signature! - Throws advice can be used with any pointcut. + + Throws advice can be used with any pointcut. +
@@ -535,27 +546,42 @@ exception, this will be thrown up the interceptor chain instead of the return value. - After returning advice can be used with any pointcut. + + After returning advice can be used with any pointcut. +
+ + Introduction advice + + + Spring treats introduction advice as a special kind of interception advice. + + + Introduction requires an IntroductionAdvisor, and an IntroductionInterceptor, implementing the following interface: + + public interface IntroductionInterceptor extends MethodInterceptor { boolean implementsInterface(Class intf); } + + The invoke() method inherited from the AOP Alliance MethodInterceptor interface must implement the introduction: that is, if the invoked method is on an introduced interface, the introduction interceptor is responsible for handling - the method call - it cannot invoke proceed(). + the method call - it cannot invoke + proceed(). @@ -580,9 +606,9 @@ public interface IntroductionInfo { - There is no MethodMatcher, and hence no - Pointcut, associated with introduction advice. Only - class filtering is logical. + There is no MethodMatcher, and + hence no Pointcut, associated with + introduction advice. Only class filtering is logical. @@ -705,11 +731,11 @@ public interface IntroductionInfo { Often it isn't necessary to override the invoke() method: the - DelegatingIntroductionInterceptor - implementation - which calls the delegate method if the method is - introduced, otherwise proceeds towards the join point - is usually - sufficient. In the present case, we need to add a check: no setter - method can be invoked if in locked mode. + DelegatingIntroductionInterceptor implementation - + which calls the delegate method if the method is introduced, otherwise + proceeds towards the join point - is usually sufficient. In the + present case, we need to add a check: no setter method can be invoked + if in locked mode. @@ -760,8 +786,8 @@ public interface IntroductionInfo {
Advisor API in Spring - In Spring, an Advisor is an aspect that contains just a single advice - object associated with a pointcut expression. + In Spring, an Advisor is an aspect that contains just a single + advice object associated with a pointcut expression. Apart from the special case of introductions, any advisor can be used with any advice. @@ -780,15 +806,16 @@ public interface IntroductionInfo { Using the ProxyFactoryBean to create AOP proxies If you're using the Spring IoC container (an ApplicationContext or - BeanFactory) for your business objects - and you should be! - you will want - to use one of Spring's AOP FactoryBeans. (Remember that a factory bean - introduces a layer of indirection, enabling it to create objects of a + BeanFactory) for your business objects - and you should be! - you will + want to use one of Spring's AOP FactoryBeans. (Remember that a factory + bean introduces a layer of indirection, enabling it to create objects of a different type.) - - - The Spring 2.0 AOP support also uses factory beans under the covers. - - + + + The Spring 2.0 AOP support also uses factory beans under the + covers. + + The basic way to create an AOP proxy in Spring is to use the org.springframework.aop.framework.ProxyFactoryBean. This gives complete control over the pointcuts and advice that will apply, @@ -820,203 +847,197 @@ public interface IntroductionInfo {
JavaBean properties - - In common with most FactoryBean implementations - provided with Spring, the ProxyFactoryBean class is - itself a JavaBean. Its properties are used to: - + + In common with most FactoryBean + implementations provided with Spring, the + ProxyFactoryBean class is itself a JavaBean. Its + properties are used to: + Specify the target you want to proxy. + - Specify whether to use CGLIB (see below and also the section entitled - ). + Specify whether to use CGLIB (see below and also the section + entitled ). - - Some key properties are inherited from - org.springframework.aop.framework.ProxyConfig (the - superclass for all AOP proxy factories in Spring). These key properties include: - + + Some key properties are inherited from + org.springframework.aop.framework.ProxyConfig + (the superclass for all AOP proxy factories in Spring). These key + properties include: + - - proxyTargetClass: true if the - target class is to be proxied, rather than the target class' interfaces. - If this property value is set to true, then CGLIB proxies - will be created (but see also below the section entitled - ). - + proxyTargetClass: true + if the target class is to be proxied, rather than the target class' + interfaces. If this property value is set to + true, then CGLIB proxies will be created (but see + also below the section entitled ). + - - optimize: controls whether or not aggressive - optimizations are applied to proxies created via CGLIB. - One should not blithely use this setting unless one fully understands - how the relevant AOP proxy handles optimization. This is currently used only - for CGLIB proxies; it has no effect with JDK dynamic proxies. - + optimize: controls whether or not + aggressive optimizations are applied to proxies created + via CGLIB. One should not blithely use this setting + unless one fully understands how the relevant AOP proxy handles + optimization. This is currently used only for CGLIB proxies; it has + no effect with JDK dynamic proxies. + - frozen: if a proxy configuration is frozen, - then changes to the configuration are no longer allowed. This is useful both as - a slight optimization and for those cases when you don't want callers to be able - to manipulate the proxy (via the Advised interface) - after the proxy has been created. The default value of this property is - false, so changes such as adding additional advice are allowed. + frozen: if a proxy configuration is + frozen, then changes to the configuration are no + longer allowed. This is useful both as a slight optimization and for + those cases when you don't want callers to be able to manipulate the + proxy (via the Advised interface) + after the proxy has been created. The default value of this property + is false, so changes such as adding additional + advice are allowed. + - - exposeProxy: determines whether or not the current - proxy should be exposed in a ThreadLocal so that - it can be accessed by the target. If a target needs to obtain - the proxy and the exposeProxy property is set to - true, the target can use the - AopContext.currentProxy() method. - + exposeProxy: determines whether or not the + current proxy should be exposed in a + ThreadLocal so that it can be accessed by the + target. If a target needs to obtain the proxy and the + exposeProxy property is set to + true, the target can use the + AopContext.currentProxy() method. + - - aopProxyFactory: the implementation of - AopProxyFactory to use. Offers a way of - customizing whether to use dynamic proxies, CGLIB or any other proxy - strategy. The default implementation will choose dynamic proxies or - CGLIB appropriately. There should be no need to use this property; - it is intended to allow the addition of new proxy types in Spring 1.1. - + aopProxyFactory: the implementation of + AopProxyFactory to use. Offers a way + of customizing whether to use dynamic proxies, CGLIB or any other + proxy strategy. The default implementation will choose dynamic + proxies or CGLIB appropriately. There should be no need to use this + property; it is intended to allow the addition of new proxy types in + Spring 1.1. - - Other properties specific to ProxyFactoryBean include: - + + Other properties specific to + ProxyFactoryBean include: + - - proxyInterfaces: array of String interface - names. If this isn't supplied, a CGLIB proxy for the target class - will be used (but see also below the section entitled - ). - + proxyInterfaces: array of String interface + names. If this isn't supplied, a CGLIB proxy for the target class + will be used (but see also below the section entitled ). + - - interceptorNames: String array of - Advisor, interceptor or other advice - names to apply. Ordering is significant, on a first come-first served - basis. That is to say that the first interceptor in the list - will be the first to be able to intercept the invocation. - - - The names are bean names in the current factory, including - bean names from ancestor factories. You can't mention bean - references here since doing so would result in the - ProxyFactoryBean ignoring the singleton - setting of the advice. - - - You can append an interceptor name with an asterisk - (*). This will result in the application of all - advisor beans with names starting with the part before the asterisk - to be applied. An example of using this feature can be found in - . - + interceptorNames: String array of + Advisor, interceptor or other advice + names to apply. Ordering is significant, on a first come-first + served basis. That is to say that the first interceptor in the list + will be the first to be able to intercept the invocation. + + The names are bean names in the current factory, including + bean names from ancestor factories. You can't mention bean + references here since doing so would result in the + ProxyFactoryBean ignoring the singleton + setting of the advice. + + You can append an interceptor name with an asterisk + (*). This will result in the application of all + advisor beans with names starting with the part before the asterisk + to be applied. An example of using this feature can be found in + . + - - singleton: whether or not the factory should return a single - object, no matter how often the getObject() - method is called. Several FactoryBean - implementations offer such a method. The default value is - true. If you want to use stateful advice - - for example, for stateful mixins - use prototype advices along - with a singleton value of false. - + singleton: whether or not the factory should return a single + object, no matter how often the getObject() + method is called. Several FactoryBean + implementations offer such a method. The default value is + true. If you want to use stateful advice - for + example, for stateful mixins - use prototype advices along with a + singleton value of false.
- -
- JDK- and CGLIB-based proxies - - This section serves as the definitive documentation on how the - ProxyFactoryBean chooses to create one of - either a JDK- and CGLIB-based proxy for a particular target object - (that is to be proxied). - - - - The behavior of the ProxyFactoryBean with regard - to creating JDK- or CGLIB-based proxies changed between versions 1.2.x and - 2.0 of Spring. The ProxyFactoryBean now - exhibits similar semantics with regard to auto-detecting interfaces - as those of the TransactionProxyFactoryBean class. - - - - If the class of a target object that is to be proxied (hereafter simply - referred to as the target class) doesn't implement any interfaces, then - a CGLIB-based proxy will be created. This is the easiest scenario, because - JDK proxies are interface based, and no interfaces means JDK proxying - isn't even possible. One simply plugs in the target bean, and specifies the - list of interceptors via the interceptorNames property. - Note that a CGLIB-based proxy will be created even if the - proxyTargetClass property of the - ProxyFactoryBean has been set to false. - (Obviously this makes no sense, and is best removed from the bean - definition because it is at best redundant, and at worst confusing.) - - - If the target class implements one (or more) interfaces, then the type of - proxy that is created depends on the configuration of the - ProxyFactoryBean. - - - If the proxyTargetClass property of the - ProxyFactoryBean has been set to true, - then a CGLIB-based proxy will be created. This makes sense, and is in - keeping with the principle of least surprise. Even if the - proxyInterfaces property of the - ProxyFactoryBean has been set to one or more - fully qualified interface names, the fact that the - proxyTargetClass property is set to - true will cause - CGLIB-based proxying to be in effect. - - - If the proxyInterfaces property of the - ProxyFactoryBean has been set to one or more - fully qualified interface names, then a JDK-based proxy will be created. - The created proxy will implement all of the interfaces that were specified - in the proxyInterfaces property; if the target class - happens to implement a whole lot more interfaces than those specified in - the proxyInterfaces property, that is all well and - good but those additional interfaces will not be implemented by the - returned proxy. - - - If the proxyInterfaces property of the - ProxyFactoryBean has not been - set, but the target class does implement one (or more) - interfaces, then the ProxyFactoryBean will auto-detect - the fact that the target class does actually implement at least one interface, - and a JDK-based proxy will be created. The interfaces that are actually - proxied will be all of the interfaces that the target - class implements; in effect, this is the same as simply supplying a list - of each and every interface that the target class implements to the - proxyInterfaces property. However, it is significantly less - work, and less prone to typos. - +
+ JDK- and CGLIB-based proxies + + This section serves as the definitive documentation on how the + ProxyFactoryBean chooses to create one of either + a JDK- and CGLIB-based proxy for a particular target object (that is to + be proxied). + + + The behavior of the ProxyFactoryBean with + regard to creating JDK- or CGLIB-based proxies changed between + versions 1.2.x and 2.0 of Spring. The + ProxyFactoryBean now exhibits similar semantics + with regard to auto-detecting interfaces as those of the + TransactionProxyFactoryBean class. + + + If the class of a target object that is to be proxied (hereafter + simply referred to as the target class) doesn't implement any + interfaces, then a CGLIB-based proxy will be created. This is the + easiest scenario, because JDK proxies are interface based, and no + interfaces means JDK proxying isn't even possible. One simply plugs in + the target bean, and specifies the list of interceptors via the + interceptorNames property. Note that a CGLIB-based + proxy will be created even if the proxyTargetClass + property of the ProxyFactoryBean has been set to + false. (Obviously this makes no sense, and is best + removed from the bean definition because it is at best redundant, and at + worst confusing.) + + If the target class implements one (or more) interfaces, then the + type of proxy that is created depends on the configuration of the + ProxyFactoryBean. + + If the proxyTargetClass property of the + ProxyFactoryBean has been set to + true, then a CGLIB-based proxy will be created. This + makes sense, and is in keeping with the principle of least surprise. + Even if the proxyInterfaces property of the + ProxyFactoryBean has been set to one or more + fully qualified interface names, the fact that the + proxyTargetClass property is set to + true will cause CGLIB-based + proxying to be in effect. + + If the proxyInterfaces property of the + ProxyFactoryBean has been set to one or more + fully qualified interface names, then a JDK-based proxy will be created. + The created proxy will implement all of the interfaces that were + specified in the proxyInterfaces property; if the + target class happens to implement a whole lot more interfaces than those + specified in the proxyInterfaces property, that is + all well and good but those additional interfaces will not be + implemented by the returned proxy. + + If the proxyInterfaces property of the + ProxyFactoryBean has not + been set, but the target class does implement one (or + more) interfaces, then the + ProxyFactoryBean will auto-detect the fact that + the target class does actually implement at least one interface, and a + JDK-based proxy will be created. The interfaces that are actually + proxied will be all of the interfaces that the + target class implements; in effect, this is the same as simply supplying + a list of each and every interface that the target class implements to + the proxyInterfaces property. However, it is + significantly less work, and less prone to typos.
Proxying interfaces - - Let's look at a simple example of ProxyFactoryBean - in action. This example involves: - + Let's look at a simple example of + ProxyFactoryBean in action. This example + involves: @@ -1036,12 +1057,12 @@ public interface IntroductionInfo { <bean id="personTarget" class="com.mycompany.PersonImpl"> - <property name="name"><value>Tony</value></property> - <property name="age"><value>51</value></property> + <property name="name" value="Tony"/> + <property name="age" value="51"/> </bean> <bean id="myAdvisor" class="com.mycompany.MyAdvisor"> - <property name="someProperty"><value>Custom string property value</value></property> + <property name="someProperty" value="Custom string property value"/> </bean> <bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"> @@ -1049,9 +1070,9 @@ public interface IntroductionInfo { <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean"> - <property name="proxyInterfaces"><value>com.mycompany.Person</value></property> + <property name="proxyInterfaces" value="com.mycompany.Person"/> - <property name="target"><ref local="personTarget"/></property> + <property name="target" ref="personTarget"/> <property name="interceptorNames"> <list> <value>myAdvisor</value> @@ -1066,16 +1087,16 @@ public interface IntroductionInfo { throws advice objects can be used. The ordering of advisors is significant. - - You might be wondering why the list doesn't hold bean - references. The reason for this is that if the ProxyFactoryBean's - singleton property is set to false, it must be able to return - independent proxy instances. If any of the advisors is itself a - prototype, an independent instance would need to be returned, so it's - necessary to be able to obtain an instance of the prototype from the - factory; holding a reference isn't sufficient. - - + + You might be wondering why the list doesn't hold bean + references. The reason for this is that if the ProxyFactoryBean's + singleton property is set to false, it must be able to return + independent proxy instances. If any of the advisors is itself a + prototype, an independent instance would need to be returned, so it's + necessary to be able to obtain an instance of the prototype from the + factory; holding a reference isn't sufficient. + + The "person" bean definition above can be used in place of a Person implementation, as follows: @@ -1085,7 +1106,7 @@ public interface IntroductionInfo { dependency on it, as with an ordinary Java object: <bean id="personUser" class="com.mycompany.PersonUser"> - <property name="person"><ref local="person" /></property> + <property name="person"><ref local="person"/></property> </bean> The PersonUser class in this example would @@ -1101,18 +1122,18 @@ public interface IntroductionInfo { is included only for completeness: <bean id="myAdvisor" class="com.mycompany.MyAdvisor"> - <property name="someProperty"><value>Custom string property value</value></property> + <property name="someProperty" value="Custom string property value"/> </bean> <bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"/> <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean"> - <property name="proxyInterfaces"><value>com.mycompany.Person</value></property> + <property name="proxyInterfaces" value="com.mycompany.Person"/> <!-- Use inner bean, not local reference to target --> <property name="target"> <bean class="com.mycompany.PersonImpl"> - <property name="name"><value>Tony</value></property> - <property name="age"><value>51</value></property> + <property name="name" value="Tony"/> + <property name="age" value="51"/> </bean> </property> <property name="interceptorNames"> @@ -1125,8 +1146,8 @@ public interface IntroductionInfo { This has the advantage that there's only one object of type Person: useful if we want to prevent users of the - application context from obtaining a reference to the un-advised object, or - need to avoid any ambiguity with Spring IoC + application context from obtaining a reference to the un-advised object, + or need to avoid any ambiguity with Spring IoC autowiring. There's also arguably an advantage in that the ProxyFactoryBean definition is self-contained. However, there are times when being able to obtain the un-advised target from the @@ -1152,8 +1173,8 @@ public interface IntroductionInfo { easy to apply good practices, it avoids forcing a particular approach.) - If you want to, you can force the use of CGLIB in any case, even if - you do have interfaces. + If you want to, you can force the use of CGLIB in any case, even + if you do have interfaces. CGLIB proxying works by generating a subclass of the target class at runtime. Spring configures this generated subclass to delegate method @@ -1257,10 +1278,10 @@ public interface IntroductionInfo { abstract attribute, as described previously, so that it may not actually ever be instantiated. Application contexts (but not simple - bean factories) will by default pre-instantiate all singletons. It is therefore - important (at least for singleton beans) that if you have a (parent) - bean definition which you intend to use only as a template, and this - definition specifies a class, you must make sure to set the + bean factories) will by default pre-instantiate all singletons. It is + therefore important (at least for singleton beans) that if you have a + (parent) bean definition which you intend to use only as a template, and + this definition specifies a class, you must make sure to set the abstract attribute to true, otherwise the application context will actually try to pre-instantiate it. @@ -1292,15 +1313,15 @@ MyBusinessInterface tb = (MyBusinessInterface) factory.getProxy(); There are also convenience methods on ProxyFactory (inherited from - AdvisedSupport) which allow you to add other advice types - such as before and throws advice. AdvisedSupport is the superclass of both - ProxyFactory and ProxyFactoryBean. + AdvisedSupport) which allow you to add other advice + types such as before and throws advice. AdvisedSupport is the superclass + of both ProxyFactory and ProxyFactoryBean. - - Integrating AOP proxy creation with the IoC framework is best - practice in most applications. We recommend that you externalize - configuration from Java code with AOP, as in general. - + + Integrating AOP proxy creation with the IoC framework is best + practice in most applications. We recommend that you externalize + configuration from Java code with AOP, as in general. +
@@ -1374,18 +1395,18 @@ advised.addAdvisor(new DefaultPointcutAdvisor(mySpecialPointcut, myAdvice)); assertEquals("Added two advisors", oldAdvisorCount + 2, advised.getAdvisors().length); - - It's questionable whether it's advisable (no pun intended) to - modify advice on a business object in production, although there are no - doubt legitimate usage cases. However, it can be very useful in - development: for example, in tests. I have sometimes found it very useful - to be able to add test code in the form of an interceptor or other advice, - getting inside a method invocation I want to test. (For example, the - advice can get inside a transaction created for that method: for example, - to run SQL to check that a database was correctly updated, before marking - the transaction for roll back.) - - + + It's questionable whether it's advisable (no pun intended) to + modify advice on a business object in production, although there are no + doubt legitimate usage cases. However, it can be very useful in + development: for example, in tests. I have sometimes found it very + useful to be able to add test code in the form of an interceptor or + other advice, getting inside a method invocation I want to test. (For + example, the advice can get inside a transaction created for that + method: for example, to run SQL to check that a database was correctly + updated, before marking the transaction for roll back.) + + Depending on how you created the proxy, you can usually set a frozen flag, in which case the Advised isFrozen() method will @@ -1438,11 +1459,12 @@ assertEquals("Added two advisors", BeanNameAutoProxyCreator The BeanNameAutoProxyCreator class is a - BeanPostProcessor that automatically creates AOP proxies - for beans with names matching literal values or wildcards. + BeanPostProcessor that automatically creates AOP + proxies for beans with names matching literal values or + wildcards. <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> - <property name="beanNames"><value>jdk*,onlyJdk</value></property> + <property name="beanNames" value="jdk*,onlyJdk"/> <property name="interceptorNames"> <list> <value>myInterceptor</value> @@ -1451,15 +1473,15 @@ assertEquals("Added two advisors", </bean> As with ProxyFactoryBean, there is an - interceptorNames property rather than a list of interceptors, to allow - correct behavior for prototype advisors. Named "interceptors" can be - advisors or any advice type. + interceptorNames property rather than a list of + interceptors, to allow correct behavior for prototype advisors. Named + "interceptors" can be advisors or any advice type. As with auto proxying in general, the main point of using BeanNameAutoProxyCreator is to apply the same - configuration consistently to multiple objects, with minimal - volume of configuration. It is a popular choice for applying - declarative transactions to multiple objects. + configuration consistently to multiple objects, with minimal volume of + configuration. It is a popular choice for applying declarative + transactions to multiple objects. Bean definitions whose names match, such as "jdkMyBean" and "onlyJdk" in the above example, are plain old bean definitions with @@ -1653,14 +1675,14 @@ assertEquals("Added two advisors", <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/> - - If you require only declarative transaction management, using - these generic XML definitions will result in Spring automatically - proxying all classes or methods with transaction attributes. You won't - need to work directly with AOP, and the programming model is similar to - that of .NET ServicedComponents. - - + + If you require only declarative transaction management, using + these generic XML definitions will result in Spring automatically + proxying all classes or methods with transaction attributes. You won't + need to work directly with AOP, and the programming model is similar + to that of .NET ServicedComponents. + + This mechanism is extensible. It's possible to do autoproxying based on custom attributes. You need to: @@ -1731,12 +1753,12 @@ assertEquals("Added two advisors", Let's look at the standard target sources provided with Spring, and how you can use them. - - When using a custom target source, your target will usually need - to be a prototype rather than a singleton bean definition. This allows - Spring to create a new target instance when required. - - + + When using a custom target source, your target will usually need + to be a prototype rather than a singleton bean definition. This allows + Spring to create a new target instance when required. + +
Hot swappable target sources @@ -1848,16 +1870,16 @@ Object oldTarget = swapper.swap(newTarget); The cast will look as follows: - + PoolingConfig conf = (PoolingConfig) beanFactory.getBean("businessObject"); +System.out.println("Max pool size is " + conf.getMaxSize()); + + + Pooling stateless service objects is not usually necessary. We + don't believe it should be the default choice, as most stateless + objects are naturally thread safe, and instance pooling is problematic + if resources are cached. + - - Pooling stateless service objects is not usually necessary. We - don't believe it should be the default choice, as most stateless objects - are naturally thread safe, and instance pooling is problematic if - resources are cached. - - Simpler pooling is available using autoproxying. It's possible to set the TargetSources used by any autoproxy creator.
@@ -1876,9 +1898,9 @@ System.out.println("Max pool size is " + conf.getMaxSize());]]> poolTargetSource definition shown above as follows. (I've also changed the name, for clarity.)
- - -]]> + <bean id="prototypeTargetSource" class="org.springframework.aop.target.PrototypeTargetSource"> + <property name="targetBeanName" ref="businessObjectTarget"/> +</bean> There's only one property: the name of the target bean. Inheritance is used in the TargetSource implementations to ensure @@ -1889,31 +1911,32 @@ System.out.println("Max pool size is " + conf.getMaxSize());]]>
<classname>ThreadLocal</classname> target sources - ThreadLocal target sources are useful if you need an object to be - created for each incoming request (per thread that is). The concept of a - ThreadLocal provide a JDK-wide facility to - transparently store resource alongside a thread. Setting up a - ThreadLocalTargetSource is pretty much the same as was explained for the - other types of target source: + ThreadLocal target sources are useful if + you need an object to be created for each incoming request (per thread + that is). The concept of a ThreadLocal provide a + JDK-wide facility to transparently store resource alongside a thread. + Setting up a ThreadLocalTargetSource is pretty + much the same as was explained for the other types of target + source: - - -]]> + <bean id="threadlocalTargetSource" class="org.springframework.aop.target.ThreadLocalTargetSource"> + <property name="targetBeanName" value="businessObjectTarget"/> +</bean> - - ThreadLocals come with serious issues (potentially - resulting in memory leaks) when incorrectly using them in a - multi-threaded and multi-classloader environments. One should always - consider wrapping a threadlocal in some other class and never directly - use the ThreadLocal itself (except of course in the wrapper class). - Also, one should always remember to correctly set and unset (where the - latter simply involved a call to ThreadLocal.set(null)) the resource - local to the thread. Unsetting should be done in any case since not - unsetting it might result in problematic behavior. Spring's ThreadLocal - support does this for you and should always be considered in favor - of using ThreadLocals without other proper handling - code. - + + ThreadLocals come with serious issues (potentially resulting in + memory leaks) when incorrectly using them in a multi-threaded and + multi-classloader environments. One should always consider wrapping a + threadlocal in some other class and never directly use the + ThreadLocal itself (except of course in the + wrapper class). Also, one should always remember to correctly set and + unset (where the latter simply involved a call to + ThreadLocal.set(null)) the resource local to the + thread. Unsetting should be done in any case since not unsetting it + might result in problematic behavior. Spring's ThreadLocal support + does this for you and should always be considered in favor of using + ThreadLocals without other proper handling code. +
@@ -1922,14 +1945,16 @@ System.out.println("Max pool size is " + conf.getMaxSize());]]> Spring AOP is designed to be extensible. While the interception implementation strategy is presently used internally, it is possible to - support arbitrary advice types in addition to the out-of-the-box interception around advice, - before, throws advice and after returning advice. + support arbitrary advice types in addition to the out-of-the-box + interception around advice, before, throws advice and after returning + advice. The org.springframework.aop.framework.adapter package is an SPI package allowing support for new custom advice types to be added without changing the core framework. The only constraint on a - custom Advice type is that it must implement the - org.aopalliance.aop.Advice tag interface. + custom Advice type is that it must + implement the org.aopalliance.aop.Advice + tag interface. Please refer to the org.springframework.aop.framework.adapter package's @@ -1945,15 +1970,15 @@ System.out.println("Max pool size is " + conf.getMaxSize());]]> The JPetStore's default configuration illustrates the use of the - TransactionProxyFactoryBean for declarative transaction - management. + TransactionProxyFactoryBean for declarative + transaction management. The /attributes directory of the JPetStore - illustrates the use of attribute-driven declarative transaction management. + illustrates the use of attribute-driven declarative transaction + management. - -
- \ No newline at end of file +
+ diff --git a/spring-framework-reference/src/beans.xml b/spring-framework-reference/src/beans.xml index 18d00b95129..b72dd243790 100644 --- a/spring-framework-reference/src/beans.xml +++ b/spring-framework-reference/src/beans.xml @@ -1339,7 +1339,7 @@ public class ExampleBean { url="http://www.springsource.com/products/sts">SpringSource Tool Suite (STS) that support automatic property completion when defining bean definitions. The use of such IDE assistance is highly - recommended. + recommended. If you are reading this reference manual straight through from top to bottom (wow!) then we are getting slightly ahead of ourselves @@ -1559,18 +1559,8 @@ public class ExampleBean { <!-- results in a setSomeMap(java.util.Map) call --> <property name="someMap"> <map> - <entry> - <key> - <value>an entry</value> - </key> - <value>just some string</value> - </entry> - <entry> - <key> - <value>a ref</value> - </key> - <ref bean="myDataSource" /> - </entry> + <entry key="an entry" value="just some string"/> + <entry key ="a ref" value-ref="myDataSource"/> </map> </property> <!-- results in a setSomeSet(java.util.Set) call --> @@ -4231,8 +4221,7 @@ org.springframework.scripting.groovy.GroovyMessenger@272961 DataSource: <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> - <property name="locations"> - <value>classpath:com/foo/jdbc.properties</value> + <property name="locations" value="classpath:com/foo/jdbc.properties"/> </property> </bean> diff --git a/spring-framework-reference/src/transaction.xml b/spring-framework-reference/src/transaction.xml index e5c6287ca4b..6ad30d3d2e6 100644 --- a/spring-framework-reference/src/transaction.xml +++ b/spring-framework-reference/src/transaction.xml @@ -1,158 +1,197 @@ - +"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> - Transaction management + Transaction management
Introduction - One of the most compelling reasons to use the Spring Framework is the - comprehensive transaction support. The Spring Framework provides a consistent - abstraction for transaction management that delivers the following benefits: + + One of the most compelling reasons to use the Spring Framework is + the comprehensive transaction support. The Spring Framework provides a + consistent abstraction for transaction management that delivers the + following benefits: + Provides a consistent programming model across different transaction APIs such as JTA, JDBC, Hibernate, JPA, and JDO. + - Supports declarative transaction management. + Supports declarative + transaction management. + - Provides a simpler API for programmatic - transaction management than a number of complex transaction APIs such as JTA. + Provides a simpler API for programmatic transaction + management than a number of complex transaction APIs such as + JTA. + - Integrates very well with Spring's various data access abstractions. + Integrates very well with Spring's various data access + abstractions. - This chapter is divided up into a number of sections, each detailing one of the - value-adds or technologies of the Spring Framework's transaction support. The chapter - closes up with some discussion of best practices surrounding transaction management - (for example, choosing between declarative and programmatic transaction management). + + This chapter is divided up into a number of sections, each detailing + one of the value-adds or technologies of the Spring Framework's + transaction support. The chapter closes up with some discussion of best + practices surrounding transaction management (for example, choosing + between declarative and programmatic transaction management). + - The first section, entitled - Motivations, - describes why one would want to use - the Spring Framework's transaction abstraction as opposed to EJB CMT - or driving transactions via a proprietary API such - as Hibernate. + The first section, entitled Motivations, describes + why one would want to use the Spring Framework's + transaction abstraction as opposed to EJB CMT or driving transactions + via a proprietary API such as Hibernate. + - The second section, entitled - Key abstractions - outlines the core classes in the Spring Framework's transaction support, - as well as how to configure and obtain DataSource + The second section, entitled Key abstractions outlines the + core classes in the Spring Framework's transaction support, as well as + how to configure and obtain DataSource instances from a variety of sources. + - The third section, entitled - Declarative transaction management, - covers the Spring Framework's support for declarative transaction management. + The third section, entitled Declarative transaction + management, covers the Spring Framework's support for + declarative transaction management. + - The fourth section, entitled - Programmatic transaction management, - covers the Spring Framework's support for programmatic (that is, explicitly - coded) transaction management. + The fourth section, entitled Programmatic transaction + management, covers the Spring Framework's support for + programmatic (that is, explicitly coded) transaction + management.
Motivations + - Is an application server needed for transaction management? - The Spring Framework's transaction management support significantly changes - traditional thinking as to when a J2EE application requires an application - server. + Is an application server needed for transaction + management? + + The Spring Framework's transaction management support + significantly changes traditional thinking as to when a J2EE application + requires an application server. + In particular, you don't need an application server just to have - declarative transactions via EJB. In fact, even if you have an application - server with powerful JTA capabilities, you may well decide that the Spring Framework's - declarative transactions offer more power and a much more productive - programming model than EJB CMT. - Typically you need an application server's JTA capability only if you need to - enlist multiple transactional resources, and for many applications being able - to handle transactions across multiple resources isn't a requirement. - For example, many high-end applications use a single, highly scalable - database (such as Oracle 9i RAC). Standalone transaction managers such as - Atomikos Transactions and - JOTM are other options. (Of course - you may need other application server capabilities such as JMS and JCA.) - The most important point is that with the Spring Framework you can - choose when to scale your application up to a full-blown application - server. Gone are the days when the only alternative to using - EJB CMT or JTA was to write code using local transactions such as those - on JDBC connections, and face a hefty rework if you ever needed that code - to run within global, container-managed transactions. With the Spring Framework, - only configuration needs to change so that your code doesn't have to. + declarative transactions via EJB. In fact, even if you have an + application server with powerful JTA capabilities, you may well decide + that the Spring Framework's declarative transactions offer more power + and a much more productive programming model than EJB CMT. + + Typically you need an application server's JTA capability only if + you need to enlist multiple transactional resources, and for many + applications being able to handle transactions across multiple resources + isn't a requirement. For example, many high-end applications use a + single, highly scalable database (such as Oracle 9i RAC). Standalone + transaction managers such as Atomikos Transactions and JOTM are other options. (Of + course you may need other application server capabilities such as JMS + and JCA.) + + The most important point is that with the Spring Framework + you can choose when to scale your application up to a + full-blown application server. Gone are the days when the + only alternative to using EJB CMT or JTA was to write code using local + transactions such as those on JDBC connections, and face a hefty rework + if you ever needed that code to run within global, container-managed + transactions. With the Spring Framework, only configuration needs to + change so that your code doesn't have to. + Traditionally, J2EE developers have had two choices for transaction - management: global or local transactions. - Global transactions are managed by the application server, using the Java Transaction - API (JTA). Local transactions are resource-specific: the most common example would - be a transaction associated with a JDBC connection. This choice has profound - implications. For instance, global transactions provide the ability to work with multiple - transactional resources (typically relational databases and message queues). - With local transactions, the application server is not involved in - transaction management and cannot help ensure correctness across multiple - resources. (It is worth noting that most applications use a single transaction - resource.) + management: global or local + transactions. Global transactions are managed by the application server, + using the Java Transaction API (JTA). Local transactions are + resource-specific: the most common example would be a transaction + associated with a JDBC connection. This choice has profound implications. + For instance, global transactions provide the ability to work with + multiple transactional resources (typically relational databases and + message queues). With local transactions, the application server is not + involved in transaction management and cannot help ensure correctness + across multiple resources. (It is worth noting that most applications use + a single transaction resource.) + Global Transactions - Global transactions have a significant downside, in that code needs - to use JTA, and JTA is a cumbersome API to use (partly due to its exception - model). Furthermore, a JTA UserTransaction - normally needs to be sourced from JNDI: meaning that we need to use - both JNDI and JTA to use JTA. - Obviously all use of global transactions limits the reusability of application - code, as JTA is normally only available in an application server environment. - Previously, the preferred way to use global transactions was via EJB - CMT (Container Managed Transaction): - CMT is a form of declarative transaction management - (as distinguished from programmatic transaction management). - EJB CMT removes the need for transaction-related JNDI lookups - although of course - the use of EJB itself necessitates the use of JNDI. It removes most of the need (although - not entirely) to write Java code to control transactions. The significant - downside is that CMT is tied to JTA and an application server - environment. Also, it is only available if one chooses to implement - business logic in EJBs, or at least behind a transactional EJB facade. The - negatives around EJB in general are so great that this is not an - attractive proposition, especially in the face of compelling alternatives for - declarative transaction management. + + Global transactions have a significant downside, in that code + needs to use JTA, and JTA is a cumbersome API to use (partly due to its + exception model). Furthermore, a JTA + UserTransaction normally needs to be + sourced from JNDI: meaning that we need to use both + JNDI and JTA to use JTA. Obviously all use of + global transactions limits the reusability of application code, as JTA + is normally only available in an application server environment. + + Previously, the preferred way to use global transactions was via + EJB CMT (Container Managed + Transaction): CMT is a form of declarative transaction management (as + distinguished from programmatic transaction + management). EJB CMT removes the need for transaction-related + JNDI lookups - although of course the use of EJB itself necessitates the + use of JNDI. It removes most of the need (although not entirely) to + write Java code to control transactions. The significant downside is + that CMT is tied to JTA and an application server environment. Also, it + is only available if one chooses to implement business logic in EJBs, or + at least behind a transactional EJB facade. The negatives around EJB in + general are so great that this is not an attractive proposition, + especially in the face of compelling alternatives for declarative + transaction management. + Local Transactions + Local transactions may be easier to use, but have significant disadvantages: they cannot work across multiple transactional resources. - For example, code that manages transactions using a JDBC connection cannot - run within a global JTA transaction. Another downside is that local - transactions tend to be invasive to the programming model. + For example, code that manages transactions using a JDBC connection + cannot run within a global JTA transaction. Another downside is that + local transactions tend to be invasive to the programming model. + Spring resolves these problems. It enables application developers to use a consistent programming model in any environment. You write your code once, and it can benefit from - different transaction management strategies in different environments. - The Spring Framework provides both declarative and programmatic transaction management. - Declarative transaction management is preferred by most users, and is - recommended in most cases. + different transaction management strategies in different environments. The + Spring Framework provides both declarative and programmatic transaction + management. Declarative transaction management is preferred by most users, + and is recommended in most cases. + With programmatic transaction management, developers work with the - Spring Framework transaction abstraction, which can run over any underlying - transaction infrastructure. With the preferred declarative model, - developers typically write little or no code related to transaction - management, and hence don't depend on the Spring Framework's transaction API - (or indeed on any other transaction API). + Spring Framework transaction abstraction, which can run over any + underlying transaction infrastructure. With the preferred declarative + model, developers typically write little or no code related to transaction + management, and hence don't depend on the Spring Framework's transaction + API (or indeed on any other transaction API).
Key abstractions + The key to the Spring transaction abstraction is the notion of a transaction strategy. A transaction strategy is defined by the org.springframework.transaction.PlatformTransactionManager interface, shown below: - public interface PlatformTransactionManager { TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; @@ -160,73 +199,92 @@ void commit(TransactionStatus status) throws TransactionException; void rollback(TransactionStatus status) throws TransactionException; -}]]> - This is primarily an SPI interface, although it can be used - programmatically. - Note that in keeping with the Spring Framework's philosophy, - PlatformTransactionManager is - an interface, and can thus be easily mocked or stubbed +} + + This is primarily an SPI interface, although it can be used programmatically. Note that + in keeping with the Spring Framework's philosophy, + PlatformTransactionManager is an + interface, and can thus be easily mocked or stubbed as necessary. Nor is it tied to a lookup strategy such as JNDI: PlatformTransactionManager implementations - are defined like any other object (or bean) in the Spring Framework's IoC container. - This benefit alone makes it a worthwhile abstraction even when working - with JTA: transactional code can be tested much more easily than if it - used JTA directly. - Again in keeping with Spring's philosophy, the TransactionException - that can be thrown by any of the PlatformTransactionManager - interface's methods is unchecked (that is it extends the - java.lang.RuntimeException class). Transaction infrastructure - failures are almost invariably fatal. In rare cases where application code can actually - recover from a transaction failure, the application developer can still choose to catch - and handle TransactionException. The salient point is + are defined like any other object (or bean) in the Spring Framework's IoC + container. This benefit alone makes it a worthwhile abstraction even when + working with JTA: transactional code can be tested much more easily than + if it used JTA directly. + + Again in keeping with Spring's philosophy, the + TransactionException that can be thrown by + any of the PlatformTransactionManager + interface's methods is unchecked (that is it extends + the java.lang.RuntimeException class). + Transaction infrastructure failures are almost invariably fatal. In rare + cases where application code can actually recover from a transaction + failure, the application developer can still choose to catch and handle + TransactionException. The salient point is that developers are not forced to do so. + The getTransaction(..) method returns a TransactionStatus object, depending on a - TransactionDefinition parameter. The returned - TransactionStatus might represent a new or - existing transaction (if there were a matching transaction in the current - call stack - with the implication being that (as with J2EE transaction contexts) - a TransactionStatus is associated with a - thread of execution). - The TransactionDefinition interface specifies: + TransactionDefinition parameter. The + returned TransactionStatus might represent + a new or existing transaction (if there were a matching transaction in the + current call stack - with the implication being that (as with J2EE + transaction contexts) a TransactionStatus + is associated with a thread of + execution). + + The TransactionDefinition interface + specifies: + - Isolation: the - degree of isolation this transaction has from the work of other - transactions. For example, can this transaction see uncommitted - writes from other transactions? + Isolation: the degree of + isolation this transaction has from the work of other transactions. + For example, can this transaction see uncommitted writes from other + transactions? + - Propagation: - normally all code executed within a transaction scope will run in that - transaction. However, there are several options specifying behavior if - a transactional method is executed when a transaction context already - exists: for example, simply continue running in the existing transaction - (the common case); or suspending the existing transaction and creating - a new transaction. Spring offers all of the transaction propagation - options familiar from EJB CMT. (Some details regarding the semantics of transaction - propagation in Spring can be found in the section entitled . - - - Timeout: how long - this transaction may run before timing out (and automatically being - rolled back by the underlying transaction infrastructure). + Propagation: normally all code + executed within a transaction scope will run in that transaction. + However, there are several options specifying behavior if a + transactional method is executed when a transaction context already + exists: for example, simply continue running in the existing + transaction (the common case); or suspending the existing transaction + and creating a new transaction. Spring offers all of the + transaction propagation options familiar from EJB CMT. + (Some details regarding the semantics of transaction propagation in + Spring can be found in the section entitled . + + + Timeout: how long this + transaction may run before timing out (and automatically being rolled + back by the underlying transaction infrastructure). + + Read-only status: a read-only transaction does not modify any data. Read-only transactions can be a - useful optimization in some cases (such as when using Hibernate). + useful optimization in some cases (such as when using + Hibernate). - These settings reflect standard transactional concepts. If necessary, - please refer to a resource discussing transaction isolation levels and other - core transaction concepts because understanding such core concepts is essential - to using the Spring Framework or indeed any other transaction management solution. - The TransactionStatus interface provides a simple - way for transactional code to control transaction execution and query - transaction status. The concepts should be familiar, as they are common to - all transaction APIs: - These settings reflect standard transactional concepts. If + necessary, please refer to a resource discussing transaction isolation + levels and other core transaction concepts because understanding such core + concepts is essential to using the Spring Framework or indeed any other + transaction management solution. + + The TransactionStatus interface + provides a simple way for transactional code to control transaction + execution and query transaction status. The concepts should be familiar, + as they are common to all transaction APIs: + + public interface TransactionStatus extends SavepointManager { boolean isNewTransaction(); @@ -240,322 +298,396 @@ boolean isCompleted(); -}]]> - Regardless of whether you opt for declarative or programmatic transaction - management in Spring, defining the correct - PlatformTransactionManager implementation is - absolutely essential. In good Spring fashion, this important definition typically - is made using via Dependency Injection. - PlatformTransactionManager implementations - normally require knowledge of the environment in which they work: JDBC, JTA, - Hibernate, etc The following examples from the +} + + Regardless of whether you opt for declarative or programmatic + transaction management in Spring, defining the correct + PlatformTransactionManager implementation + is absolutely essential. In good Spring fashion, this important definition + typically is made using via Dependency Injection. + + PlatformTransactionManager + implementations normally require knowledge of the environment in which + they work: JDBC, JTA, Hibernate, etc The following examples from the dataAccessContext-local.xml file from Spring's - jPetStore sample application show how a local - PlatformTransactionManager implementation can be - defined. (This will work with plain JDBC.) + jPetStore sample application show how a + local PlatformTransactionManager + implementation can be defined. (This will work with plain JDBC.) + We must define a JDBC DataSource, and - then use the Spring DataSourceTransactionManager, giving - it a reference to the DataSource. - - - - - -]]> - The related PlatformTransactionManager bean - definition will look like this: - - -]]> - If we use JTA in a J2EE container, as in the 'dataAccessContext-jta.xml' - file from the same sample application, we use a container DataSource, - obtained via JNDI, in conjunction with Spring's JtaTransactionManager. - The JtaTransactionManager doesn't need to know about the - DataSource, or any other specific resources, as - it will use the container's global transaction management infrastructure. - -DataSourceTransactionManager, + giving it a reference to the + DataSource. + + <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> + <property name="driverClassName" value="${jdbc.driverClassName}" /> + <property name="url" value="${jdbc.url}" /> + <property name="username" value="${jdbc.username}" /> + <property name="password" value="${jdbc.password}" /> +</bean> + + The related + PlatformTransactionManager bean definition + will look like this: + + <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> + <property name="dataSource" ref="dataSource"/> +</bean> + + If we use JTA in a J2EE container, as in the + 'dataAccessContext-jta.xml' file from the same sample + application, we use a container DataSource, + obtained via JNDI, in conjunction with Spring's + JtaTransactionManager. The + JtaTransactionManager doesn't need to know about + the DataSource, or any other specific + resources, as it will use the container's global transaction management + infrastructure. + + <?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/jee - http://www.springframework.org/schema/jee/spring-jee-3.0.xsd"> + http://www.springframework.org/schema/jee/spring-jee-3.0.xsd"> - + <jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/> - + <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" /> - ]]><!-- other <bean/> definitions here --><!-- other <bean/> definitions here --> + +</beans> -]]> - The above definition of the 'dataSource' bean uses the - <jndi-lookup/> tag from the 'jee' - namespace. For more information on schema-based configuration, see , - and for more information on the <jee/> tags - see the section entitled . + The above definition of the 'dataSource' bean + uses the <jndi-lookup/> tag from the + 'jee' namespace. For more information on schema-based + configuration, see , and for more + information on the <jee/> tags see the section + entitled . - We can also use Hibernate local transactions easily, as shown in the - following examples from the Spring Framework's PetClinic - sample application. In this case, we need to define a Hibernate - LocalSessionFactoryBean, which application code will - use to obtain Hibernate Session instances. - The DataSource bean definition will be - similar to the one shown previously (and thus is not shown). If the - DataSource is managed by the JEE container it should - be non-transactional as the Spring Framework, rather than the JEE container, will - manage transactions. - The 'txManager' bean in this case is of the - HibernateTransactionManager type. In the same way as the - DataSourceTransactionManager needs a reference to the - DataSource, the - HibernateTransactionManager needs a reference to the - SessionFactory. - - - - - org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml - - - - - hibernate.dialect=${hibernate.dialect} - - - - - -]]> + We can also use Hibernate local transactions easily, as shown in the + following examples from the Spring Framework's PetClinic sample application. In this case, we need + to define a Hibernate LocalSessionFactoryBean, + which application code will use to obtain Hibernate + Session instances. + + The DataSource bean definition will + be similar to the one shown previously (and thus is not shown). If the + DataSource is managed by the JEE container + it should be non-transactional as the Spring Framework, rather than the + JEE container, will manage transactions. + + The 'txManager' bean in this case is of the + HibernateTransactionManager type. In the same way + as the DataSourceTransactionManager needs a + reference to the DataSource, the + HibernateTransactionManager needs a reference to + the SessionFactory. + + <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> + <property name="dataSource" ref="dataSource" /> + <property name="mappingResources"> + <list> + <value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value> + </list> + </property> + <property name="hibernateProperties"> + <value> + hibernate.dialect=${hibernate.dialect} + </value> + </property> +</bean> + +<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> + <property name="sessionFactory" ref="sessionFactory" /> +</bean> + With Hibernate and JTA transactions, we can simply use the - JtaTransactionManager as with JDBC or any other resource strategy. - ]]> + JtaTransactionManager as with JDBC or any other + resource strategy. + + <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/> + Note that this is identical to JTA configuration for any resource, as these are global transactions, which can enlist any transactional resource. - - In all these cases, application code will not need to change at - all. We can change how transactions are managed merely by changing - configuration, even if that change means moving from local to global - transactions or vice versa. - + + In all these cases, application code will not need to change + at all. We can change how transactions are managed merely by changing + configuration, even if that change means moving from local to global + transactions or vice versa.
Resource synchronization with transactions + It should now be clear how different transaction managers are created, and how they are linked to related resources which need to be - synchronized to transactions (for example DataSourceTransactionManager - to a JDBC DataSource, + synchronized to transactions (for example + DataSourceTransactionManager to a JDBC + DataSource, HibernateTransactionManager to a Hibernate - SessionFactory, and so forth). There remains the question - however of how the application code, directly or indirectly using a - persistence API (such as JDBC, Hibernate, and JDO), ensures that these resources - are obtained and handled properly in terms of proper - creation/reuse/cleanup and trigger (optionally) transaction - synchronization via the relevant PlatformTransactionManager. + SessionFactory, and so forth). There + remains the question however of how the application code, directly or + indirectly using a persistence API (such as JDBC, Hibernate, and JDO), + ensures that these resources are obtained and handled properly in terms of + proper creation/reuse/cleanup and trigger (optionally) transaction + synchronization via the relevant + PlatformTransactionManager.
High-level approach + The preferred approach is to use Spring's highest level persistence integration APIs. These do not replace the native APIs, but - internally handle resource creation/reuse, cleanup, optional - transaction synchronization of the resources and exception mapping so - that user data access code doesn't have to worry about these concerns at - all, but can concentrate purely on non-boilerplate persistence logic. - Generally, the same template approach is used - for all persistence APIs, with examples including the - JdbcTemplate, HibernateTemplate, - and JdoTemplate classes (detailed in subsequent chapters - of this reference documentation. + internally handle resource creation/reuse, cleanup, optional transaction + synchronization of the resources and exception mapping so that user data + access code doesn't have to worry about these concerns at all, but can + concentrate purely on non-boilerplate persistence logic. Generally, the + same template approach is used for all persistence + APIs, with examples including the JdbcTemplate, + HibernateTemplate, and + JdoTemplate classes (detailed in subsequent + chapters of this reference documentation.
Low-level approach + At a lower level exist classes such as DataSourceUtils (for JDBC), SessionFactoryUtils (for Hibernate), - PersistenceManagerFactoryUtils (for JDO), and so on. - When it is preferable for application code to deal directly with the + PersistenceManagerFactoryUtils (for JDO), and so + on. When it is preferable for application code to deal directly with the resource types of the native persistence APIs, these classes ensure that proper Spring Framework-managed instances are obtained, transactions are (optionally) synchronized, and exceptions which happen in the process are properly mapped to a consistent API. - For example, in the case of JDBC, instead of the traditional JDBC approach of - calling the getConnection() method on the - DataSource, you would instead use Spring's + + For example, in the case of JDBC, instead of the traditional JDBC + approach of calling the getConnection() method on the + DataSource, you would instead use + Spring's org.springframework.jdbc.datasource.DataSourceUtils class as follows: - + + Connection conn = DataSourceUtils.getConnection(dataSource); + If an existing transaction exists, and already has a connection synchronized (linked) to it, that instance will be returned. Otherwise, the method call will trigger the creation of a new connection, which - will be (optionally) synchronized to any existing transaction, and - made available for subsequent reuse in that same transaction. As mentioned, - this has the added advantage that any SQLException - will be wrapped in a Spring Framework - CannotGetJdbcConnectionException - one of the Spring - Framework's hierarchy of unchecked DataAccessExceptions. This gives you more - information than can easily be obtained from the - SQLException, and ensures portability across - databases: even across different persistence technologies. + will be (optionally) synchronized to any existing transaction, and made + available for subsequent reuse in that same transaction. As mentioned, + this has the added advantage that any + SQLException will be wrapped in a Spring + Framework + CannotGetJdbcConnectionException - one of + the Spring Framework's hierarchy of unchecked DataAccessExceptions. This + gives you more information than can easily be obtained from the + SQLException, and ensures portability + across databases: even across different persistence technologies. + It should be noted that this will also work fine without Spring transaction management (transaction synchronization is optional), so you can use it whether or not you are using Spring for transaction management. + Of course, once you've used Spring's JDBC support or Hibernate support, you will generally prefer not to use - DataSourceUtils or the other helper classes, because - you'll be much happier working via the Spring abstraction than directly - with the relevant APIs. For example, if you use the Spring + DataSourceUtils or the other helper classes, + because you'll be much happier working via the Spring abstraction than + directly with the relevant APIs. For example, if you use the Spring JdbcTemplate or jdbc.object - package to simplify your use of JDBC, correct connection retrieval happens - behind the scenes and you won't need to write any special code. + package to simplify your use of JDBC, correct connection retrieval + happens behind the scenes and you won't need to write any special + code.
<classname>TransactionAwareDataSourceProxy</classname> + At the very lowest level exists the TransactionAwareDataSourceProxy class. This is a - proxy for a target DataSource, which wraps the - target DataSource to add awareness of Spring-managed - transactions. In this respect, it is similar to a transactional JNDI - DataSource as provided by a J2EE server. + proxy for a target DataSource, which + wraps the target DataSource to add + awareness of Spring-managed transactions. In this respect, it is similar + to a transactional JNDI DataSource as + provided by a J2EE server. + It should almost never be necessary or desirable to use this class, except when existing code exists which must be called and passed - a standard JDBC DataSource interface implementation. - In that case, it's possible to still have this code be usable, but - participating in Spring managed transactions. It is preferable to write - your new code using the higher level abstractions mentioned - above. + a standard JDBC DataSource interface + implementation. In that case, it's possible to still have this code be + usable, but participating in Spring managed transactions. It is + preferable to write your new code using the higher level abstractions + mentioned above.
Declarative transaction management - Most users of the Spring Framework choose declarative transaction management. - It is the option with the least impact on application code, and hence is most - consistent with the ideals of a non-invasive - lightweight container. - The Spring Framework's declarative transaction management is made possible - with Spring AOP, although, as the transactional aspects code comes with the - Spring Framework distribution and may be used in a boilerplate fashion, AOP concepts - do not generally have to be understood to make effective use of this code. + + Most users of the Spring Framework choose declarative transaction + management. It is the option with the least impact on application code, + and hence is most consistent with the ideals of a + non-invasive lightweight container. + + The Spring Framework's declarative transaction management is made + possible with Spring AOP, although, as the transactional aspects code + comes with the Spring Framework distribution and may be used in a + boilerplate fashion, AOP concepts do not generally have to be understood + to make effective use of this code. + It may be helpful to begin by considering EJB CMT and explaining the - similarities and differences with the Spring Framework's declarative transaction - management. The basic approach is similar: it is possible to specify - transaction behavior (or lack of it) down to individual method level. It is - possible to make a setRollbackOnly() call within a - transaction context if necessary. The differences are: + similarities and differences with the Spring Framework's declarative + transaction management. The basic approach is similar: it is possible to + specify transaction behavior (or lack of it) down to individual method + level. It is possible to make a setRollbackOnly() + call within a transaction context if necessary. The differences + are: + Unlike EJB CMT, which is tied to JTA, the Spring Framework's - declarative transaction management works in any environment. It can - work with JDBC, JDO, Hibernate or other transactions under the covers, - with configuration changes only. + declarative transaction management works in any environment. It can + work with JDBC, JDO, Hibernate or other transactions under the covers, + with configuration changes only. + The Spring Framework enables declarative transaction management - to be applied to any class, not merely special classes such as EJBs. + to be applied to any class, not merely special classes such as + EJBs. + - The Spring Framework offers declarative - rollback rules: this is - a feature with no EJB equivalent. Both programmatic and declarative support for rollback rules is - provided. + The Spring Framework offers declarative rollback + rules: this is a feature with no EJB equivalent. + Both programmatic and declarative support for rollback rules is + provided. + - The Spring Framework gives you an opportunity to customize transactional - behavior, using AOP. For example, if you want to insert custom - behavior in the case of transaction rollback, you can. You can also - add arbitrary advice, along with the transactional advice. With EJB - CMT, you have no way to influence the container's transaction - management other than setRollbackOnly(). + The Spring Framework gives you an opportunity to customize + transactional behavior, using AOP. For example, if you want to insert + custom behavior in the case of transaction rollback, you can. You can + also add arbitrary advice, along with the transactional advice. With + EJB CMT, you have no way to influence the container's transaction + management other than + setRollbackOnly(). + - The Spring Framework does not support propagation of transaction contexts across remote calls, as - do high-end application servers. If you need this feature, we recommend that you use EJB. However, - consider carefully before using such a feature, because normally, one does not want transactions to - span remote calls. - + The Spring Framework does not support propagation of transaction + contexts across remote calls, as do high-end application servers. If + you need this feature, we recommend that you use EJB. However, + consider carefully before using such a feature, because normally, one + does not want transactions to span remote calls. + + - Where is <classname>TransactionProxyFactoryBean</classname>? - Declarative transaction configuration in versions of Spring 2.0 and above - differs considerably from previous versions of Spring. The main difference is - that there is no longer any need to configure + Where is + <classname>TransactionProxyFactoryBean</classname>? + + Declarative transaction configuration in versions of Spring 2.0 + and above differs considerably from previous versions of Spring. The + main difference is that there is no longer any need to configure TransactionProxyFactoryBean beans. - The old, pre-Spring 2.0 configuration style is still 100% - valid configuration; think of the new <tx:tags/> - as simply defining TransactionProxyFactoryBean beans + + The old, pre-Spring 2.0 configuration style is still 100% valid + configuration; think of the new <tx:tags/> as + simply defining TransactionProxyFactoryBean beans on your behalf. + The concept of rollback rules is important: they enable us to specify which exceptions (and throwables) should cause automatic roll back. We specify this declaratively, in configuration, not in Java code. - So, while we can still call setRollbackOnly()on the - TransactionStatus object to roll the current - transaction back programmatically, most often we can specify a rule that - MyApplicationException must always result in - rollback. This has the significant advantage that business objects don't need - to depend on the transaction infrastructure. For example, they typically - don't need to import any Spring APIs, transaction or other. + So, while we can still call setRollbackOnly()on + the TransactionStatus object to roll the + current transaction back programmatically, most often we can specify a + rule that MyApplicationException must + always result in rollback. This has the significant advantage that + business objects don't need to depend on the transaction infrastructure. + For example, they typically don't need to import any Spring APIs, + transaction or other. + While the EJB default behavior is for the EJB container to automatically roll back the transaction on a system exception (usually a runtime exception), EJB CMT does not roll - back the transaction automatically on an application exception - (that is, a checked exception other than java.rmi.RemoteException). - While the Spring default behavior for declarative transaction management follows - EJB convention (roll back is automatic only on unchecked exceptions), it is often - useful to customize this. + back the transaction automatically on an application + exception (that is, a checked exception other than + java.rmi.RemoteException). While the Spring + default behavior for declarative transaction management follows EJB + convention (roll back is automatic only on unchecked exceptions), it is + often useful to customize this.
- Understanding the Spring Framework's declarative transaction implementation - The aim of this section is to dispel the mystique that is sometimes associated - with the use of declarative transactions. It is all very well for this reference - documentation simply to tell you to annotate your classes with the - @Transactional annotation, add the line - ('<tx:annotation-driven/>') to your configuration, - and then expect you to understand how it all works. This section will explain the - inner workings of the Spring Framework's declarative transaction infrastructure to - help you navigate your way back upstream to calmer waters in the event of - transaction-related issues. - The most important concepts to grasp with regard to the Spring Framework's - declarative transaction support are that this support is enabled - via AOP proxies, - and that the transactional advice is driven by metadata (currently - XML- or annotation-based). The combination of AOP with transactional metadata yields - an AOP proxy that uses a TransactionInterceptor in conjunction - with an appropriate PlatformTransactionManager implementation - to drive transactions around method invocations. + Understanding the Spring Framework's declarative transaction + implementation + + The aim of this section is to dispel the mystique that is + sometimes associated with the use of declarative transactions. It is all + very well for this reference documentation simply to tell you to + annotate your classes with the + @Transactional annotation, add the line + ('<tx:annotation-driven/>') to your + configuration, and then expect you to understand how it all works. This + section will explain the inner workings of the Spring Framework's + declarative transaction infrastructure to help you navigate your way + back upstream to calmer waters in the event of transaction-related + issues. + + The most important concepts to grasp with regard to the Spring + Framework's declarative transaction support are that this support is + enabled via AOP + proxies, and that the transactional advice is driven + by metadata (currently XML- or annotation-based). + The combination of AOP with transactional metadata yields an AOP proxy + that uses a TransactionInterceptor in conjunction + with an appropriate PlatformTransactionManager + implementation to drive transactions around method + invocations. + - Although knowledge of Spring AOP is not required to use Spring's declarative - transaction support, it can help. Spring AOP is thoroughly covered in the chapter - entitled . + Although knowledge of Spring AOP is not required to use Spring's + declarative transaction support, it can help. Spring AOP is thoroughly + covered in the chapter entitled . - Conceptually, calling a method on a transactional proxy looks like this... - - - - - - - - - - -
+ + Conceptually, calling a method on a transactional proxy looks like + this... + + + + + + + + + + +
A first example - Consider the following interface, and its attendant implementation. - (The intent is to convey the concepts, and using the rote Foo and - Bar tropes means that you can concentrate on the transaction - usage and not have to worry about the domain model.) - // the service interface that we want to make transactionalConsider the following interface, and its attendant + implementation. (The intent is to convey the concepts, and using the + rote Foo and Bar tropes + means that you can concentrate on the transaction usage and not have to + worry about the domain model.) + + // the service interface that we want to make transactional package x.y.service; @@ -569,8 +701,9 @@ public interface FooService { void updateFoo(Foo foo); -}]]> - // an implementation of the above interface + + // an implementation of the above interface package x.y.service; @@ -592,160 +725,189 @@ public class DefaultFooService implements FooService { throw new UnsupportedOperationException(); } -}]]> +} + (For the purposes of this example, the fact that the DefaultFooService class throws - UnsupportedOperationException instances in the body - of each implemented method is good; it will allow us to see transactions being created - and then rolled back in response to the UnsupportedOperationException - instance being thrown.) - Let's assume that the first two methods of the FooService - interface (getFoo(String) and getFoo(String, String)) - have to execute in the context of a transaction with read-only semantics, and that - the other methods (insertFoo(Foo) and - updateFoo(Foo)) have to execute in the context of a transaction - with read-write semantics. Don't worry about taking the following configuration in - all at once; everything will be explained in detail in the next few paragraphs. - <!-- from the file 'context.xml' --> -UnsupportedOperationException instances + in the body of each implemented method is good; it will allow us to see + transactions being created and then rolled back in response to the + UnsupportedOperationException instance + being thrown.) + + Let's assume that the first two methods of the + FooService interface + (getFoo(String) and getFoo(String, + String)) have to execute in the context of a transaction with + read-only semantics, and that the other methods + (insertFoo(Foo) and + updateFoo(Foo)) have to execute in the context of a + transaction with read-write semantics. Don't worry about taking the + following configuration in all at once; everything will be explained in + detail in the next few paragraphs. + + <!-- from the file 'context.xml' --> +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" - ]]>xmlns:tx="http://www.springframework.org/schema/tx"xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - ]]>http://www.springframework.org/schema/tx - http://www.springframework.org/schema/tx/spring-tx-3.0.xsdhttp://www.springframework.org/schema/tx + http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop - http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> + http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> - ]]><!-- this is the service object that we want to make transactional --> + <!-- this is the service object that we want to make transactional --> + <bean id="fooService" class="x.y.service.DefaultFooService"/> - ]]><!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean below) --> - ]]><!-- the transactional semantics... --> - ]]><!-- all methods starting with 'get' are read-only --> - ]]><!-- other methods use the default transaction settings (see below) --> - - + <!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean below) --> + <tx:advice id="txAdvice" transaction-manager="txManager"> + <!-- the transactional semantics... --> + <tx:attributes> + <!-- all methods starting with 'get' are read-only --> + <tx:method name="get*" read-only="true"/> + <!-- other methods use the default transaction settings (see below) --> + <tx:method name="*"/> + </tx:attributes> + </tx:advice> - ]]><!-- ensure that the above transactional advice runs for any execution - of an operation defined by the FooService interface --> - - - + <!-- ensure that the above transactional advice runs for any execution + of an operation defined by the FooService interface --> + <aop:config> + <aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.FooService.*(..))"/> + <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/> + </aop:config> - ]]><!-- don't forget the DataSource --> - - - - - + <!-- don't forget the DataSource --> + <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> + <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/> + <property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/> + <property name="username" value="scott"/> + <property name="password" value="tiger"/> + </bean> - ]]><!-- similarly, don't forget the PlatformTransactionManager --> - - + <!-- similarly, don't forget the PlatformTransactionManager --> + <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> + <property name="dataSource" ref="dataSource"/> + </bean> - ]]><!-- other <bean/> definitions here --><!-- other <bean/> definitions here --> + +</beans> -]]> Let's pick apart the above configuration. We have a service object - (the 'fooService' bean) that we want to make transactional. - The transaction semantics that we want to apply are encapsulated in the - <tx:advice/> definition. The - <tx:advice/> definition reads as - ... all methods on starting with 'get' are to execute - in the context of a read-only transaction, and all other methods are to execute - with the default transaction semantics. The + (the 'fooService' bean) that we want to make + transactional. The transaction semantics that we want to apply are + encapsulated in the <tx:advice/> definition. + The <tx:advice/> definition reads as + ... all methods on starting with + 'get' are to execute in the context of a read-only + transaction, and all other methods are to execute with the default + transaction semantics. The 'transaction-manager' attribute of the - <tx:advice/> tag is set to the - name of the PlatformTransactionManager bean - that is going to actually drive the transactions (in this + <tx:advice/> tag is set to the name of the + PlatformTransactionManager bean that is + going to actually drive the transactions (in this case the 'txManager' bean). + - You can actually omit the 'transaction-manager' - attribute in the transactional advice (<tx:advice/>) - if the bean name of the PlatformTransactionManager - that you want to wire in has the name 'transactionManager'. + You can actually omit the + 'transaction-manager' attribute in the + transactional advice (<tx:advice/>) if the + bean name of the + PlatformTransactionManager that you + want to wire in has the name 'transactionManager'. If the PlatformTransactionManager bean - that you want to wire in has any other name, then you have to be explicit - and use the 'transaction-manager' attribute as in the example above. + that you want to wire in has any other name, then you have to be + explicit and use the 'transaction-manager' + attribute as in the example above. - The <aop:config/> definition ensures that the transactional - advice defined by the 'txAdvice' bean actually executes at the appropriate - points in the program. First we define a pointcut that matches the execution of any - operation defined in the FooService interface - ('fooServiceOperation'). Then we associate the pointcut with the - 'txAdvice' using an advisor. The result indicates that at the execution - of a 'fooServiceOperation', the advice defined by 'txAdvice' - will be run. - The expression defined within the <aop:pointcut/> - element is an AspectJ pointcut expression; see the chapter entitled - for more details on pointcut expressions in Spring 2.0. - A common requirement is to make an entire service layer transactional. - The best way to do this is simply to change the pointcut expression to match - any operation in your service layer. For example: - - - - ]]> - (This example assumes that all your service interfaces are defined - in the 'x.y.service' package; see the chapter entitled - for more details.) + + The <aop:config/> definition ensures that + the transactional advice defined by the 'txAdvice' + bean actually executes at the appropriate points in the program. First + we define a pointcut that matches the execution of any operation defined + in the FooService interface + ('fooServiceOperation'). Then we associate the + pointcut with the 'txAdvice' using an advisor. The + result indicates that at the execution of a + 'fooServiceOperation', the advice defined by + 'txAdvice' will be run. + + The expression defined within the + <aop:pointcut/> element is an AspectJ pointcut + expression; see the chapter entitled for more + details on pointcut expressions in Spring 2.0. + + A common requirement is to make an entire service layer + transactional. The best way to do this is simply to change the pointcut + expression to match any operation in your service layer. For + example: + + <aop:config> + <aop:pointcut id="fooServiceMethods" expression="execution(* x.y.service.*.*(..))"/> + <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceMethods"/> + </aop:config> + + (This example assumes that all your service interfaces + are defined in the 'x.y.service' package; see the + chapter entitled for more + details.) + Now that we've analyzed the configuration, you may be asking - yourself, Okay... but what does all this configuration actually - do?. + yourself, Okay... but what does all this configuration + actually do?. + The above configuration is going to effect the creation of a transactional proxy around the object that is created from the - 'fooService' bean definition. The proxy will be configured - with the transactional advice, so that when an appropriate method is invoked - on the proxy, a transaction may - be started, suspended, be marked as read-only, etc., depending on the - transaction configuration associated with that method. Consider the following - program that test drives the above configuration. - 'fooService' bean definition. The proxy will be + configured with the transactional advice, so that when an appropriate + method is invoked on the proxy, a transaction + may be started, suspended, be marked as read-only, + etc., depending on the transaction configuration associated with that + method. Consider the following program that test drives the above + configuration. + + public final class Boot { public static void main(final String[] args) throws Exception { ApplicationContext ctx = new ClassPathXmlApplicationContext("context.xml", Boot.class); FooService fooService = (FooService) ctx.getBean("fooService"); fooService.insertFoo (new Foo()); } -}]]> - The output from running the above program will look something - like this. (Please note that the Log4J output and the stacktrace - from the UnsupportedOperationException thrown by the - insertFoo(..) method of the +} + + The output from running the above program will look something like + this. (Please note that the Log4J output and the stacktrace + from the UnsupportedOperationException + thrown by the insertFoo(..) method of the DefaultFooService class have been truncated in the interest of clarity.) - <!-- the Spring container is starting up... --> <!-- the Spring container is starting up... --> [AspectJInvocationContextExposingAdvisorAutoProxyCreator] - Creating implicit proxy for bean 'fooService' with 0 common interceptors and 1 specific interceptors - ]]><!-- the DefaultFooService is actually proxied --><!-- the DefaultFooService is actually proxied --> [JdkDynamicAopProxy] - Creating JDK dynamic proxy for [x.y.service.DefaultFooService] - ]]><!-- ... the insertFoo(..) method is now being invoked on the proxy --><!-- ... the insertFoo(..) method is now being invoked on the proxy --> [TransactionInterceptor] - Getting transaction for x.y.service.FooService.insertFoo - ]]><!-- the transactional advice kicks in here... --><!-- the transactional advice kicks in here... --> [DataSourceTransactionManager] - Creating new transaction with name [x.y.service.FooService.insertFoo] [DataSourceTransactionManager] - Acquired Connection [org.apache.commons.dbcp.PoolableConnection@a53de4] for JDBC transaction - ]]><!-- the insertFoo(..) method from DefaultFooService throws an exception... --><!-- the insertFoo(..) method from DefaultFooService throws an exception... --> [RuleBasedTransactionAttribute] - Applying rules to determine whether transaction should rollback on java.lang.UnsupportedOperationException [TransactionInterceptor] - Invoking rollback for transaction on x.y.service.FooService.insertFoo due to throwable [java.lang.UnsupportedOperationException] - ]]><!-- and the transaction is rolled back (by default, RuntimeException instances cause rollback) --><!-- and the transaction is rolled back (by default, RuntimeException instances cause rollback) --> [DataSourceTransactionManager] - Rolling back JDBC transaction on Connection [org.apache.commons.dbcp.PoolableConnection@a53de4] [DataSourceTransactionManager] - Releasing JDBC Connection after transaction @@ -753,92 +915,120 @@ public class DefaultFooService implements FooService { Exception in thread "main" java.lang.UnsupportedOperationException at x.y.service.DefaultFooService.insertFoo(DefaultFooService.java:14) - ]]><!-- AOP infrastructure stack trace elements removed for clarity --><!-- AOP infrastructure stack trace elements removed for clarity --> at $Proxy0.insertFoo(Unknown Source) - at Boot.main(Boot.java:11)]]> + at Boot.main(Boot.java:11)
Rolling back - The previous section outlined the basics of how to specify the transactional - settings for the classes, typically service layer classes, in your application in a - declarative fashion. This section describes how you can control the rollback of - transactions in a simple declarative fashion. + + The previous section outlined the basics of how to specify the + transactional settings for the classes, typically service layer classes, + in your application in a declarative fashion. This section describes how + you can control the rollback of transactions in a simple declarative + fashion. + The recommended way to indicate to the Spring Framework's - transaction infrastructure that a transaction's work is to be rolled back is to - throw an Exception from code that is currently - executing in the context of a transaction. The Spring Framework's - transaction infrastructure code will catch any unhandled - Exception as it bubbles up the call stack, and will - mark the transaction for rollback. - Note however that the Spring Framework's transaction infrastructure - code will, by default, only mark a transaction for rollback in - the case of runtime, unchecked exceptions; that is, when the thrown exception is an - instance or subclass of RuntimeException. - (Errors will also - by default - result in a rollback.) Checked - exceptions that are thrown from a transactional method will - not result in the transaction being rolled back. - Exactly which Exception types mark a transaction - for rollback can be configured. Find below a snippet of XML configuration that - demonstrates how one would configure rollback for a checked, application-specific - Exception type. - - - rollback-for="NoProductInStockException" - - -]]> - It is also possible to specify 'no rollback rules', for those times when you do - not want a transaction to be marked for rollback when an exception is thrown. - In the example configuration below, we effectively are telling the Spring Framework's transaction - infrastructure to commit the attendant transaction even in the face of an unhandled - InstrumentNotFoundException. - - - no-rollback-for="InstrumentNotFoundException" - - -]]> - When the Spring Framework's transaction infrastructure has caught an exception and is consulting - any configured rollback rules to determine whether or not to mark the transaction for rollback, the - strongest matching rule wins. So in the case of the following configuration, - any exception other than an InstrumentNotFoundException would result in the - attendant transaction being marked for rollback. - - - - -]]> - The second way to indicate that a rollback is required is to do so - programmatically. Although very simple, this way is quite invasive, and tightly couples - your code to the Spring Framework's transaction infrastructure, as can be seen below: - Exception from code + that is currently executing in the context of a transaction. The Spring + Framework's transaction infrastructure code will catch any unhandled + Exception as it bubbles up the call + stack, and will mark the transaction for rollback. + + Note however that the Spring Framework's transaction + infrastructure code will, by default, only mark a + transaction for rollback in the case of runtime, unchecked exceptions; + that is, when the thrown exception is an instance or subclass of + RuntimeException. + (Errors will also - by default - result in a + rollback.) Checked exceptions that are thrown from a transactional + method will not result in the transaction being + rolled back. + + Exactly which Exception types mark + a transaction for rollback can be configured. Find below a snippet of + XML configuration that demonstrates how one would configure rollback for + a checked, application-specific Exception + type. + + <tx:advice id="txAdvice" transaction-manager="txManager"> + <tx:attributes> + <tx:method name="get*" read-only="true" rollback-for="NoProductInStockException"/> + <tx:method name="*"/> + </tx:attributes> +</tx:advice> + + It is also possible to specify 'no rollback rules', for those + times when you do not want a transaction to be + marked for rollback when an exception is thrown. In the example + configuration below, we effectively are telling the Spring Framework's + transaction infrastructure to commit the attendant transaction even in + the face of an unhandled + InstrumentNotFoundException. + + <tx:advice id="txAdvice"> + <tx:attributes> + <tx:method name="updateStock" no-rollback-for="InstrumentNotFoundException"/> + <tx:method name="*"/> + </tx:attributes> +</tx:advice> + + When the Spring Framework's transaction infrastructure has caught + an exception and is consulting any configured rollback rules to + determine whether or not to mark the transaction for rollback, the + strongest matching rule wins. So in the case of the + following configuration, any exception other than an + InstrumentNotFoundException would result + in the attendant transaction being marked for rollback. + + <tx:advice id="txAdvice"> + <tx:attributes> + <tx:method name="*" rollback-for="Throwable" no-rollback-for="InstrumentNotFoundException"/> + </tx:attributes> +</tx:advice> + + The second way to indicate that a rollback is required is to do so + programmatically. Although very simple, this way is + quite invasive, and tightly couples your code to the Spring Framework's + transaction infrastructure, as can be seen below: + + public void resolvePosition() { try { - ]]>// some business logic...// some business logic... } catch (NoProductInStockException ex) { - ]]>// trigger rollback programmatically// trigger rollback programmatically TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } -}]]> - You are strongly encouraged to use the declarative approach to rollback if at all possible. - Programmatic rollback is available should you absolutely need it, but its usage flies in the face of - achieving a nice, clean POJO-based architecture. +} + + You are strongly encouraged to use the declarative approach to + rollback if at all possible. Programmatic rollback is available should + you absolutely need it, but its usage flies in the face of achieving a + nice, clean POJO-based architecture.
- Configuring different transactional semantics for different beans - Consider the scenario where you have a number of service layer objects, - and you want to apply totally different transactional configuration - to each of them. This is achieved by defining distinct <aop:advisor/> - elements with differing 'pointcut' and 'advice-ref' - attribute values. - Let's assume that all of your service layer classes are defined in a root - 'x.y.service' package. To make all beans that are instances of classes - defined in that package (or in subpackages) and that have names ending in - 'Service' have the default transactional configuration, you would write - the following: - -Configuring different transactional semantics for different + beans + + Consider the scenario where you have a number of service layer + objects, and you want to apply totally different + transactional configuration to each of them. This is achieved by + defining distinct <aop:advisor/> elements with + differing 'pointcut' and + 'advice-ref' attribute values. + + Let's assume that all of your service layer classes are defined in + a root 'x.y.service' package. To make all beans that + are instances of classes defined in that package (or in subpackages) and + that have names ending in 'Service' have the default + transactional configuration, you would write the following: + + <?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" @@ -848,41 +1038,41 @@ Exception in thread "main" java.lang.UnsupportedOperationException http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop - http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> + http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> - + <aop:config> - + <aop:pointcut id="serviceOperation" + expression="execution(* x.y.service..*Service.*(..))"/> - + <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice"/> - + </aop:config> - ]]><!-- these two beans will be transactional... --> - + <!-- these two beans will be transactional... --> + <bean id="fooService" class="x.y.service.DefaultFooService"/> + <bean id="barService" class="x.y.service.extras.SimpleBarService"/> - ]]><!-- ... and these two beans won't --> ]]><!-- (not in the right package) --> ]]><!-- (doesn't end in 'Service') --><!-- ... and these two beans won't --> + <bean id="anotherService" class="org.xyz.SomeService"/> <!-- (not in the right package) --> + <bean id="barManager" class="x.y.service.SimpleBarManager"/> <!-- (doesn't end in 'Service') --> - - - - - - + <tx:advice id="txAdvice"> + <tx:attributes> + <tx:method name="get*" read-only="true"/> + <tx:method name="*"/> + </tx:attributes> + </tx:advice> - ]]><!-- other transaction infrastructure beans such as a PlatformTransactionManager omitted... --><!-- other transaction infrastructure beans such as a PlatformTransactionManager omitted... --> -]]> +</beans> - Find below an example of configuring two distinct beans with totally different - transactional settings. + Find below an example of configuring two distinct beans with + totally different transactional settings. - -<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" @@ -892,171 +1082,213 @@ Exception in thread "main" java.lang.UnsupportedOperationException http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop - http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> + http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> - + <aop:config> - + <aop:pointcut id="defaultServiceOperation" + expression="execution(* x.y.service.*Service.*(..))"/> - + <aop:pointcut id="noTxServiceOperation" + expression="execution(* x.y.service.ddl.DefaultDdlManager.*(..))"/> - + <aop:advisor pointcut-ref="defaultServiceOperation" advice-ref="defaultTxAdvice"/> - + <aop:advisor pointcut-ref="noTxServiceOperation" advice-ref="noTxAdvice"/> - + </aop:config> - ]]><!-- this bean will be transactional (see the 'defaultServiceOperation' pointcut) --> + <!-- this bean will be transactional (see the 'defaultServiceOperation' pointcut) --> + <bean id="fooService" class="x.y.service.DefaultFooService"/> - ]]><!-- this bean will also be transactional, but with totally different transactional settings --> + <!-- this bean will also be transactional, but with totally different transactional settings --> + <bean id="anotherFooService" class="x.y.service.ddl.DefaultDdlManager"/> - - - - - - + <tx:advice id="defaultTxAdvice"> + <tx:attributes> + <tx:method name="get*" read-only="true"/> + <tx:method name="*"/> + </tx:attributes> + </tx:advice> - - - - - + <tx:advice id="noTxAdvice"> + <tx:attributes> + <tx:method name="*" propagation="NEVER"/> + </tx:attributes> + </tx:advice> - ]]><!-- other transaction infrastructure beans such as a PlatformTransactionManager omitted... --><!-- other transaction infrastructure beans such as a PlatformTransactionManager omitted... --> -]]> +</beans>
<literal><tx:advice/></literal> settings - This section summarises the various transactional settings that can be specified - using the <tx:advice/> tag. The default - <tx:advice/> settings are: - - + + This section summarises the various transactional settings that + can be specified using the <tx:advice/> tag. + The default <tx:advice/> settings are: + + - The propagation setting is REQUIRED + The propagation + setting is REQUIRED + The isolation level is DEFAULT + The transaction is read/write + - The transaction timeout defaults to the default timeout of the - underlying transaction system, or or none if timeouts are not supported + The transaction timeout defaults to the default timeout of + the underlying transaction system, or or none if timeouts are not + supported + - Any RuntimeException will trigger - rollback, and any checked Exception - will not + Any RuntimeException will + trigger rollback, and any checked + Exception will not - - - These default settings can be changed; the various - attributes of the <tx:method/> tags that are nested within - <tx:advice/> and <tx:attributes/> - tags are summarized below: - - + + + These default settings can be changed; the various attributes of + the <tx:method/> tags that are nested within + <tx:advice/> and + <tx:attributes/> tags are summarized + below: + +
<literal><tx:method/></literal> settings + Attribute + Required? + Default + Description + name + Yes + - - The method name(s) with which the transaction attributes - are to be associated. The wildcard (*) character can be used to - associate the same transaction attribute settings with a number - of methods; for example, 'get*', - 'handle*', 'on*Event', and so forth. - + + The method name(s) with which the transaction + attributes are to be associated. The wildcard (*) character + can be used to associate the same transaction attribute + settings with a number of methods; for example, + 'get*', + 'handle*', 'on*Event', + and so forth. + propagation + No + REQUIRED + The transaction propagation behavior + isolation + No + DEFAULT + The transaction isolation level + timeout + No + -1 + The transaction timeout value (in seconds) + read-only + No + false + Is this transaction read-only? + rollback-for + No + - - The Exception(s) that will trigger - rollback; comma-delimited. For example, - 'com.foo.MyBusinessException,ServletException' - + + The Exception(s) that will + trigger rollback; comma-delimited. For example, + 'com.foo.MyBusinessException,ServletException' + no-rollback-for + No + - - The Exception(s) that will - not trigger rollback; comma-delimited. - For example, - 'com.foo.MyBusinessException,ServletException' - + + The Exception(s) that will + not trigger rollback; comma-delimited. + For example, + 'com.foo.MyBusinessException,ServletException' -
-
-
+ +
Using <interfacename>@Transactional</interfacename> - - The functionality offered by the @Transactional - annotation and the support classes is only available to you if you - are using at least Java 5 (Tiger). - - In addition to the XML-based declarative approach to transaction configuration, - you can also use an annotation-based approach to transaction configuration. Declaring - transaction semantics directly in the Java source code puts the declarations much - closer to the affected code, and there is generally not much danger of undue coupling, - since code that is meant to be used transactionally is almost always deployed that way - anyway. - The ease-of-use afforded by the use of the @Transactional - annotation is best illustrated with an example, after which all of the details - will be explained. Consider the following class definition: - // the service class that we want to make transactional@Transactional + The functionality offered by the + @Transactional annotation and the + support classes is only available to you if you are using at least + Java 5 (Tiger). + + + In addition to the XML-based declarative approach to transaction + configuration, you can also use an annotation-based approach to + transaction configuration. Declaring transaction semantics directly in + the Java source code puts the declarations much closer to the affected + code, and there is generally not much danger of undue coupling, since + code that is meant to be used transactionally is almost always deployed + that way anyway. + + The ease-of-use afforded by the use of the + @Transactional annotation is best + illustrated with an example, after which all of the details will be + explained. Consider the following class definition: + + // the service class that we want to make transactional +@Transactional public class DefaultFooService implements FooService { Foo getFoo(String fooName); @@ -1066,13 +1298,15 @@ public class DefaultFooService implements FooService { void insertFoo(Foo foo); void updateFoo(Foo foo); -}]]> - When the above POJO is defined as a bean in a Spring IoC container, the bean - instance can be made transactional by adding merely one line of - XML configuration, like so: - <!-- from the file 'context.xml' --> - + + When the above POJO is defined as a bean in a Spring IoC + container, the bean instance can be made transactional by adding merely + one line of XML configuration, like so: + + <!-- from the file 'context.xml' --> +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" @@ -1082,417 +1316,519 @@ public class DefaultFooService implements FooService { http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop - http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> + http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> - ]]><!-- this is the service object that we want to make transactional --> + <!-- this is the service object that we want to make transactional --> + <bean id="fooService" class="x.y.service.DefaultFooService"/> - ]]><!-- enable the configuration of transactional behavior based on annotations -->]]><!-- enable the configuration of transactional behavior based on annotations --> + <tx:annotation-driven transaction-manager="txManager"/> - ]]><!-- a PlatformTransactionManager is still required --> - ]]><!-- (this dependency is defined somewhere else) --> - + <!-- a PlatformTransactionManager is still required --> + <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> + <!-- (this dependency is defined somewhere else) --> + <property name="dataSource" ref="dataSource"/> + </bean> - ]]><!-- other <bean/> definitions here --><!-- other <bean/> definitions here --> + +</beans> -]]> - You can actually omit the 'transaction-manager' - attribute in the <tx:annotation-driven/> tag - if the bean name of the PlatformTransactionManager - that you want to wire in has the name 'transactionManager'. - If the PlatformTransactionManager bean - that you want to dependency inject has any other name, then you have to be - explicit and use the 'transaction-manager' attribute as - in the example above. + You can actually omit the + 'transaction-manager' attribute in the + <tx:annotation-driven/> tag if the bean name + of the PlatformTransactionManager that + you want to wire in has the name + 'transactionManager'. If the + PlatformTransactionManager bean that + you want to dependency inject has any other name, then you have to be + explicit and use the 'transaction-manager' + attribute as in the example above. + - Method visibility and <interfacename>@Transactional</interfacename> - When using proxies, the @Transactional annotation - should only be applied to methods with public visibility. - If you do annotate protected, private or package-visible methods with the - @Transactional annotation, no error will be raised, - but the annotated method will not exhibit the configured transactional settings. - Consider the use of AspectJ (see below) if you need to annotate non-public methods. + Method visibility and + <interfacename>@Transactional</interfacename> + + When using proxies, the + @Transactional annotation should only + be applied to methods with public visibility. If + you do annotate protected, private or package-visible methods with the + @Transactional annotation, no error + will be raised, but the annotated method will not exhibit the + configured transactional settings. Consider the use of AspectJ (see + below) if you need to annotate non-public methods. - The @Transactional annotation may be placed - before an interface definition, a method on an interface, a class definition, or a - public method on a class. However, please note that the mere - presence of the @Transactional annotation is not - enough to actually turn on the transactional behavior - the - @Transactional annotation is simply metadata - that can be consumed by something that is @Transactional-aware - and that can use the metadata to configure the appropriate beans with transactional - behavior. In the case of the above example, it is the presence of the + + The @Transactional annotation may + be placed before an interface definition, a method on an interface, a + class definition, or a public method on a class. + However, please note that the mere presence of the + @Transactional annotation is not enough + to actually turn on the transactional behavior - the + @Transactional annotation is + simply metadata that can be consumed by something that is + @Transactional-aware and that can use the + metadata to configure the appropriate beans with transactional behavior. + In the case of the above example, it is the presence of the <tx:annotation-driven/> element that switches on the transactional behavior. - The Spring team's recommendation is that you only annotate concrete - classes with the @Transactional annotation, - as opposed to annotating interfaces. You certainly can place the - @Transactional annotation on an interface (or - an interface method), but this will only work as you would expect it to if - you are using interface-based proxies. The fact that annotations are - not inherited means that if you are using class-based - proxies (proxy-target-class="true") or the weaving-based aspect - (mode="aspectj") then the transaction settings will not be - recognised by the proxying/weaving infrastructure and the object will not be - wrapped in a transactional proxy (which would be decidedly bad). - So please do take the Spring team's advice and only annotate concrete classes - (and the methods of concrete classes) with the + The Spring team's recommendation is that you only annotate + concrete classes with the @Transactional + annotation, as opposed to annotating interfaces. You certainly can place + the @Transactional annotation on an + interface (or an interface method), but this will only work as you would + expect it to if you are using interface-based proxies. The fact that + annotations are not inherited means that if you are + using class-based proxies (proxy-target-class="true") + or the weaving-based aspect (mode="aspectj") then the + transaction settings will not be recognised by the proxying/weaving + infrastructure and the object will not be wrapped in a transactional + proxy (which would be decidedly bad). So please do + take the Spring team's advice and only annotate concrete classes (and + the methods of concrete classes) with the @Transactional annotation. - Note: In proxy mode (which is the default), only 'external' - method calls coming in through the proxy will be intercepted. - This means that 'self-invocation', i.e. a method within the target object - calling some other method of the target object, won't lead to an actual - transaction at runtime even if the invoked method is marked with + Note: In proxy mode (which is the default), only + 'external' method calls coming in through the proxy will be + intercepted. This means that 'self-invocation', i.e. a method + within the target object calling some other method of the target object, + won't lead to an actual transaction at runtime even if the invoked + method is marked with @Transactional! Consider the use of AspectJ mode (see below) if you expect self-invocations to be wrapped with transactions as well. In this case, there won't be a proxy in the first place; instead, the target class - will be 'weaved' (i.e. its byte code will be modified) in order to - turn @Transactional into runtime behavior - on any kind of method. + will be 'weaved' (i.e. its byte code will be modified) in order to turn + @Transactional into runtime behavior on + any kind of method. + + + <literal><tx:annotation-driven/></literal> + settings - -
- <literal><tx:annotation-driven/></literal> settings Attribute + Default + Description + transaction-manager + transactionManager - The name of transaction manager to use. Only required - if the name of the transaction manager is not transactionManager, - as in the example above. + + The name of transaction manager to use. Only + required if the name of the transaction manager is not + transactionManager, as in the example + above. + mode + proxy - The default mode "proxy" will process annotated beans - to be proxied using Spring's AOP framework (following proxy semantics, - as discussed above, applying to method calls coming in through the proxy only). - The alternative mode "aspectj" will instead weave the affected classes with - Spring's AspectJ transaction aspect (modifying the target class byte code - in order to apply to any kind of method call). + + The default mode "proxy" will process annotated + beans to be proxied using Spring's AOP framework (following + proxy semantics, as discussed above, applying to method calls + coming in through the proxy only). The alternative mode + "aspectj" will instead weave the affected classes with + Spring's AspectJ transaction aspect (modifying the target + class byte code in order to apply to any kind of method call). AspectJ weaving requires spring-aspects.jar on the classpath - as well as load-time weaving (or compile-time weaving) enabled. - (See the section entitled - for details on how to set up load-time weaving.) + as well as load-time weaving (or compile-time weaving) + enabled. (See the section entitled for details on how to set up + load-time weaving.) + proxy-target-class + false - Applies to proxy mode only. Controls what type - of transactional proxies are created for classes annotated - with the @Transactional annotation. + + Applies to proxy mode only. Controls what type of + transactional proxies are created for classes annotated with + the @Transactional annotation. If "proxy-target-class" attribute is set to - "true", then class-based proxies will be created. - If "proxy-target-class" is "false" - or if the attribute is omitted, then standard JDK interface-based proxies - will be created. (See the section entitled - for a detailed examination of the different proxy types.) + "true", then class-based proxies will be + created. If "proxy-target-class" is + "false" or if the attribute is omitted, + then standard JDK interface-based proxies will be created. + (See the section entitled for + a detailed examination of the different proxy + types.) + order + Ordered.LOWEST_PRECEDENCE - Defines the order of the transaction advice that will be applied to - beans annotated with @Transactional. More on the - rules related to ordering of AOP advice can be found in the AOP chapter (see section - ). Note that not specifying - any ordering will leave the decision as to what order advice is run in to - the AOP subsystem. + + Defines the order of the transaction advice that + will be applied to beans annotated with + @Transactional. More on the + rules related to ordering of AOP advice can be found in the + AOP chapter (see section ). Note that not + specifying any ordering will leave the decision as to what + order advice is run in to the AOP subsystem. -
-
+
- - The "proxy-target-class" attribute on the - <tx:annotation-driven/> element controls - what type of transactional proxies are created for classes annotated - with the @Transactional annotation. - If "proxy-target-class" attribute is set to - "true", then class-based proxies will be created. - If "proxy-target-class" is "false" - or if the attribute is omitted, then standard JDK interface-based proxies - will be created. (See the section entitled - for a detailed examination of the different proxy types.) - - Note that <tx:annotation-driven/> only looks for - @Transactional on beans in the same application context it is defined in. - This means that, if you put <tx:annotation-driven/> in a - WebApplicationContext for a DispatcherServlet, it only - checks for @Transactional beans in your controllers, and not your services. - See for more information. + The "proxy-target-class" attribute on the + <tx:annotation-driven/> element controls what + type of transactional proxies are created for classes annotated with + the @Transactional annotation. If + "proxy-target-class" attribute is set to + "true", then class-based proxies will be created. + If "proxy-target-class" is + "false" or if the attribute is omitted, then + standard JDK interface-based proxies will be created. (See the section + entitled for a detailed examination of + the different proxy types.) - The most derived location takes precedence when evaluating the transactional - settings for a method. In the case of the following example, the - DefaultFooService class is annotated at the class level - with the settings for a read-only transaction, but the - @Transactional annotation on the - updateFoo(Foo) method in the same class takes precedence - over the transactional settings defined at the class level. - + Note that <tx:annotation-driven/> only + looks for @Transactional on beans in + the same application context it is defined in. This means that, if you + put <tx:annotation-driven/> in a + WebApplicationContext for a + DispatcherServlet, it only checks for + @Transactional beans in your + controllers, and not your services. See + for more information. + + + The most derived location takes precedence when evaluating the + transactional settings for a method. In the case of the following + example, the DefaultFooService class is annotated + at the class level with the settings for a read-only transaction, but + the @Transactional annotation on the + updateFoo(Foo) method in the same class takes + precedence over the transactional settings defined at the class + level. + + @Transactional(readOnly = true) public class DefaultFooService implements FooService { public Foo getFoo(String fooName) { - ]]>// do something// do something } - ]]>// these settings have precedence for this method// these settings have precedence for this method @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) public void updateFoo(Foo foo) { - ]]>// do something// do something } -}]]> +}
<interfacename>@Transactional</interfacename> settings + The @Transactional annotation is metadata that specifies that an interface, class, or method must have - transactional semantics; for example, start a brand new read-only - transaction when this method is invoked, suspending any existing - transaction. The default + transactional semantics; for example, start a brand + new read-only transaction when this method is invoked, suspending any + existing transaction. The default @Transactional settings are: + - The propagation setting is PROPAGATION_REQUIRED + The propagation setting is + PROPAGATION_REQUIRED + - The isolation level is ISOLATION_DEFAULT + The isolation level is + ISOLATION_DEFAULT + The transaction is read/write + - The transaction timeout defaults to the default timeout of the - underlying transaction system, or or none if timeouts are not supported + The transaction timeout defaults to the default timeout of + the underlying transaction system, or or none if timeouts are not + supported + - Any RuntimeException will trigger - rollback, and any checked Exception - will not + Any RuntimeException will + trigger rollback, and any checked + Exception will not - These default settings can be changed; the various - properties of the @Transactional annotation - are summarized in the following table: - - - <interfacename>@Transactional</interfacename> properties + + These default settings can be changed; the various properties of + the @Transactional annotation are + summarized in the following table: + +
+ <interfacename>@Transactional</interfacename> + properties + Property + Type + Description + - - propagation - + propagation + enum: Propagation + optional propagation setting + - - isolation - + isolation + enum: Isolation + optional isolation level + - - readOnly - + readOnly + boolean + read/write vs. read-only transaction + - - timeout - + timeout + int (in seconds granularity) + the transaction timeout + - - rollbackFor - - an array of Class objects, which - must be derived from Throwable + rollbackFor + + an array of Class objects, + which must be derived from + Throwable + an optional array of exception classes which must cause rollback + - - rollbackForClassname - - an array of class names. Classes - must be derived from Throwable + rollbackForClassname + + an array of class names. + Classes must be derived from + Throwable + an optional array of names of exception classes that must cause rollback + - - noRollbackFor - - an array of Class objects, which - must be derived from Throwable - an optional array of exception classes that - must not cause rollback. + noRollbackFor + + an array of Class objects, + which must be derived from + Throwable + + an optional array of exception classes that must not cause rollback. + - - noRollbackForClassname - - an array of String class names, which - must be derived from Throwable + noRollbackForClassname + + an array of String class + names, which must be derived from + Throwable + an optional array of names of exception classes that - must not cause rollback + must not cause + rollback -
-
- Currently it is not possible to have explicit control over the name of a transaction, where - 'name' means the transaction name that will be shown in a transaction monitor, if applicable (for - example, WebLogic's transaction monitor), and in logging output. For declarative transactions, the - transaction name is always the fully-qualified class name + "." + method name of the - transactionally-advised class. For example, if the handlePayment(..) - method of the BusinessService class started a transaction, the name of the - transaction would be: com.foo.BusinessService.handlePayment. -
-
+ + Currently it is not possible to have explicit control over the + name of a transaction, where 'name' means the transaction name that + will be shown in a transaction monitor, if applicable (for example, + WebLogic's transaction monitor), and in logging output. For + declarative transactions, the transaction name is always the + fully-qualified class name + "." + method name of the + transactionally-advised class. For example, if the + handlePayment(..) method of the + BusinessService class started a transaction, + the name of the transaction would be: + com.foo.BusinessService.handlePayment. + +
Transaction propagation - Please note that this section of the Spring reference documentation is - not an introduction to transaction propagation proper; rather it details some of the - semantics regarding transaction propagation in Spring. - In the case of Spring-managed transactions, please be aware of the difference between - physical and logical transactions, and how the propagation - setting applies to this difference. -
- Required - - - - - - - PROPAGATION_REQUIRED - - - - When the propagation setting is PROPAGATION_REQUIRED, a - logical transaction scope is created for each method that it gets applied to. Each - such logical transaction scope can individually decide on rollback-only status, with an outer - transaction scope being logically independent from the inner transaction scope. Of course, in case of - standard PROPAGATION_REQUIRED behavior, they will be mapped to the same physical - transaction. So a rollback-only marker set in the inner transaction scope does affect the outer - transactions chance to actually commit (as you would expect it to). - However, in the case where an inner transaction scopes sets the rollback-only marker, the outer - transaction itself has not decided on the rollback itself, and so the rollback (silently triggered by - the inner transaction scope) is unexpected: a corresponding - UnexpectedRollbackException will be thrown at that point. This is - expected behavior so that the caller of a transaction can never be misled to assume - that a commit was performed when it really was not. So if an inner transaction (that the outer caller is - not aware of) silently marks a transaction as rollback-only, the outer caller would still innocently - call commit - and needs to receive an UnexpectedRollbackException to indicate - clearly that a rollback was performed instead. -
+ Please note that this section of the Spring reference + documentation is not an introduction to transaction + propagation proper; rather it details some of the semantics regarding + transaction propagation in Spring. -
- RequiresNew - - - - - - - PROPAGATION_REQUIRES_NEW - - - - PROPAGATION_REQUIRES_NEW, in contrast, uses a completely - independent transaction for each affected transaction scope. In that case, the underlying physical - transactions will be different and hence can commit or rollback independently, with an outer transaction - not affected by an inner transaction's rollback status. -
+ In the case of Spring-managed transactions, please be aware of the + difference between physical and + logical transactions, and how the propagation + setting applies to this difference. -
- Nested - PROPAGATION_NESTED is different again in that it uses a - single physical transaction with multiple savepoints that it can roll back to. - Such partial rollbacks allow an inner transaction scope to trigger a rollback - for its scope, with the outer transaction being able to continue the physical - transaction despite some operations having been rolled back. This is typically mapped onto JDBC - savepoints, so will only work with JDBC resource transactions (see Spring's - DataSourceTransactionManager). -
+
+ Required -
+ + + + -
+ PROPAGATION_REQUIRED + + + When the propagation setting is + PROPAGATION_REQUIRED, a + logical transaction scope is created for each + method that it gets applied to. Each such logical transaction scope + can individually decide on rollback-only status, with an outer + transaction scope being logically independent from the inner + transaction scope. Of course, in case of standard + PROPAGATION_REQUIRED behavior, they will be mapped + to the same physical transaction. So a rollback-only marker set in the + inner transaction scope does affect the outer transactions chance to + actually commit (as you would expect it to). + + However, in the case where an inner transaction scopes sets the + rollback-only marker, the outer transaction itself has not decided on + the rollback itself, and so the rollback (silently triggered by the + inner transaction scope) is unexpected: a corresponding + UnexpectedRollbackException will be thrown at + that point. This is expected behavior so that the + caller of a transaction can never be misled to assume that a commit + was performed when it really was not. So if an inner transaction (that + the outer caller is not aware of) silently marks a transaction as + rollback-only, the outer caller would still innocently call commit - + and needs to receive an + UnexpectedRollbackException to indicate clearly + that a rollback was performed instead. +
+ +
+ RequiresNew + + + + + + + PROPAGATION_REQUIRES_NEW + + + PROPAGATION_REQUIRES_NEW, in contrast, uses a + completely independent transaction for each + affected transaction scope. In that case, the underlying physical + transactions will be different and hence can commit or rollback + independently, with an outer transaction not affected by an inner + transaction's rollback status. +
+ +
+ Nested + + PROPAGATION_NESTED is different again in that + it uses a single physical transaction with + multiple savepoints that it can roll back to. Such partial rollbacks + allow an inner transaction scope to trigger a rollback for + its scope, with the outer transaction being able to + continue the physical transaction despite some operations having been + rolled back. This is typically mapped onto JDBC savepoints, so will + only work with JDBC resource transactions (see Spring's + DataSourceTransactionManager). +
+
+ +
Advising transactional operations Consider the situation where you would like to execute - both transactional and - (to keep things simple) some basic profiling advice. How do you - effect this in the context of using - <tx:annotation-driven/>? - What we want to see when we invoke the updateFoo(Foo) - method is: + both transactional and (to + keep things simple) some basic profiling advice. How do you effect this + in the context of using + <tx:annotation-driven/>? + + What we want to see when we invoke the + updateFoo(Foo) method is: the configured profiling aspect starting up, + then the transactional advice executing, + then the method on the advised object executing + - then the transaction committing (we'll assume a sunny day scenario here), + then the transaction committing (we'll assume a sunny day + scenario here), + - and then finally the profiling aspect reporting (somehow) exactly - how long the whole transactional method invocation took + and then finally the profiling aspect reporting (somehow) + exactly how long the whole transactional method invocation + took + - This chapter is not concerned with explaining AOP in any great detail - (except as it applies to transactions). Please see the chapter entitled - for detailed coverage of the various bits and pieces - of the following AOP configuration (and AOP in general). + This chapter is not concerned with explaining AOP in any great + detail (except as it applies to transactions). Please see the chapter + entitled for detailed coverage of the various + bits and pieces of the following AOP configuration (and AOP in + general). - Here is the code for a simple profiling aspect. The - ordering of advice is controlled via the Ordered - interface. For full details on advice ordering, see . - Here is the code for a simple profiling aspect. The ordering of + advice is controlled via the Ordered + interface. For full details on advice ordering, see . + + package x.y; import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.util.StopWatch; @@ -1502,7 +1838,7 @@ public class SimpleProfiler implements Ordered { private int order; - ]]>// allows us to control the ordering of advice// allows us to control the ordering of advice public int getOrder() { return this.order; } @@ -1511,7 +1847,7 @@ public class SimpleProfiler implements Ordered { this.order = order; } - ]]>// this method is the around advice// this method is the around advice public Object profile(ProceedingJoinPoint call) throws Throwable { Object returnValue; StopWatch clock = new StopWatch(getClass().getName()); @@ -1525,9 +1861,10 @@ public class SimpleProfiler implements Ordered { return returnValue; } } -]]> - - + + <?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" @@ -1537,47 +1874,53 @@ public class SimpleProfiler implements Ordered { http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop - http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> + http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> - + <bean id="fooService" class="x.y.service.DefaultFooService"/> - ]]><!-- this is the aspect --> - ]]><!-- execute before the transactional advice (hence the lower order number) -->value="1" - + <!-- this is the aspect --> + <bean id="profiler" class="x.y.SimpleProfiler"> + <!-- execute before the transactional advice (hence the lower order number) --> + <property name="order" value="1"/> + </bean> - order="200" + <tx:annotation-driven transaction-manager="txManager" order="200"/> - - ]]><!-- this advice will execute around the transactional advice --> - - - - + <aop:config> + <!-- this advice will execute around the transactional advice --> + <aop:aspect id="profilingAspect" ref="profiler"> + <aop:pointcut id="serviceMethodWithReturnValue" + expression="execution(!void x.y..*Service.*(..))"/> + <aop:around method="profile" pointcut-ref="serviceMethodWithReturnValue"/> + </aop:aspect> + </aop:config> - - - - - - + <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> + <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/> + <property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/> + <property name="username" value="scott"/> + <property name="password" value="tiger"/> + </bean> - - - + <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> + <property name="dataSource" ref="dataSource"/> + </bean> -]]> - The result of the above configuration will be a 'fooService' - bean that has profiling and transactional aspects applied to it - in that order. The configuration of any number of additional - aspects is effected in a similar fashion. - Finally, find below some example configuration for effecting the same - setup as above, but using the purely XML declarative approach. - - + + The result of the above configuration will be a + 'fooService' bean that has profiling and + transactional aspects applied to it in that order. + The configuration of any number of additional aspects is effected in a + similar fashion. + + Finally, find below some example configuration for effecting the + same setup as above, but using the purely XML declarative + approach. + + <?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" @@ -1587,156 +1930,182 @@ public class SimpleProfiler implements Ordered { http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop - http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> + http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> - + <bean id="fooService" class="x.y.service.DefaultFooService"/> - ]]><!-- the profiling advice --> - ]]><!-- execute before the transactional advice (hence the lower order number) --><property name="order" value="1 - + <!-- the profiling advice --> + <bean id="profiler" class="x.y.SimpleProfiler"> + <!-- execute before the transactional advice (hence the lower order number) --> + <property name="order" value="1"/> + </bean> - + <aop:config> - + <aop:pointcut id="entryPointMethod" expression="execution(* x.y..*Service.*(..))"/> - ]]><!-- will execute after the profiling advice (c.f. the order attribute) --><!-- will execute after the profiling advice (c.f. the order attribute) --> + <aop:advisor advice-ref="txAdvice" pointcut-ref="entryPointMethod" - ]]>order="2"/> <!-- order value is higher than the profiling aspect -->order="2"/> <!-- order value is higher than the profiling aspect --> - - - - + <aop:aspect id="profilingAspect" ref="profiler"> + <aop:pointcut id="serviceMethodWithReturnValue" + expression="execution(!void x.y..*Service.*(..))"/> + <aop:around method="profile" pointcut-ref="serviceMethodWithReturnValue"/> + </aop:aspect> - + </aop:config> - - - - - - + <tx:advice id="txAdvice" transaction-manager="txManager"> + <tx:attributes> + <tx:method name="get*" read-only="true"/> + <tx:method name="*"/> + </tx:attributes> + </tx:advice> - ]]><!-- other <bean/> definitions such as a DataSource and a PlatformTransactionManager here --><!-- other <bean/> definitions such as a DataSource and a PlatformTransactionManager here --> -]]> - The result of the above configuration will be a 'fooService' - bean that has profiling and transactional aspects applied to it - in that order. If we wanted the profiling advice to execute - after the transactional advice on the way in, and - before the transactional advice on the way out, then we would - simply swap the value of the profiling aspect bean's 'order' - property such that it was higher than the transactional advice's order value. - The configuration of any number of additional aspects is achieved in a - similar fashion. +</beans> + + The result of the above configuration will be a + 'fooService' bean that has profiling and + transactional aspects applied to it in that order. + If we wanted the profiling advice to execute after + the transactional advice on the way in, and before + the transactional advice on the way out, then we would simply swap the + value of the profiling aspect bean's 'order' property + such that it was higher than the transactional advice's order + value. + + The configuration of any number of additional aspects is achieved + in a similar fashion.
- Using <interfacename>@Transactional</interfacename> with AspectJ + Using <interfacename>@Transactional</interfacename> with + AspectJ + It is also possible to use the Spring Framework's - @Transactional support outside of a Spring container - by means of an AspectJ aspect. To use this support you must first - annotate your classes (and optionally your classes' methods with the - @Transactional annotation, and then you must link - (weave) your application with the + @Transactional support outside of a + Spring container by means of an AspectJ aspect. To use this support you + must first annotate your classes (and optionally your classes' methods + with the @Transactional annotation, and + then you must link (weave) your application with the org.springframework.transaction.aspectj.AnnotationTransactionAspect - defined in the spring-aspects.jar file. - The aspect must also be configured with a transaction manager. You could of course - use the Spring Framework's IoC container to take care of dependency injecting the - aspect. The simplest way to - configure the transaction management aspect is to use the - '<tx:annotation-driven/>' element and specify the - mode attribute to asepctj as described in - . - - + defined in the spring-aspects.jar file. The aspect must + also be configured with a transaction manager. You could of course use + the Spring Framework's IoC container to take care of dependency + injecting the aspect. The simplest way to configure the transaction + management aspect is to use the + '<tx:annotation-driven/>' element and specify + the mode attribute to asepctj as + described in . Since we're focusing here on applications running outside of a Spring container, we'll show you how to do it programmatically. + - Prior to continuing, you may well want to read the previous sections entitled - and - respectively. + Prior to continuing, you may well want to read the previous + sections entitled and respectively. - // construct an appropriate transaction manager // construct an appropriate transaction manager DataSourceTransactionManager txManager = new DataSourceTransactionManager(getDataSource()); -]]>// configure the AnnotationTransactionAspect to use it; this must be done before executing any transactional methods +// configure the AnnotationTransactionAspect to use it; this must be done before executing any transactional methods +AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); - When using this aspect, you must annotate the implementation - class (and/or methods within that class), not the interface - (if any) that the class implements. AspectJ follows Java's rule that annotations on - interfaces are not inherited. - + When using this aspect, you must annotate the + implementation class (and/or methods within that + class), not the interface (if any) that the class + implements. AspectJ follows Java's rule that annotations on interfaces + are not inherited. + - The @Transactional annotation on a class specifies - the default transaction semantics for the execution of any method in the class. - The @Transactional annotation on a method within - the class overrides the default transaction semantics given by the class annotation - (if present). Any method may be annotated, regardless of visibility. - To weave your applications with the AnnotationTransactionAspect - you must either build your application with AspectJ (see the - AspectJ Development Guide) - or use load-time weaving. See the section entitled for a - discussion of load-time weaving with AspectJ. + The @Transactional annotation on a + class specifies the default transaction semantics for the execution of + any method in the class. + + The @Transactional annotation on a + method within the class overrides the default transaction semantics + given by the class annotation (if present). Any method may be annotated, + regardless of visibility. + + To weave your applications with the + AnnotationTransactionAspect you must either build + your application with AspectJ (see the AspectJ + Development Guide) or use load-time weaving. See the section + entitled for a discussion of load-time + weaving with AspectJ.
Programmatic transaction management - The Spring Framework provides two means of programmatic transaction management: + + The Spring Framework provides two means of programmatic transaction + management: + Using the TransactionTemplate. + - Using a PlatformTransactionManager + Using a + PlatformTransactionManager implementation directly. - If you are going to use programmatic transaction management, the Spring - team generally recommends using the TransactionTemplate. - The second approach is similar to using the JTA UserTransaction - API (although exception handling is less cumbersome). + + If you are going to use programmatic transaction management, the + Spring team generally recommends using the + TransactionTemplate. The second approach is similar + to using the JTA UserTransaction API + (although exception handling is less cumbersome).
Using the <classname>TransactionTemplate</classname> + The TransactionTemplate adopts the same approach as other Spring templates such as the JdbcTemplate. It uses a callback approach, to - free application code from having to do the boilerplate acquisition - and release of transactional resources, and results in code that is - intention driven, in that the code that is written focuses solely - on what the developer wants to do. - - As you will immediately see in the examples that follow, using - the TransactionTemplate absolutely - couples you to Spring's transaction infrastructure and APIs. - Whether or not programmatic transaction management is suitable - for your development needs is a decision that you will have to - make yourself. - - Application code that must execute in a transactional context, - and that will use the TransactionTemplate explicitly, - looks like this. You, as an application developer, will write a - TransactionCallback implementation (typically - expressed as an anonymous inner class) that will contain all of the code - that you need to have execute in the context of a transaction. You will then - pass an instance of your custom TransactionCallback - to the execute(..) method exposed on the - TransactionTemplate. - - ]]>// single TransactionTemplate shared amongst all methods in this instance + As you will immediately see in the examples that follow, using + the TransactionTemplate absolutely couples you + to Spring's transaction infrastructure and APIs. Whether or not + programmatic transaction management is suitable for your development + needs is a decision that you will have to make yourself. + + + Application code that must execute in a transactional context, and + that will use the TransactionTemplate explicitly, + looks like this. You, as an application developer, will write a + TransactionCallback implementation + (typically expressed as an anonymous inner class) that will contain all + of the code that you need to have execute in the context of a + transaction. You will then pass an instance of your custom + TransactionCallback to the + execute(..) method exposed on the + TransactionTemplate. + + public class SimpleService implements Service { + + // single TransactionTemplate shared amongst all methods in this instance private final TransactionTemplate transactionTemplate; - ]]>// use constructor-injection to supply the PlatformTransactionManager// use constructor-injection to supply the PlatformTransactionManager public SimpleService(PlatformTransactionManager transactionManager) { Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null."); this.transactionTemplate = new TransactionTemplate(transactionManager); @@ -1745,49 +2114,58 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); ]]>// the code in this method executes in a transactional context// the code in this method executes in a transactional context public Object doInTransaction(TransactionStatus status) { updateOperation1(); return resultOfUpdateOperation2(); } }); } -}]]> +} + If there is no return value, use the convenient TransactionCallbackWithoutResult class via an anonymous class like so: - TransactionCallbackWithoutResulttransactionTemplate.execute(new TransactionCallbackWithoutResult() { protected void doInTransactionWithoutResult(TransactionStatus status) { updateOperation1(); updateOperation2(); } -});]]> +}); + Code within the callback can roll the transaction back by calling the setRollbackOnly() method on the supplied TransactionStatus object. - transactionTemplate.execute(new TransactionCallbackWithoutResult() { protected void doInTransactionWithoutResult(TransactionStatus status) { try { updateOperation1(); updateOperation2(); } catch (SomeBusinessExeption ex) { - ]]>status.setRollbackOnly();status.setRollbackOnly(); } } -});]]> +}); -
- Specifying transaction settings - Transaction settings such as the propagation mode, the isolation level, - the timeout, and so forth can be set on the TransactionTemplate - either programmatically or in configuration. TransactionTemplate - instances by default have the default transactional settings. - Find below an example of programmatically customizing the - transactional settings for a specific TransactionTemplate. - - + Specifying transaction settings + + Transaction settings such as the propagation mode, the isolation + level, the timeout, and so forth can be set on the + TransactionTemplate either programmatically or + in configuration. TransactionTemplate instances + by default have the default + transactional settings. Find below an example of + programmatically customizing the transactional settings for a specific + TransactionTemplate. + + public class SimpleService implements Service { private final TransactionTemplate transactionTemplate; @@ -1795,36 +2173,43 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); ]]>// the transaction settings can be set here explicitly if so desired// the transaction settings can be set here explicitly if so desired this.transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED); - this.transactionTemplate.setTimeout(30); ]]>// 30 seconds// and so forth...// 30 seconds + // and so forth... } -}]]> - Find below an example of defining a TransactionTemplate with some custom - transactional settings, using Spring XML configuration. The 'sharedTransactionTemplate' - can then be injected into as many services as are required. - - - -"]]> -
- - Finally, instances of the TransactionTemplate class are - threadsafe, in that instances do not maintain any conversational state. - TransactionTemplate instances do - however maintain configuration state, so while a number of classes - may choose to share a single instance of a TransactionTemplate, if a class needed - to use a TransactionTemplate with different settings - (for example, a different isolation level), then two distinct - TransactionTemplate instances would need to be - created and used. - -
+} + + Find below an example of defining a + TransactionTemplate with some custom + transactional settings, using Spring XML configuration. The + 'sharedTransactionTemplate' can then be injected + into as many services as are required. + + <bean id="sharedTransactionTemplate" + class="org.springframework.transaction.support.TransactionTemplate"> + <property name="isolationLevelName" value="ISOLATION_READ_UNCOMMITTED"/> + <property name="timeout" value="30"/> +</bean>" +
+ + Finally, instances of the + TransactionTemplate class are threadsafe, in that + instances do not maintain any conversational state. + TransactionTemplate instances + do however maintain configuration state, so while a + number of classes may choose to share a single instance of a + TransactionTemplate, if a class needed to use a + TransactionTemplate with different settings (for + example, a different isolation level), then two distinct + TransactionTemplate instances would need to be + created and used. +
- Using the <interfacename>PlatformTransactionManager</interfacename> + Using the + <interfacename>PlatformTransactionManager</interfacename> + You can also use the org.springframework.transaction.PlatformTransactionManager directly to manage your transaction. Simply pass the implementation of @@ -1833,141 +2218,174 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); ]]>TransactionDefinition and TransactionStatus objects you can initiate transactions, rollback and commit. - // explicitly setting the transaction name is something that can only be done programmaticallyDefaultTransactionDefinition def = new DefaultTransactionDefinition(); +// explicitly setting the transaction name is something that can only be done programmatically def.setName("SomeTxName"); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); TransactionStatus status = txManager.getTransaction(def); try { - ]]>// execute your business logic here// execute your business logic here } catch (MyException ex) { txManager.rollback(status); throw ex; } -txManager.commit(status);]]> +txManager.commit(status);
- Choosing between programmatic and declarative transaction management + Choosing between programmatic and declarative transaction + management + Programmatic transaction management is usually a good idea only if you have a small number of transactional operations. For example, if you have a web application that require transactions only for certain update operations, you may not want to set up transactional proxies using Spring - or any other technology. In this case, using the TransactionTemplate - may be a good approach. Being able to set the transaction name - explicitly is also something that can only be done using the programmatic - approach to transaction management. + or any other technology. In this case, using the + TransactionTemplate may be a + good approach. Being able to set the transaction name explicitly is also + something that can only be done using the programmatic approach to + transaction management. + On the other hand, if your application has numerous transactional operations, declarative transaction management is usually worthwhile. It keeps transaction management out of business logic, and is not difficult to configure. When using the Spring Framework, rather than EJB CMT, the - configuration cost of declarative transaction management is greatly reduced. + configuration cost of declarative transaction management is greatly + reduced.
Application server-specific integration + Spring's transaction abstraction generally is application server - agnostic. Additionally, Spring's JtaTransactionManager class, - which can optionally perform a JNDI lookup for the JTA + agnostic. Additionally, Spring's + JtaTransactionManager class, which can optionally + perform a JNDI lookup for the JTA UserTransaction and - TransactionManager objects, autodetects - the location for the latter object, which varies by application server. Having - access to the JTA TransactionManager allows for - enhanced transaction semantics, in particular supporting transaction suspension. - Please see the JtaTransactionManager Javadocs for details. - - Spring's JtaTransactionManager is the standard - choice when running on J2EE application servers, known to work on all common - servers. Its advanced functionality such as transaction suspension is known to - work on many servers as well - including GlassFish, JBoss, Geronimo and Oracle - OC4J - without any special configuration required. However, for fully supported - transaction suspension and further advanced integration, Spring ships special - adapters for IBM WebSphere and BEA WebLogic and also for Oracle OC4J. - We'll discuss these adapters in the following sections. - For standard scenarios, including WebLogic, WebSphere and OC4J, - consider using the convenient '<tx:jta-transaction-manager/>' - configuration element. This will automatically detect the underlying - server and choose the best transaction manager available for the platform. - This means that you won't have to configure server-specific adapter classes - (as discussed in the following sections) explicitly; they will rather be chosen - automatically, with the standard JtaTransactionManager - as default fallback. + TransactionManager objects, autodetects the + location for the latter object, which varies by application server. Having + access to the JTA TransactionManager allows + for enhanced transaction semantics, in particular supporting transaction + suspension. Please see the JtaTransactionManager + Javadocs for details. + + Spring's JtaTransactionManager is the + standard choice when running on J2EE application servers, known to work on + all common servers. Its advanced functionality such as transaction + suspension is known to work on many servers as well - including GlassFish, + JBoss, Geronimo and Oracle OC4J - without any special configuration + required. However, for fully supported transaction suspension and further + advanced integration, Spring ships special adapters for IBM WebSphere and + BEA WebLogic and also for Oracle OC4J. We'll discuss these adapters in the + following sections. + + For standard scenarios, including WebLogic, WebSphere and + OC4J, consider using the convenient + '<tx:jta-transaction-manager/>' configuration + element. This will automatically detect the underlying server + and choose the best transaction manager available for the platform. This + means that you won't have to configure server-specific adapter classes (as + discussed in the following sections) explicitly; they will rather be + chosen automatically, with the standard + JtaTransactionManager as default fallback.
IBM WebSphere - On WebSphere 6.1.0.9 and above, the recommended Spring JTA transaction - manager to use is WebSphereUowTransactionManager. - This special adapter leverages IBM's UOWManager - API which is available in WebSphere Application Server 6.0.2.19 or above - and 6.1.0.9 or above. With this adapter, Spring-driven transaction suspension - (suspend/resume as initiated by PROPAGATION_REQUIRES_NEW) - is officially supported by IBM! + + On WebSphere 6.1.0.9 and above, the recommended Spring JTA + transaction manager to use is + WebSphereUowTransactionManager. This special + adapter leverages IBM's UOWManager API + which is available in WebSphere Application Server 6.0.2.19 or above and + 6.1.0.9 or above. With this adapter, Spring-driven transaction + suspension (suspend/resume as initiated by + PROPAGATION_REQUIRES_NEW) is officially supported by + IBM!
BEA WebLogic - On WebLogic 9.0 or above, you will generally prefer to use - the WebLogicJtaTransactionManager instead - of the stock JtaTransactionManager class. - This special WebLogic-specific subclass of the normal + + On WebLogic 9.0 or above, you will generally prefer to use the + WebLogicJtaTransactionManager instead of the + stock JtaTransactionManager class. This special + WebLogic-specific subclass of the normal JtaTransactionManager supports the full power of - Spring's transaction definitions in a WebLogic-managed transaction environment, - beyond standard JTA semantics: Features include transaction names, per-transaction - isolation levels, and proper resuming of transactions in all cases. + Spring's transaction definitions in a WebLogic-managed transaction + environment, beyond standard JTA semantics: Features include transaction + names, per-transaction isolation levels, and proper resuming of + transactions in all cases.
Oracle OC4J + Spring ships a special adapter class for OC4J 10.1.3 or above: OC4JJtaTransactionManager. This is analogous to the WebLogicJtaTransactionManager class discussed in the previous section, providing similar value-adds on OC4J: transaction names and per-transaction isolation levels. - Note that the full JTA functionality, including transaction suspension, - works fine with Spring's JtaTransactionManager on - OC4J as well. The special OC4JJtaTransactionManager - adapter simply provides value-adds beyond standard JTA. + + Note that the full JTA functionality, including transaction + suspension, works fine with Spring's + JtaTransactionManager on OC4J as well. The + special OC4JJtaTransactionManager adapter simply + provides value-adds beyond standard JTA.
Solutions to common problems +
- Use of the wrong transaction manager for a specific <interfacename>DataSource</interfacename> + Use of the wrong transaction manager for a specific + <interfacename>DataSource</interfacename> + You should take care to use the correct - PlatformTransactionManager - implementation for their requirements. Used properly, the Spring Framework - merely provides a straightforward and portable abstraction. If you are using + PlatformTransactionManager implementation + for their requirements. Used properly, the Spring Framework merely + provides a straightforward and portable abstraction. If you are using global transactions, you must use the - org.springframework.transaction.jta.JtaTransactionManager class - (or an - application server-specific subclass - of it) for all your transactional operations. Otherwise the transaction infrastructure - will attempt to perform local transactions on resources such as container - DataSource instances. Such local transactions - do not make sense, and a good application server will treat them as errors. + org.springframework.transaction.jta.JtaTransactionManager + class (or an application + server-specific subclass of it) for all your transactional + operations. Otherwise the transaction infrastructure will attempt to + perform local transactions on resources such as container + DataSource instances. Such local + transactions do not make sense, and a good application server will treat + them as errors.
- Further Resources - Find below links to further resources about the Spring Framework's transaction support. - - - Distributed transactions in Spring, with and without XA - is a JavaWorld feature where SpringSource's David Syer guides you through seven patterns for distributed transactions in Spring applications, three of them with XA - and four without. - - - Java Transaction Design Strategies - is a book available from InfoQ that provides a well-paced - introduction to transactions in Java. It also includes side-by-side examples of how to configure and use - transactions using both the Spring Framework and EJB3. - - -
+ Further Resources + Find below links to further resources about the Spring Framework's + transaction support. + + + + Distributed + transactions in Spring, with and without XA is a JavaWorld + feature where SpringSource's David Syer guides you through seven + patterns for distributed transactions in Spring applications, three of + them with XA and four without. + + + + Java + Transaction Design Strategies is a book available from InfoQ that provides a well-paced + introduction to transactions in Java. It also includes side-by-side + examples of how to configure and use transactions using both the + Spring Framework and EJB3. + + +