diff --git a/spring-framework-reference/src/transaction.xml b/spring-framework-reference/src/transaction.xml index 6ad30d3d2e6a24628cf84c3a8f884862c13e72d3..48744186067953c316474ccaebc9084539761018 100644 --- a/spring-framework-reference/src/transaction.xml +++ b/spring-framework-reference/src/transaction.xml @@ -2,142 +2,112 @@ - Transaction management + Transaction Management
- Introduction + Introduction to Spring Framework transaction management - 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: + Comprehensive transaction support is among the most compelling + reasons to use Spring Framework. 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. + Consistent programming model across different transaction APIs + such as Java Transaction API (JTA), JDBC, Hibernate, Java Persistence + API (JPA), and Java Data Objects (JDO). - Supports declarative + Support for declarative transaction management. - Provides a simpler API for Simpler API for programmatic transaction - management than a number of complex transaction APIs such as - JTA. + management than complex transaction APIs such as JTA. - Integrates very well with Spring's various data access + Excellent integration with Spring's 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). + The following sections describe Spring Framework's transaction + value-adds and technologies. (The chapter also includes discussions of + best practices, application server integration, and solutions to common + problems.) - 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. + Advantages of Spring + Framework's transaction support model describes + why you would use Spring Framework's transaction + abstraction instead of EJB Container-Managed Transactions (CMT) or + choosing to drive transactions through 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 - instances from a variety of sources. + Understanding the Spring + Framework transaction abstraction outlines the core classes and + describes 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. + Synchronizing + resources with transactions describes how the application code + ensures that resources are created, reused, and cleaned up + properly. - The fourth section, entitled Programmatic transaction - management, covers the Spring Framework's support for - programmatic (that is, explicitly coded) transaction + Declarative transaction + management describes support for declarative transaction management. + + + Programmatic + transaction management covers 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. - - 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. - - - 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.) - - - 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. + Advantages of Spring Framework's transaction support model<!--Renamed section to make it more to the point.--> + + Traditionally, Java EE developers have had two choices for + transaction management: global or + local transactions, both of which have profound + limitations. Global and local transaction management is reviewed in the + next two sections, followed by a discussion of how Spring Framework's + transaction management support addresses the limitations of the global and + local transaction models. + + + +
+ Global transactions + + Global transactions enable you to work with multiple transactional + resources, typically relational databases and message queues. The + application server manages global transactions through the JTA, which 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 you + also need to use JNDI in order to use JTA. + Obviously the use of global transactions would limit any potetntial + reuse 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 @@ -145,51 +115,103 @@ role="bold">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. - - - 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. - - 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). + JNDI lookups, although of course the use of EJB itself necessitates the + use of JNDI. It removes most but not all of the need 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 of 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 are resource-specific, such as a transaction + associated with a JDBC connection. 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. Because the application server is not involved in + transaction management, it cannot help ensure correctness across + multiple resources. (It is worth noting that most applications use a + single transaction resource.) Another downside is that local + transactions are invasive to the programming model. +
+ +
+ Spring Framework's consistent programming model + + Spring resolves the disadvantages of global and local + transactions. 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. Spring Framework provides both declarative and + programmatic transaction management. Most users prefer declarative + transaction management, which 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 do not depend on + the Spring Framework transaction API, or any other transaction + API. + + + Do you need an application server for transaction + management? + + Spring Framework's transaction management support changes + traditional rules as to when a Java EE application requires an + application server. + + In particular, you do not need an application server simply for + declarative transactions through EJBs. In fact, even if your + application server has powerful JTA capabilities, you may decide that + the Spring Framework's declarative transactions offer more power and a + more productive programming model than EJB CMT. + + Typically you need an application server's JTA capability only + if your application needs to handle transactions across multiple + resources, which is not a requirement for many applications. Many + high-end applications use a single, highly scalable database (such as + Oracle RAC) instead. Standalone transaction managers such as Atomikos Transactions and + JOTM are other + options. Of course, you may need other application server capabilities + such as Java Message Service (JMS) and J2EE Connector Architecture + (JCA). + + Spring Framework gives you the choice of when to scale + your application to a fully loaded application server. Gone + are the days when the only alternative to using EJB CMT or JTA was to + write code with local transactions such as those on JDBC connections, + and face a hefty rework if you need that code to run within global, + container-managed transactions. With Spring Framework, only some of + the bean definitions in your configuration file, rather than your + code, needs to change. + + + +
- Key abstractions + Understanding the Spring Framework transaction abstraction<!--If this section applies only to prog. tx management, we should say that up front. Add info? TR: It's relevant for declarative tx as well--> 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: + interface: public interface PlatformTransactionManager { @@ -201,22 +223,24 @@ 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, + This is primarily a service provider interface (SPI), although it + can be used programmatically from your + application code. Because 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: + interface, it can be easily mocked or stubbed as + necessary. It is not 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. + are defined like any other object (or bean) in the Spring Framework IoC + container. This benefit alone makes Spring Framework transactions a + worthwhile abstraction even when you work 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 + 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 @@ -228,56 +252,57 @@ 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). + a new transaction, or can represent an existing transaction if a matching + transaction exists in the current call stack. The implication in this + latter case is that, as with Java EE 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 + Isolation: The degree to which + this transaction is isolated 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 + Propagation: Typically, all + code executed within a transaction scope will run in that transaction. + However, you have options for specifying behavior in the event that 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 For + example, code can continue running in the existing transaction (the + common case); or the existing transaction can be suspended and a new + transaction created. Spring offers all of the transaction + propagation options familiar from EJB CMT. To read about + the semantics of transaction propagation in Spring, see . - Timeout: how long this - transaction may run before timing out (and automatically being rolled - back by the underlying transaction infrastructure). + Timeout: How long this + transaction runs before timing out and being rolled back automatically + 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). + 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 you are 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. + necessary, refer to resources that discuss transaction isolation levels + and other core transaction concepts. Understanding these concepts is + essential to using the Spring Framework or any transaction management + solution. The TransactionStatus interface provides a simple way for transactional code to control transaction @@ -303,21 +328,21 @@ 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. + is absolutely essential. You typically define this implementation through + 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.) + they work: JDBC, JTA, Hibernate, and so on. The following examples show + how you can define a local + PlatformTransactionManager implementation. + (This example works with plain JDBC.) - We must define a JDBC DataSource, and - then use the Spring DataSourceTransactionManager, - giving it a reference to the - DataSource. + You define a JDBC DataSource <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}" /> @@ -326,23 +351,21 @@ <property name="password" value="${jdbc.password}" /> </bean> - The related - PlatformTransactionManager bean definition - will look like this: + The related The + PlatformTransactionManager bean definition will then have + a reference to the DataSource definition. + It 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. + If you use JTA in a Java EE container then you use a container + DataSource, obtained through JNDI, in + conjunction with Spring's JtaTransactionManager. + This is what the JTA and JNDI lookup version would look like: + + <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" @@ -362,29 +385,41 @@ </beans> + The JtaTransactionManager does not need to + know about the DataSource, or any other + specific resources, because it uses the container's global transaction + management infrastructure. + - The above definition of the 'dataSource' bean + The above definition of the dataSource bean uses the <jndi-lookup/> tag from the - 'jee' namespace. For more information on schema-based + 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. + You can also use Hibernate local transactions easily, as shown in + the following examples. In this case, you need to define a Hibernate + LocalSessionFactoryBean, which your 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. + be similar to the local JDBC example shown previously and thus not shown + in the following example. - The 'txManager' bean in this case is of the + + + + If the DataSource, used by any + non-JTA transaction manager, is looked up via JNDI and managed by a Java + EE container then it should be non-transactional because the Spring + Framework, rather than the Java EE container, will manage the + 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 @@ -409,105 +444,114 @@ <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. + If you are using Hibernate and Java EE container managed JTA + transactions, then you should simply use the same + JtaTransactionManager as in the previous JTA + example for JDBC. <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. + + If you use JTA then your transacton manager definition will look + the same regardles of what data access technology you use, be it JDBC, + Hibernate JPA or any other supported technology. This is due to the fact + that JTA transactions 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 does not need to change. You + 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 + Synchronizing resources 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 + It should now be clear how you create different transaction + managers, and how they are linked to related resources that need to be 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). This section + describes how the application code, directly or indirectly using a + persistence API such as JDBC, Hibernate, or JDO, ensures that these + resources are created, reused, and cleaned up properly. The section also + discusses how transaction synchronization is triggered (optionally) + through 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. + High-level synchronization approach + + The preferred approach is to use Spring's highest level template + based persistence integration APIs or to use native ORM APIs with + transaction aware factory beans or proxies for managing the native + resource factories. These transaction aware solutions internally handle + resource creation and reuse, cleanup, optional transaction + synchronization of the resources, and exception mapping. Thus user data + access code does not have to address these tasks, but can be focused + purely on non-boilerplate persistence logic. Generally, you use the + native ORM API or a template approach for JDBC + access using the JdbcTemplate. All of these + solutions are detailed in subsequent chapters of this reference + documentation.
- Low-level approach + Low-level synchronization approach - At a lower level exist classes such as - DataSourceUtils (for JDBC), + Classes such as DataSourceUtils (for JDBC), + EntityManagerFactoryUtils (for JPA), SessionFactoryUtils (for Hibernate), 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. + on exist at a lower level. When you want the application code to deal + directly with the resource types of the native persistence APIs, you use + these classes to ensure that proper Spring Framework-managed instances + are obtained, transactions are (optionally) synchronized, and exceptions + that occur 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 + DataSource, you 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 + If an existing transaction already has a connection synchronized + (linked) to it, that instance is returned. Otherwise, the method call + triggers the creation of a new connection, which is (optionally) + synchronized to any existing transaction, and made available for + subsequent reuse in that same transaction. As mentioned, any + SQLException is wrapped in a Spring Framework - CannotGetJdbcConnectionException - one of + CannotGetJdbcConnectionException, one of the Spring Framework's hierarchy of unchecked DataAccessExceptions. This - gives you more information than can easily be obtained from the + approach gives you more information than can be obtained easily from the SQLException, and ensures portability - across databases: even across different persistence technologies. + 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. + This approach also works 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 + Of course, once you have used Spring's JDBC support, JPA 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 + because you will be much happier working through 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 + occurs behind the scenes and you won't need to write any special code. + +
@@ -519,74 +563,73 @@ 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. + provided by a Java EE 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. + class, except when existing code must be called and passed a standard + JDBC DataSource interface implementation. + In that case, it is possible that this code is usable, but participating + in Spring managed transactions. It is preferable to write your new code + by 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. - - 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: + + Most Spring Framework users choose declarative transaction + management. This option has the least impact on application code, and + hence is most consistent with the ideals of a + non-invasive lightweight container. + + + Spring Framework's declarative transaction management is made + possible with Spring aspect-oriented programming (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. + + Spring Framework's declarative transaction management is similar to + EJB CMT in that you can 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 between the two types of transaction + management are: - Unlike EJB CMT, which is tied to JTA, the Spring Framework's + Unlike EJB CMT, which is tied to JTA, 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. + work with JTA transactions or local transactions using JDBC, JPA, + Hibernate or JDO by simple adjusting the configuration files. - The Spring Framework enables declarative transaction management - to be applied to any class, not merely special classes such as + You can apply Spring Framework declarative transaction + management to any class, not merely special classes such as EJBs. - The Spring Framework offers declarative Spring Framework offers declarative rollback - rules: this is a feature with no EJB equivalent. - Both programmatic and declarative support for rollback rules is + rules, 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 + Spring Framework enables you to customize transactional + behavior, by using AOP. For example, you can insert custom behavior in + the case of transaction rollback. You can also add arbitrary advice, + along with the transactional advice. With EJB CMT, cannot influence + the container's transaction management except with setRollbackOnly(). - The Spring Framework does not support propagation of transaction + 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 @@ -603,48 +646,46 @@ 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 + The 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. - - 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. + The concept of rollback rules is important: they enable you to + specify which exceptions (and throwables) should + cause automatic rollback. You specify this declaratively, in + configuration, not in Java code. So, although you can still call + setRollbackOnly()on the + TransactionStatus object to roll back the + current transaction back, most often you can specify a rule that + MyApplicationException must always result + in rollback. The significant advantage to this option is that business + objects do not depend on the transaction infrastructure. For example, they + typically do not need to import Spring transaction APIs or other Spring + APIs. + + Although EJB container default behavior automatically rolls 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 behavior. + +
- Understanding the Spring Framework's declarative transaction + <title>Understanding 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 + It is not sufficient to tell you simply 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 + section explains the inner workings of Spring Framework's declarative + transaction infrastructure in the event of transaction-related issues. The most important concepts to grasp with regard to the Spring @@ -659,14 +700,14 @@ 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 . + Spring AOP is covered in . Conceptually, calling a method on a transactional proxy looks like this... + + @@ -679,13 +720,19 @@
- A first example + Example of declarative transaction implementation 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.) + implementation. This example uses the rote Foo + and Bar tropes so that you can concentrate on the + transaction usage without focusing on the domain model. 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 allows you to see + transactions created and then rolled back in response to the + UnsupportedOperationException + instance. // the service interface that we want to make transactional @@ -727,24 +774,14 @@ public class DefaultFooService implements FooService { } - (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. + Assume that the first two methods of the + FooService interface, + getFoo(String) and getFoo(String, String), + must execute in the context of a transaction with read-only + semantics, and that the other methods,insertFoo(Foo) + and updateFoo(Foo), must execute in the context of a + transaction with read-write semantics. The following configuration is + explained in detail in the next few paragraphs. <!-- from the file 'context.xml' --> <?xml version="1.0" encoding="UTF-8"?> @@ -798,49 +835,48 @@ public class DefaultFooService implements FooService { </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 + Examine the preceding configuration. You want to make a service + object, the fooService bean, transactional. The + transaction semantics 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 + 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 - case the 'txManager' bean). + going to 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 + You can 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. + want to wire in has the name transactionManager. If + the PlatformTransactionManager bean + that you want to wire in has any other name, then you must use the + transaction-manager attribute explicitly, as in the + preceding example. 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 + the transactional advice defined by the txAdvice bean + executes at the appropriate points in the program. First you define a + pointcut that matches the execution of any operation defined in the + FooService interface + (fooServiceOperation). Then you 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. + 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. + expression; see 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 @@ -850,26 +886,28 @@ public class DefaultFooService implements FooService { <aop:config> <aop:pointcut id="fooServiceMethods" expression="execution(* x.y.service.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceMethods"/> - </aop:config> +</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.) + + In this example it is assumed that all your service + interfaces are defined in the x.y.service + package; see for more + details. + Now that we've analyzed the configuration, you may be asking 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. + The above configuration will be used to create 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 is started, suspended, marked as read-only, and so on, + depending on the transaction configuration associated with that method. + Consider the following program that test drives the above + configuration: public final class Boot { @@ -880,12 +918,10 @@ public class DefaultFooService implements FooService { } } - 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 output from running the preceding program will resemble the + following. (The Log4J output and the stack trace from the + UnsupportedOperationException thrown by the insertFoo(..) method of the + DefaultFooService class have been truncated for clarity.) <!-- the Spring container is starting up... --> [AspectJInvocationContextExposingAdvisorAutoProxyCreator] - Creating implicit proxy @@ -914,44 +950,47 @@ public class DefaultFooService implements FooService { [DataSourceUtils] - Returning JDBC Connection to DataSource Exception in thread "main" java.lang.UnsupportedOperationException - at x.y.service.DefaultFooService.insertFoo(DefaultFooService.java:14) + at x.y.service.DefaultFooService.insertFoo(DefaultFooService.java:14) <!-- AOP infrastructure stack trace elements removed for clarity --> - at $Proxy0.insertFoo(Unknown Source) - at Boot.main(Boot.java:11) + at $Proxy0.insertFoo(Unknown Source) + at Boot.main(Boot.java:11)
- Rolling back + Rolling back a declarative transaction - 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 + The previous section outlined the basics of how to specify + transactional settings for classes, typically service layer classes, + declaratively in your application. 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 + The recommended way to indicate to 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. Spring Framework's + transaction infrastructure code, in its default configuration, will + catch any unhandled Exception as it + bubbles up the call stack, and mark the transaction for rollback. + + However, Spring Framework's transaction infrastructure code, 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. + (Errors will also - by default - result + in a rollback). Checked exceptions that are thrown from a transactional + method do not result in rollback. + + You can configure exactly which + Exception types mark a transaction for + rollback. The following XML snippet demonstrates how you configure + rollback for a checked, application-specific + Exception type. <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> @@ -961,10 +1000,9 @@ Exception in thread "main" java.lang.UnsupportedOperationException </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 + You can also specify 'no rollback rules', if you do + not want a transaction rolled back when an + exception is thrown. The following example tells Spring Framework's transaction infrastructure to commit the attendant transaction even in the face of an unhandled InstrumentNotFoundException. @@ -976,13 +1014,13 @@ Exception in thread "main" java.lang.UnsupportedOperationException </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. + When Spring Framework's transaction infrastructure catches an + exception and is consults configured rollback rules to determine whether + 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 results in a + rollback of the attendant transaction. <tx:advice id="txAdvice"> <tx:attributes> @@ -990,10 +1028,10 @@ Exception in thread "main" java.lang.UnsupportedOperationException </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: + You can also indicate a required rollback + programmatically. Although very simple, this + process is quite invasive, and tightly couples your code to Spring + Framework's transaction infrastructure: public void resolvePosition() { try { @@ -1007,7 +1045,7 @@ Exception in thread "main" java.lang.UnsupportedOperationException 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. + clean POJO-based architecture.
@@ -1015,17 +1053,18 @@ Exception in thread "main" java.lang.UnsupportedOperationException 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: + objects, and you want to apply a totally different + transactional configuration to each of them. You do this by defining + distinct <aop:advisor/> elements with differing + pointcut and advice-ref attribute + values. + + As a point of comparison, first 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" @@ -1068,8 +1107,8 @@ Exception in thread "main" java.lang.UnsupportedOperationException </beans> - Find below an example of configuring two distinct beans with - totally different transactional settings. + The following example shows how to configure two distinct beans + with totally different transactional settings. <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" @@ -1125,38 +1164,38 @@ Exception in thread "main" java.lang.UnsupportedOperationException
<literal><tx:advice/></literal> settings - This section summarises the various transactional settings that + This section summarizes the various transactional settings that can be specified using the <tx:advice/> tag. The default <tx:advice/> settings are: - The propagation - setting is REQUIRED + Propagation setting is + REQUIRED. - The isolation level is DEFAULT + Isolation level is DEFAULT. - The transaction is read/write + 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 + Transaction timeout defaults to the default timeout of the + underlying transaction system, or none if timeouts are not + supported. - Any RuntimeException will - trigger rollback, and any checked - Exception will not + Any RuntimeException triggers + rollback, and any checked Exception + does not. - These default settings can be changed; the various attributes of + You can change these default settings; the various attributes of the <tx:method/> tags that are nested within <tx:advice/> and <tx:attributes/> tags are summarized @@ -1166,6 +1205,14 @@ Exception in thread "main" java.lang.UnsupportedOperationException <literal><tx:method/></literal> settings + + + + + + + + Attribute @@ -1186,13 +1233,12 @@ Exception in thread "main" java.lang.UnsupportedOperationException - The method name(s) with which the transaction + 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. + get*, handle*, + on*Event, and so forth. @@ -1202,7 +1248,7 @@ Exception in thread "main" java.lang.UnsupportedOperationException REQUIRED - The transaction propagation behavior + Transaction propagation behavior. @@ -1212,7 +1258,7 @@ Exception in thread "main" java.lang.UnsupportedOperationException DEFAULT - The transaction isolation level + Transaction isolation level. @@ -1222,7 +1268,7 @@ Exception in thread "main" java.lang.UnsupportedOperationException -1 - The transaction timeout value (in seconds) + Transaction timeout value (in seconds). @@ -1242,9 +1288,9 @@ Exception in thread "main" java.lang.UnsupportedOperationException - The Exception(s) that will - trigger rollback; comma-delimited. For example, - 'com.foo.MyBusinessException,ServletException' + Exception(s) that trigger + rollback; comma-delimited. For example, + com.foo.MyBusinessException,ServletException. @@ -1254,10 +1300,10 @@ Exception in thread "main" java.lang.UnsupportedOperationException - The Exception(s) that will + Exception(s) that do not trigger rollback; comma-delimited. For example, - 'com.foo.MyBusinessException,ServletException' + com.foo.MyBusinessException,ServletException. @@ -1267,25 +1313,17 @@ Exception in thread "main" java.lang.UnsupportedOperationException
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. + configuration, you can use an annotation-based approach. Declaring + transaction semantics directly in the Java source code puts the + declarations much closer to the affected code. There is not much danger + of undue coupling, because 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: + illustrated with an example, which is explained in the text that + follows. Consider the following class definition: // the service class that we want to make transactional @Transactional @@ -1302,7 +1340,7 @@ public class DefaultFooService implements FooService { 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: + one line of XML configuration: <!-- from the file 'context.xml' --> <?xml version="1.0" encoding="UTF-8"?> @@ -1335,76 +1373,78 @@ public class DefaultFooService implements FooService { </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 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 use the transaction-manager attribute + explicitly, as in the preceding example. 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. + When using proxies, you should apply the + @Transactional annotation only to + methods with public visibility. If you do + annotate protected, private or package-visible methods with the + @Transactional annotation, no error is + raised, but the annotated method does 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 + You can place the @Transactional + annotation 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 + However, 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 + to activate 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 preceding example, the + <tx:annotation-driven/> element 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 - @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 - @Transactional! + + Spring recommends that you only annotate concrete classes (and + methods of 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 works only 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 are not recognized by the proxying and weaving + infrastructure, and the object will not be wrapped in a + transactional proxy, which would be decidedly + bad. + + + + In proxy mode (which is the default), only external method calls + coming in through the proxy are intercepted. This means that + self-invocation, in effect, a method within the target object calling + another method of the target object, will not 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. + self-invocations to be wrapped with transactions as well. In + this case, there will not be a proxy in the first place; instead, the + target class will be weaved (that is, its byte code will be modified) in + order to turn @Transactional into runtime + behavior on any kind of method. <literal><tx:annotation-driven/></literal> @@ -1427,8 +1467,8 @@ public class DefaultFooService implements FooService { <entry>transactionManager</entry> - <entry><para>The name of transaction manager to use. Only - required if the name of the transaction manager is not + <entry><para>Name of transaction manager to use. Only required + if the name of the transaction manager is not <literal>transactionManager</literal>, as in the example above.</para></entry> </row> @@ -1438,18 +1478,17 @@ public class DefaultFooService implements FooService { <entry>proxy</entry> - <entry><para>The default mode "proxy" will process annotated + <entry><para>The default mode "proxy" processes 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 <xref - linkend="aop-aj-ltw-spring" /> for details on how to set up - load-time weaving.)</para></entry> + "aspectj" instead weaves the affected classes with Spring's + AspectJ transaction aspect, modifying the target class byte + code to apply to any kind of method call. AspectJ weaving + requires spring-aspects.jar in the classpath as well as + load-time weaving (or compile-time weaving) enabled. (See + <xref linkend="aop-aj-ltw-spring" /> for details on how to set + up load-time weaving.)</para></entry> </row> <row> @@ -1460,14 +1499,13 @@ public class DefaultFooService implements FooService { <entry><para>Applies to proxy mode only. Controls what type of transactional proxies are created for classes annotated with the <interfacename>@Transactional</interfacename> annotation. - If "<literal>proxy-target-class</literal>" attribute is set to - "<literal>true</literal>", then class-based proxies will be - created. If "<literal>proxy-target-class</literal>" is - "<literal>false</literal>" or if the attribute is omitted, - then standard JDK interface-based proxies will be created. - (See the section entitled <xref linkend="aop-proxying" /> for - a detailed examination of the different proxy - types.)</para></entry> + If the <literal>proxy-target-class</literal> attribute is set + to <literal>true</literal>, then class-based proxies are + created. If <literal>proxy-target-class</literal> is + <literal>false</literal> or if the attribute is omitted, then + standard JDK interface-based proxies are created. (See <xref + linkend="aop-proxying" /> for a detailed examination of the + different proxy types.)</para></entry> </row> <row> @@ -1476,49 +1514,48 @@ public class DefaultFooService implements FooService { <entry>Ordered.LOWEST_PRECEDENCE</entry> <entry><para>Defines the order of the transaction advice that - will be applied to beans annotated with - <interfacename>@Transactional</interfacename>. More on the - rules related to ordering of AOP advice can be found in the - AOP chapter (see section <xref - linkend="aop-ataspectj-advice-ordering" />). Note that not - specifying any ordering will leave the decision as to what - order advice is run in to the AOP subsystem.</para></entry> + is applied to beans annotated with + <interfacename>@Transactional</interfacename>. (For more + information about the rules related to ordering of AOP advice, + see <xref linkend="aop-ataspectj-advice-ordering" />.) No + specified ordering means that the AOP subsystem determines the + order of the advice.</para></entry> </row> </tbody> </tgroup> </table></para> <note> - <para>The "<literal>proxy-target-class</literal>" attribute on the + <para>The <literal>proxy-target-class</literal> attribute on the <literal><tx:annotation-driven/></literal> element controls what type of transactional proxies are created for classes annotated with the <interfacename>@Transactional</interfacename> annotation. If - "<literal>proxy-target-class</literal>" attribute is set to - "<literal>true</literal>", then class-based proxies will be created. - If "<literal>proxy-target-class</literal>" is - "<literal>false</literal>" or if the attribute is omitted, then - standard JDK interface-based proxies will be created. (See the section - entitled <xref linkend="aop-proxying" /> for a detailed examination of - the different proxy types.)</para> + <literal>proxy-target-class</literal> attribute is set to + <literal>true</literal>, class-based proxies are created. If + <literal>proxy-target-class</literal> is <literal>false</literal> or + if the attribute is omitted, standard JDK interface-based proxies are + created. (See <xref linkend="aop-proxying" /> for a discussion of the + different proxy types.)</para> </note> <note> - <para>Note that <literal><tx:annotation-driven/></literal> only - looks for <interfacename>@Transactional</interfacename> on beans in - the same application context it is defined in. This means that, if you - put <literal><tx:annotation-driven/></literal> in a + <para><literal><tx:annotation-driven/></literal> only looks for + <interfacename>@Transactional</interfacename> on beans in the same + application context it is defined in. This means that, if you put + <literal><tx:annotation-driven/></literal> in a <interfacename>WebApplicationContext</interfacename> for a <classname>DispatcherServlet</classname>, it only checks for <interfacename>@Transactional</interfacename> beans in your - controllers, and not your services. See <xref linkend="mvc-servlet" /> - for more information.</para> + controllers, and not your services. <!--I don't understand the logic of preceding explanation. Also identify *it* in first sentence of Note.-->See + <xref linkend="mvc-servlet" /> for more information.</para> </note> <para>The most derived location takes precedence when evaluating the - transactional settings for a method. In the case of the following - example, the <classname>DefaultFooService</classname> class is annotated - at the class level with the settings for a read-only transaction, but - the <interfacename>@Transactional</interfacename> annotation on the + transactional settings for a method. <!--Do you need to clarify what *most derived* location means? Lowest level?-->In + the case of the following example, the + <classname>DefaultFooService</classname> class is annotated at the class + level with the settings for a read-only transaction, but the + <interfacename>@Transactional</interfacename> annotation on the <methodname>updateFoo(Foo)</methodname> method in the same class takes precedence over the transactional settings defined at the class level.</para> @@ -1545,33 +1582,34 @@ public class DefaultFooService implements FooService { transactional semantics; for example, <quote><emphasis>start a brand new read-only transaction when this method is invoked, suspending any existing transaction</emphasis></quote>. The default - <interfacename>@Transactional</interfacename> settings are:</para> + <interfacename>@Transactional</interfacename> settings are as + follows:</para> <itemizedlist> <listitem> - <para>The propagation setting is - <literal>PROPAGATION_REQUIRED</literal></para> + <para>Propagation setting is + <literal>PROPAGATION_REQUIRED.</literal></para> </listitem> <listitem> - <para>The isolation level is - <literal>ISOLATION_DEFAULT</literal></para> + <para>Isolation level is + <literal>ISOLATION_DEFAULT.</literal></para> </listitem> <listitem> - <para>The transaction is read/write</para> + <para>Transaction is read/write.</para> </listitem> <listitem> - <para>The transaction timeout defaults to the default timeout of - the underlying transaction system, or or none if timeouts are not - supported</para> + <para>Transaction timeout defaults to the default timeout of the + underlying transaction system, or to none if timeouts are not + supported.</para> </listitem> <listitem> - <para>Any <exceptionname>RuntimeException</exceptionname> will - trigger rollback, and any checked - <exceptionname>Exception</exceptionname> will not</para> + <para>Any <exceptionname>RuntimeException</exceptionname> triggers + rollback, and any checked <exceptionname>Exception</exceptionname> + does not.<!--Bullet list above does not exactly map to properties in table.ok?--></para> </listitem> </itemizedlist> @@ -1601,7 +1639,7 @@ public class DefaultFooService implements FooService { <entry>enum: <classname>Propagation</classname></entry> - <entry>optional propagation setting</entry> + <entry>Optional propagation setting.</entry> </row> <row> @@ -1609,7 +1647,7 @@ public class DefaultFooService implements FooService { <entry>enum: <classname>Isolation</classname></entry> - <entry>optional isolation level</entry> + <entry>Optional isolation level.</entry> </row> <row> @@ -1617,7 +1655,7 @@ public class DefaultFooService implements FooService { <entry>boolean</entry> - <entry>read/write vs. read-only transaction</entry> + <entry>Read/write vs. read-only transaction</entry> </row> <row> @@ -1625,63 +1663,63 @@ public class DefaultFooService implements FooService { <entry>int (in seconds granularity)</entry> - <entry>the transaction timeout</entry> + <entry>Transaction timeout.</entry> </row> <row> <entry><literal>rollbackFor</literal></entry> - <entry>an array of <classname>Class</classname> objects, - which must be derived from - <classname>Throwable</classname></entry> + <entry>Array of <classname>Class</classname> objects, which + must be derived from + <classname>Throwable.</classname></entry> - <entry>an optional array of exception classes which - <emphasis role="bold">must</emphasis> cause rollback</entry> + <entry>Optional array of exception classes that <emphasis + role="bold">must</emphasis> cause rollback.</entry> </row> <row> <entry><literal>rollbackForClassname</literal></entry> - <entry>an array of <classname></classname> class names. - Classes must be derived from - <classname>Throwable</classname></entry> + <entry>Array of class names. Classes must be derived from + <classname>Throwable.</classname></entry> - <entry>an optional array of names of exception classes that - <emphasis role="bold">must</emphasis> cause rollback</entry> + <entry>Optional array of names of exception classes that + <emphasis role="bold">must</emphasis> cause + rollback.</entry> </row> <row> <entry><literal>noRollbackFor</literal></entry> - <entry>an array of <classname>Class</classname> objects, - which must be derived from - <classname>Throwable</classname></entry> + <entry>Array of <classname>Class</classname> objects, which + must be derived from + <classname>Throwable.</classname></entry> - <entry>an optional array of exception classes that <emphasis + <entry>Optional array of exception classes that <emphasis role="bold">must not</emphasis> cause rollback.</entry> </row> <row> <entry><literal>noRollbackForClassname</literal></entry> - <entry>an array of <classname>String</classname> class - names, which must be derived from - <classname>Throwable</classname></entry> + <entry>Array of <classname>String</classname> class names, + which must be derived from + <classname>Throwable.</classname></entry> - <entry>an optional array of names of exception classes that + <entry>Optional array of names of exception classes that <emphasis role="bold">must not</emphasis> cause - rollback</entry> + rollback.</entry> </row> </tbody> </tgroup> </table></para> - <para>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 + <para>Currently you cannot 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 + "." + <!--Meaning of symbols is unclear.-->method name of the transactionally-advised class. For example, if the <methodname>handlePayment(..)</methodname> method of the <classname>BusinessService</classname> class started a transaction, @@ -1693,15 +1731,18 @@ public class DefaultFooService implements FooService { <section id="tx-propagation"> <title>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. + + + This section describes some semantics of transaction propagation + in Spring. Please note that this section 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. + In Spring-managed transactions, be aware of the difference between + physical and logical + transactions, and how the propagation setting applies to this + difference.
Required @@ -1718,28 +1759,28 @@ public class DefaultFooService implements FooService { 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 + method that to which the setting is applied. Each such logical + transaction scope can determine rollback-only status individually, + with an outer transaction scope being logically independent from the + inner transaction scope. Of course, in case of standard + PROPAGATION_REQUIRED behavior, all these scopes + will be mapped to the same physical transaction. So a rollback-only + marker set in the inner transaction scope does affect the outer + transaction's chance to actually commit (as you would expect it + to). + + However, in the case where an inner transaction scope sets the + rollback-only marker, the outer transaction has not decided on the + rollback itself, and so the rollback (silently triggered by the inner + transaction scope) is unexpected. A corresponding + UnexpectedRollbackException is 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. + was performed when it really was not. So if an inner transaction (of + which the outer caller is not aware) silently marks a transaction as + rollback-only, the outer caller still calls commit. The outer caller + needs to receive an UnexpectedRollbackException + to indicate clearly that a rollback was performed instead.
@@ -1755,10 +1796,11 @@ public class DefaultFooService implements FooService {
- PROPAGATION_REQUIRES_NEW, in contrast, uses a + PROPAGATION_REQUIRES_NEW, in contrast to + PROPAGATION_REQUIRED, 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 + transactions are different and hence can commit or roll back independently, with an outer transaction not affected by an inner transaction's rollback status. @@ -1766,66 +1808,64 @@ public class DefaultFooService implements FooService {
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). + PROPAGATION_NESTED 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 setting is typically mapped onto JDBC savepoints, so will + only work with JDBC resource transactions. See Spring's + DataSourceTransactionManager.
- Advising transactional operations + Advising transactional operations<!--Need better heading? Executing transactional advice?--> - 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 + Suppose you want to execute both + transactional and some basic profiling advice. How + do you effect this in the context of <tx:annotation-driven/>? - What we want to see when we invoke the - updateFoo(Foo) method is: + When you invoke the updateFoo(Foo) + method, you want to see the following actions: - + - the configured profiling aspect starting up, + Configured profiling aspect starts up. - then the transactional advice executing, + Transactional advice executes. - then the method on the advised object executing + Method on the advised object executes. - then the transaction committing (we'll assume a sunny day - scenario here), + Transaction commits. - and then finally the profiling aspect reporting (somehow) - exactly how long the whole transactional method invocation - took + Profiling aspect reports exact duration of the whole + transactional method invocation. - + 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). + detail (except as it applies to transactions). See for detailed coverage 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 discussed above. + The + ordering of advice is controlled through the + Ordered interface. For full details on + advice ordering, see . package x.y; @@ -1909,15 +1949,14 @@ public class SimpleProfiler implements Ordered { </beans> - 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. + The result of the above configuration is a + fooService bean that has profiling and transactional + aspects applied to it in the desired order. You + configure any number of additional aspects in similar fashion. - Finally, find below some example configuration for effecting the - same setup as above, but using the purely XML declarative - approach. + The following example effects the same setup as above, but uses + the purely XML declarative approach. <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" @@ -1970,17 +2009,15 @@ public class SimpleProfiler implements Ordered { </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. + fooService bean that has profiling and transactional + aspects applied to it in that order. If you want + the profiling advice to execute after the + transactional advice on the way in, and before the + transactional advice on the way out, then you simply swap the value of + the profiling aspect bean's order property so that it + is higher than the transactional advice's order value. + + You configure additional aspects in similar fashion.
@@ -1989,26 +2026,25 @@ public class SimpleProfiler implements Ordered { 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 + Spring container by means of an AspectJ aspect. To do so, you first + annotate your classes (and optionally your classes' methods) with the + @Transactional annotation, and then you + 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 . - Since we're focusing here on applications running outside of a Spring - container, we'll show you how to do it programmatically. + also be configured with a transaction manager. You can 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 . Because 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 Prior to continuing, you may want to read and respectively. @@ -2040,9 +2076,9 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); 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. + Development Guide) or use load-time weaving. See for a discussion of load-time weaving with + AspectJ.
@@ -2064,11 +2100,11 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); - 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). + The Spring team generally recommends the + TransactionTemplate for programmatic transaction + management. The second approach is similar to using the JTA + UserTransaction API, although exception + handling is less cumbersome.
Using the <classname>TransactionTemplate</classname> @@ -2082,20 +2118,20 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); - 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 + As you will 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 + looks like the following. You, as an application developer, 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 + (typically expressed as an anonymous inner class) that contains the code + that you need to execute in the context of a transaction. You then pass + an instance of your custom TransactionCallback to the execute(..) method exposed on the TransactionTemplate. @@ -2124,8 +2160,8 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); If there is no return value, use the convenient - TransactionCallbackWithoutResult class via an - anonymous class like so: + TransactionCallbackWithoutResult class with an + anonymous class as follows: transactionTemplate.execute(new TransactionCallbackWithoutResult() { @@ -2138,7 +2174,7 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); Code within the callback can roll the transaction back by calling the setRollbackOnly() method on the supplied - TransactionStatus object. + TransactionStatus object: transactionTemplate.execute(new TransactionCallbackWithoutResult() { @@ -2155,15 +2191,15 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); Specifying transaction settings - Transaction settings such as the propagation mode, the isolation - level, the timeout, and so forth can be set on the + You can specify transaction settings such as the propagation + mode, the isolation level, the timeout, and so forth 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. + transactional settings. The following example shows the + programmatic customization of the transactional settings for a + specific TransactionTemplate: public class SimpleService implements Service { @@ -2180,11 +2216,11 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); - Find below an example of defining a + The following example defines a TransactionTemplate with some custom transactional settings, using Spring XML configuration. The - 'sharedTransactionTemplate' can then be injected - into as many services as are required. + sharedTransactionTemplate can then be injected into + as many services as are required. <bean id="sharedTransactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> @@ -2198,12 +2234,11 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); 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 + number of classes may share a single instance of a + TransactionTemplate, if a class needs 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. + example, a different isolation level), then you need to create two + distinct TransactionTemplate instances.
@@ -2213,11 +2248,11 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); You can also use the org.springframework.transaction.PlatformTransactionManager directly to manage your transaction. Simply pass the implementation of - the PlatformTransactionManager you're - using to your bean via a bean reference. Then, using the + the PlatformTransactionManager you are + using to your bean through a bean reference. Then, using the TransactionDefinition and TransactionStatus objects you can - initiate transactions, rollback and commit. + initiate transactions, roll back, and commit. DefaultTransactionDefinition def = new DefaultTransactionDefinition(); // explicitly setting the transaction name is something that can only be done programmatically @@ -2270,27 +2305,27 @@ txManager.commit(status); 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. + suspension. 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 + standard choice to run on Java EE application servers, and is known to + work on all common servers. Advanced functionality such as transaction + suspension works 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, BEA WebLogic + Server, and Oracle OC4J. These adapters iare discussed in the following + sections. + + For standard scenarios, including WebLogic Server, + WebSphere and OC4J, consider using the convenient + <tx:jta-transaction-manager/> configuration + element. When configured, this element automatically detects + the underlying server and chooses 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; rather, they are chosen automatically, with the standard JtaTransactionManager as default fallback.
@@ -2299,18 +2334,18 @@ txManager.commit(status); 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 + adapter leverages IBM's UOWManager API, + which is available in WebSphere Application Server 6.0.2.19 and later + and 6.1.0.9 and later. With this adapter, Spring-driven transaction suspension (suspend/resume as initiated by PROPAGATION_REQUIRES_NEW) is officially supported by IBM!
- BEA WebLogic + BEA WebLogic Server - On WebLogic 9.0 or above, you will generally prefer to use the + On WebLogic Server 9.0 or above, you typically would use the WebLogicJtaTransactionManager instead of the stock JtaTransactionManager class. This special WebLogic-specific subclass of the normal @@ -2324,17 +2359,17 @@ txManager.commit(status);
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. + Spring ships a special adapter class for OC4J 10.1.3 or later + called OC4JJtaTransactionManager. This class is + analogous to the WebLogicJtaTransactionManager + class discussed in the previous section, providing similar value-adds on + OC4J: transaction names and per-transaction isolation levels. + + 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.
@@ -2345,19 +2380,20 @@ txManager.commit(status); Use of the wrong transaction manager for a specific <interfacename>DataSource</interfacename> - You should take care to use the correct + Use the correct 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 + based on your choice of transactional technologies and 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 + operations. Otherwise the transaction infrastructure attempts 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 + transactions do not make sense, and a good application server treats them as errors.
@@ -2365,17 +2401,17 @@ txManager.commit(status);
Further Resources - Find below links to further resources about the Spring Framework's - transaction support. + For more information about 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. + presentation in which SpringSource's David Syer guides you through + seven patterns for distributed transactions in Spring applications, + three of them with XA and four without. @@ -2383,8 +2419,8 @@ txManager.commit(status); 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. + examples of how to configure and use transactions with both the Spring + Framework and EJB3.
PROPAGATION_REQUIRES_NEW