提交 dd96d6d2 编写于 作者: T Thomas Risberg

Beverly's edits reviewed; changed J2EE to Java EE

上级 fc7c49a2
...@@ -2,142 +2,112 @@ ...@@ -2,142 +2,112 @@
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<chapter id="transaction"> <chapter id="transaction">
<title>Transaction management</title> <title>Transaction Management</title>
<section id="transaction-intro"> <section id="transaction-intro">
<title>Introduction</title> <title>Introduction to Spring Framework transaction management</title>
<para>One of the most compelling reasons to use the Spring Framework is <para>Comprehensive transaction support is among the most compelling
the comprehensive transaction support. The Spring Framework provides a reasons to use Spring Framework. Spring Framework provides a consistent
consistent abstraction for transaction management that delivers the abstraction for transaction management that delivers the following
following benefits:</para> benefits:</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para>Provides a consistent programming model across different <para>Consistent programming model across different transaction APIs
transaction APIs such as JTA, JDBC, Hibernate, JPA, and JDO.</para> such as Java Transaction API (JTA), JDBC, Hibernate, Java Persistence
API (JPA), and Java Data Objects (JDO).</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Supports <link linkend="transaction-declarative">declarative <para>Support for <link linkend="transaction-declarative">declarative
transaction management</link>.</para> transaction management</link>.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Provides a simpler API for <link <para>Simpler API for <link
linkend="transaction-programmatic">programmatic</link> transaction linkend="transaction-programmatic">programmatic</link> transaction
management than a number of complex transaction APIs such as management than complex transaction APIs such as JTA.</para>
JTA.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Integrates very well with Spring's various data access <para>Excellent integration with Spring's data access
abstractions.</para> abstractions.</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>This chapter is divided up into a number of sections, each detailing <para>The following sections describe Spring Framework's transaction
one of the value-adds or technologies of the Spring Framework's value-adds and technologies. (The chapter also includes discussions of
transaction support. The chapter closes up with some discussion of best best practices, application server integration, and solutions to common
practices surrounding transaction management (for example, choosing problems.)</para>
between declarative and programmatic transaction management).</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para>The first section, entitled <link <para><link linkend="transaction-motivation">Advantages of Spring
linkend="transaction-motivation">Motivations</link>, describes Framework's transaction support model</link> describes
<emphasis>why</emphasis> one would want to use the Spring Framework's <emphasis>why</emphasis> you would use Spring Framework's transaction
transaction abstraction as opposed to EJB CMT or driving transactions abstraction instead of EJB Container-Managed Transactions (CMT) or
via a proprietary API such as Hibernate.</para> choosing to drive transactions through a proprietary API such as
Hibernate.</para>
<!--The section (formerly called Motivation) does not mention Hibernate. It talks about local and global.-->
</listitem> </listitem>
<listitem> <listitem>
<para>The second section, entitled <link <para><link linkend="transaction-strategies">Understanding the Spring
linkend="transaction-strategies">Key abstractions</link> outlines the Framework transaction abstraction</link> outlines the core classes and
core classes in the Spring Framework's transaction support, as well as describes how to configure and obtain
how to configure and obtain <interfacename>DataSource</interfacename> <interfacename>DataSource</interfacename> instances from a variety of
instances from a variety of sources.</para> sources.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>The third section, entitled <link <para><link linkend="tx-resource-synchronization">Synchronizing
linkend="transaction-declarative">Declarative transaction resources with transactions </link>describes how the application code
management</link>, covers the Spring Framework's support for ensures that resources are created, reused, and cleaned up
declarative transaction management.</para> properly.<!--Added above link and bullet item.--></para>
</listitem> </listitem>
<listitem> <listitem>
<para>The fourth section, entitled <link <para><link linkend="transaction-declarative">Declarative transaction
linkend="transaction-programmatic">Programmatic transaction management</link> describes support for declarative transaction
management</link>, covers the Spring Framework's support for
programmatic (that is, explicitly coded) transaction
management.</para> management.</para>
</listitem> </listitem>
<listitem>
<para><link linkend="transaction-programmatic">Programmatic
transaction management</link> covers support for programmatic (that
is, explicitly coded) transaction management.</para>
</listitem>
</itemizedlist> </itemizedlist>
</section> </section>
<section id="transaction-motivation"> <section id="transaction-motivation">
<title>Motivations</title> <title>Advantages of Spring Framework's transaction support model<!--Renamed section to make it more to the point.--></title>
<sidebar> <para>Traditionally, Java EE developers have had two choices for
<title>Is an application server needed for transaction transaction management: <emphasis>global</emphasis> or
management?</title> <emphasis>local</emphasis> transactions, both of which have profound
limitations. Global and local transaction management is reviewed in the
<para>The Spring Framework's transaction management support next two sections, followed by a discussion of how Spring Framework's
significantly changes traditional thinking as to when a J2EE application transaction management support addresses the limitations of the global and
requires an application server.</para> local transaction models.</para>
<para>In particular, you don't need an application server just to have <!--Gave global, local, and spring models their own sections. These need to be called out at a higher level, esp. Spring advantage!-->
declarative transactions via EJB. In fact, even if you have an
application server with powerful JTA capabilities, you may well decide <section>
that the Spring Framework's declarative transactions offer more power <title>Global transactions</title>
and a much more productive programming model than EJB CMT.</para>
<para>Global transactions enable you to work with multiple transactional
<para>Typically you need an application server's JTA capability only if resources, typically relational databases and message queues. The
you need to enlist multiple transactional resources, and for many application server manages global transactions through the JTA, which is
applications being able to handle transactions across multiple resources a cumbersome API to use (partly due to its exception model).
isn't a requirement. For example, many high-end applications use a Furthermore, a JTA <interfacename>UserTransaction</interfacename>
single, highly scalable database (such as Oracle 9i RAC). Standalone normally needs to be sourced from JNDI, meaning that you
transaction managers such as <ulink <emphasis>also</emphasis> need to use JNDI in order to use JTA.
url="http://www.atomikos.com/">Atomikos Transactions</ulink> and <ulink Obviously the use of global transactions would limit any potetntial
url="http://jotm.objectweb.org/">JOTM</ulink> are other options. (Of reuse of application code, as JTA is normally only available in an
course you may need other application server capabilities such as JMS application server environment.</para>
and JCA.)</para>
<para>The most important point is that with the Spring Framework
<emphasis>you can choose when to scale your application up to a
full-blown application server</emphasis>. 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.</para>
</sidebar>
<para>Traditionally, J2EE developers have had two choices for transaction
management: <emphasis>global</emphasis> or <emphasis>local</emphasis>
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.)</para>
<formalpara>
<title>Global Transactions</title>
<para>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
<interfacename>UserTransaction</interfacename> normally needs to be
sourced from JNDI: meaning that we need to use <emphasis>both</emphasis>
JNDI <emphasis>and</emphasis> 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.</para>
<para>Previously, the preferred way to use global transactions was via <para>Previously, the preferred way to use global transactions was via
EJB <emphasis>CMT</emphasis> (<emphasis>Container Managed EJB <emphasis>CMT</emphasis> (<emphasis>Container Managed
...@@ -145,51 +115,103 @@ ...@@ -145,51 +115,103 @@
role="bold">declarative transaction management</emphasis> (as role="bold">declarative transaction management</emphasis> (as
distinguished from <emphasis role="bold">programmatic transaction distinguished from <emphasis role="bold">programmatic transaction
management</emphasis>). EJB CMT removes the need for transaction-related management</emphasis>). EJB CMT removes the need for transaction-related
JNDI lookups - although of course the use of EJB itself necessitates the 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 use of JNDI. It removes most but not all of the need to write Java code
write Java code to control transactions. The significant downside is to control transactions. The significant downside is that CMT is tied to
that CMT is tied to JTA and an application server environment. Also, it JTA and an application server environment. Also, it is only available if
is only available if one chooses to implement business logic in EJBs, or one chooses to implement business logic in EJBs, or at least behind a
at least behind a transactional EJB facade. The negatives around EJB in transactional EJB facade. The negatives of EJB in general are so great
general are so great that this is not an attractive proposition, that this is not an attractive proposition, especially in the face of
especially in the face of compelling alternatives for declarative compelling alternatives for declarative transaction management.</para>
transaction management.</para> </section>
</formalpara>
<section>
<formalpara> <title>Local transactions</title>
<title>Local Transactions</title>
<para>Local transactions are resource-specific, such as a transaction
<para>Local transactions may be easier to use, but have significant associated with a JDBC connection. Local transactions may be easier to
disadvantages: they cannot work across multiple transactional resources. use, but have significant disadvantages: they cannot work across
For example, code that manages transactions using a JDBC connection multiple transactional resources. For example, code that manages
cannot run within a global JTA transaction. Another downside is that transactions using a JDBC connection cannot run within a global JTA
local transactions tend to be invasive to the programming model.</para> transaction. Because the application server is not involved in
</formalpara> transaction management, it cannot help ensure correctness across
multiple resources. (It is worth noting that most applications use a
<para>Spring resolves these problems. It enables application developers to single transaction resource.) Another downside is that local
use a <emphasis>consistent</emphasis> programming model <emphasis>in any transactions are invasive to the programming model.</para>
environment</emphasis>. You write your code once, and it can benefit from </section>
different transaction management strategies in different environments. The
Spring Framework provides both declarative and programmatic transaction <section>
management. Declarative transaction management is preferred by most users, <title>Spring Framework's consistent programming model</title>
and is recommended in most cases.</para>
<para>Spring resolves the disadvantages of global and local
<para>With programmatic transaction management, developers work with the transactions. It enables application developers to use a
Spring Framework transaction abstraction, which can run over any <emphasis>consistent</emphasis> programming model <emphasis>in any
underlying transaction infrastructure. With the preferred declarative environment</emphasis>. You write your code once, and it can benefit
model, developers typically write little or no code related to transaction from different transaction management strategies in different
management, and hence don't depend on the Spring Framework's transaction environments. Spring Framework provides both declarative and
API (or indeed on any other transaction API).</para> programmatic transaction management. Most users prefer declarative
transaction management, which is recommended in most cases.</para>
<!--Do you need to specify that Spring allows you to work with *multiple* transactional resourcess (as global transactions do)?-->
<para>With programmatic transaction management, developers work with the
Spring Framework transaction abstraction, which can run over any
underlying transaction infrastructure. <!--Re preceding statement, does this mean that next section re transaction abstraction applies only to programmatic tx management?If so--><!--shouldn't the next section be subsection of *Programmatic transaction management* section? However, there is a sentence in the next--><!--section that reads *regardless of whether you opt for declarative or prog. tx man. defining correct PlatformTransactionManager impl. is--><!--absolutely essential.* This is followed by discussion of that impl. So I'm not sure what goes where.
TR: I think it's fine as is - the concepts apply to both programmatic and declarative transactions
-->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.</para>
<sidebar>
<title>Do you need an application server for transaction
management?</title>
<para>Spring Framework's transaction management support changes
traditional rules as to when a Java EE application requires an
application server.</para>
<para>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.</para>
<para>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 <ulink
url="http://www.atomikos.com/">Atomikos Transactions</ulink> and
<ulink url="http://jotm.objectweb.org/">JOTM</ulink> are other
options. Of course, you may need other application server capabilities
such as Java Message Service (JMS) and J2EE Connector Architecture
(JCA).</para>
<para>Spring Framework <emphasis>gives you the choice of when to scale
your application to a fully loaded application server</emphasis>. 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.</para>
<!--CLarify last sentence. Only what kind of configuration has to change?
TR: changed to say "some of the bean definitions in your configuration file"-->
</sidebar>
</section>
</section> </section>
<section id="transaction-strategies"> <section id="transaction-strategies">
<title>Key abstractions</title> <title>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--></title>
<para>The key to the Spring transaction abstraction is the notion of a <para>The key to the Spring transaction abstraction is the notion of a
<emphasis>transaction strategy</emphasis>. A transaction strategy is <emphasis>transaction strategy</emphasis>. A transaction strategy is
defined by the defined by the
<interfacename>org.springframework.transaction.PlatformTransactionManager</interfacename> <interfacename>org.springframework.transaction.PlatformTransactionManager</interfacename>
interface, shown below:</para> interface:</para>
<programlisting language="java">public interface PlatformTransactionManager { <programlisting language="java">public interface PlatformTransactionManager {
...@@ -201,22 +223,24 @@ ...@@ -201,22 +223,24 @@
void rollback(TransactionStatus status) throws TransactionException; void rollback(TransactionStatus status) throws TransactionException;
}</programlisting> }</programlisting>
<para>This is primarily an SPI interface, although it can be used <link <para>This is primarily a service provider interface (SPI), although it
linkend="transaction-programmatic-ptm">programmatically</link>. Note that can be used <link
in keeping with the Spring Framework's philosophy, linkend="transaction-programmatic-ptm">programmatically</link> from your
application code. <!--Write out SPI with SPI in parentheses. SPI stands for a number of different things.And does logic of sentence make sense?
TR: spelled SPI out and added a bit of clarification at the end-->Because
<interfacename>PlatformTransactionManager</interfacename> is an <interfacename>PlatformTransactionManager</interfacename> is an
<emphasis>interface</emphasis>, and can thus be easily mocked or stubbed <emphasis>interface</emphasis>, it can be easily mocked or stubbed as
as necessary. Nor is it tied to a lookup strategy such as JNDI: necessary. It is not tied to a lookup strategy such as JNDI.
<interfacename>PlatformTransactionManager</interfacename> implementations <interfacename>PlatformTransactionManager</interfacename> implementations
are defined like any other object (or bean) in the Spring Framework's IoC are defined like any other object (or bean) in the Spring Framework IoC
container. This benefit alone makes it a worthwhile abstraction even when container. This benefit alone makes Spring Framework transactions a
working with JTA: transactional code can be tested much more easily than worthwhile abstraction even when you work with JTA. Transactional code can
if it used JTA directly.</para> be tested much more easily than if it used JTA directly.</para>
<para>Again in keeping with Spring's philosophy, the <para>Again in keeping with Spring's philosophy, the
<exceptionname>TransactionException</exceptionname> that can be thrown by <exceptionname>TransactionException</exceptionname> that can be thrown by
any of the <interfacename>PlatformTransactionManager</interfacename> any of the <interfacename>PlatformTransactionManager</interfacename>
interface's methods is <emphasis>unchecked</emphasis> (that is it extends interface's methods is <emphasis>unchecked</emphasis> (that is, it extends
the <exceptionname>java.lang.RuntimeException</exceptionname> class). the <exceptionname>java.lang.RuntimeException</exceptionname> class).
Transaction infrastructure failures are almost invariably fatal. In rare Transaction infrastructure failures are almost invariably fatal. In rare
cases where application code can actually recover from a transaction cases where application code can actually recover from a transaction
...@@ -228,56 +252,57 @@ ...@@ -228,56 +252,57 @@
<interfacename>TransactionStatus</interfacename> object, depending on a <interfacename>TransactionStatus</interfacename> object, depending on a
<interfacename>TransactionDefinition</interfacename> parameter. The <interfacename>TransactionDefinition</interfacename> parameter. The
returned <interfacename>TransactionStatus</interfacename> might represent returned <interfacename>TransactionStatus</interfacename> might represent
a new or existing transaction (if there were a matching transaction in the a new transaction, or can represent an existing transaction if a matching
current call stack - with the implication being that (as with J2EE transaction exists in the current call stack. The implication in this
transaction contexts) a <interfacename>TransactionStatus</interfacename> latter case is that, as with Java EE transaction contexts, a
is associated with a <emphasis role="bold">thread</emphasis> of <interfacename>TransactionStatus</interfacename> is associated with a
execution).</para> <emphasis role="bold">thread</emphasis> of execution.<!--Previous sentences were difficult to follow because of all the parenthetical phrases.Revise if necessary.--></para>
<para>The <interfacename>TransactionDefinition</interfacename> interface <para>The <interfacename>TransactionDefinition</interfacename> interface
specifies:</para> specifies:</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para><emphasis role="bold">Isolation</emphasis>: the degree of <para><emphasis role="bold">Isolation</emphasis>: The degree to which
isolation this transaction has from the work of other transactions. this transaction is isolated from the work of other transactions. For
For example, can this transaction see uncommitted writes from other example, can this transaction see uncommitted writes from other
transactions?</para> transactions?</para>
</listitem> </listitem>
<listitem> <listitem>
<para><emphasis role="bold">Propagation</emphasis>: normally all code <para><emphasis role="bold">Propagation</emphasis>: Typically, all
executed within a transaction scope will run in that transaction. code executed within a transaction scope will run in that transaction.
However, there are several options specifying behavior if a However, you have options for specifying behavior in the event that a
transactional method is executed when a transaction context already transactional method is executed when a transaction context already
exists: for example, simply continue running in the existing exists. <!--Correct to say you have options? A human has to specify what the behavior will be, right?-->For
transaction (the common case); or suspending the existing transaction example, code can continue running in the existing transaction (the
and creating a new transaction. <emphasis>Spring offers all of the common case); or the existing transaction can be suspended and a new
transaction propagation options familiar from EJB CMT</emphasis>. transaction created. <emphasis>Spring offers all of the transaction
(Some details regarding the semantics of transaction propagation in propagation options familiar from EJB CMT</emphasis>. To read about
Spring can be found in the section entitled <xref the semantics of transaction propagation in Spring, see <xref
linkend="tx-propagation" />.</para> linkend="tx-propagation" />.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><emphasis role="bold">Timeout</emphasis>: how long this <para><emphasis role="bold">Timeout</emphasis>: How long this
transaction may run before timing out (and automatically being rolled transaction runs before timing out and being rolled back automatically
back by the underlying transaction infrastructure).</para> by the underlying transaction infrastructure.</para>
</listitem> </listitem>
<listitem> <listitem>
<para><emphasis role="bold">Read-only status</emphasis>: a read-only <para><emphasis role="bold">Read-only status</emphasis>: A read-only
transaction does not modify any data. Read-only transactions can be a transaction<!-- describes status but (TR: this was a bit confusing; it read better the original way)
useful optimization in some cases (such as when using we could say 'reads but does not modify' --> does not modify any data.
Hibernate).</para> Read-only transactions can be a useful optimization in some cases,
such as when you are using Hibernate.<!--I added that it describes status. OK? Elaborate on purpose?--></para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>These settings reflect standard transactional concepts. If <para>These settings reflect standard transactional concepts. If
necessary, please refer to a resource discussing transaction isolation necessary, refer to resources that discuss transaction isolation levels
levels and other core transaction concepts because understanding such core and other core transaction concepts. Understanding these concepts is
concepts is essential to using the Spring Framework or indeed any other essential to using the Spring Framework or any transaction management
transaction management solution.</para> solution.</para>
<para>The <interfacename>TransactionStatus</interfacename> interface <para>The <interfacename>TransactionStatus</interfacename> interface
provides a simple way for transactional code to control transaction provides a simple way for transactional code to control transaction
...@@ -303,21 +328,21 @@ ...@@ -303,21 +328,21 @@
<para>Regardless of whether you opt for declarative or programmatic <para>Regardless of whether you opt for declarative or programmatic
transaction management in Spring, defining the correct transaction management in Spring, defining the correct
<interfacename>PlatformTransactionManager</interfacename> implementation <interfacename>PlatformTransactionManager</interfacename> implementation
is absolutely essential. In good Spring fashion, this important definition is absolutely essential. You typically define this implementation through
typically is made using via Dependency Injection.</para> dependency injection.</para>
<!--Do you need a link to an explanation of DI?
TR: at this point in the text, I don't think you would need that
-->
<para><interfacename>PlatformTransactionManager</interfacename> <para><interfacename>PlatformTransactionManager</interfacename>
implementations normally require knowledge of the environment in which implementations normally require knowledge of the environment in which
they work: JDBC, JTA, Hibernate, etc The following examples from the they work: JDBC, JTA, Hibernate, and so on. The following examples show
<literal>dataAccessContext-local.xml</literal> file from Spring's how you can define a local
<emphasis role="bold">jPetStore</emphasis> sample application show how a <interfacename>PlatformTransactionManager</interfacename> implementation.
local <interfacename>PlatformTransactionManager</interfacename> (This example works with plain JDBC.)</para>
implementation can be defined. (This will work with plain JDBC.)</para>
<para>We must define a JDBC <interfacename>DataSource</interfacename>, and <para>You define a JDBC <interfacename>DataSource</interfacename></para>
then use the Spring <classname>DataSourceTransactionManager</classname>,
giving it a reference to the
<interfacename>DataSource</interfacename>.</para>
<programlisting language="xml">&lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt; <programlisting language="xml">&lt;bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"&gt;
&lt;property name="driverClassName" value="${jdbc.driverClassName}" /&gt; &lt;property name="driverClassName" value="${jdbc.driverClassName}" /&gt;
...@@ -326,23 +351,21 @@ ...@@ -326,23 +351,21 @@
&lt;property name="password" value="${jdbc.password}" /&gt; &lt;property name="password" value="${jdbc.password}" /&gt;
&lt;/bean&gt;</programlisting> &lt;/bean&gt;</programlisting>
<para>The related <para>The related <interfacename>The
<interfacename>PlatformTransactionManager</interfacename> bean definition PlatformTransactionManager</interfacename> bean definition will then have
will look like this:</para> a reference to the <interfacename>DataSource</interfacename> definition.
It will look like this:</para>
<programlisting language="xml">&lt;bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt; <programlisting language="xml">&lt;bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt;
&lt;property name="dataSource" ref="dataSource"/&gt; &lt;property name="dataSource" ref="dataSource"/&gt;
&lt;/bean&gt;</programlisting> &lt;/bean&gt;</programlisting>
<para>If we use JTA in a J2EE container, as in the <para>If you use JTA in a Java EE container then you use a container
<filename>'dataAccessContext-jta.xml'</filename> file from the same sample <interfacename>DataSource</interfacename>, obtained through JNDI, in
application, we use a container <interfacename>DataSource</interfacename>, conjunction with Spring's <classname>JtaTransactionManager</classname>.
obtained via JNDI, in conjunction with Spring's This is what the JTA and JNDI lookup version would look like:</para>
<classname>JtaTransactionManager</classname>. The
<classname>JtaTransactionManager</classname> doesn't need to know about <!--Indicate what the following example demonstrates.What is its purpose?-->
the <interfacename>DataSource</interfacename>, or any other specific
resources, as it will use the container's global transaction management
infrastructure.</para>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt; <programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans" &lt;beans xmlns="http://www.springframework.org/schema/beans"
...@@ -362,29 +385,41 @@ ...@@ -362,29 +385,41 @@
&lt;/beans&gt;</programlisting> &lt;/beans&gt;</programlisting>
<para>The <classname>JtaTransactionManager</classname> does not need to
know about the <interfacename>DataSource</interfacename>, or any other
specific resources, because it uses the container's global transaction
management infrastructure.</para>
<note> <note>
<para>The above definition of the <literal>'dataSource'</literal> bean <para>The above definition of the <literal>dataSource</literal> bean
uses the <literal>&lt;jndi-lookup/&gt;</literal> tag from the uses the <literal>&lt;jndi-lookup/&gt;</literal> tag from the
<literal>'jee'</literal> namespace. For more information on schema-based <literal>jee</literal> namespace. For more information on schema-based
configuration, see <xref linkend="xsd-config" />, and for more configuration, see <xref linkend="xsd-config" />, and for more
information on the <literal>&lt;jee/&gt;</literal> tags see the section information on the <literal>&lt;jee/&gt;</literal> tags see the section
entitled <xref linkend="xsd-config-body-schemas-jee" />.</para> entitled <xref linkend="xsd-config-body-schemas-jee" />.</para>
</note> </note>
<para>We can also use Hibernate local transactions easily, as shown in the <para>You can also use Hibernate local transactions easily, as shown in
following examples from the Spring Framework's <emphasis the following examples. In this case, you need to define a Hibernate
role="bold">PetClinic</emphasis> sample application. In this case, we need <classname>LocalSessionFactoryBean</classname>, which your application
to define a Hibernate <classname>LocalSessionFactoryBean</classname>, code will use to obtain Hibernate <interfacename>Session</interfacename>
which application code will use to obtain Hibernate instances.</para>
<interfacename>Session</interfacename> instances.</para>
<para>The <interfacename>DataSource</interfacename> bean definition will <para>The <interfacename>DataSource</interfacename> bean definition will
be similar to the one shown previously (and thus is not shown). If the be similar to the local JDBC example shown previously and thus not shown
<interfacename>DataSource</interfacename> is managed by the JEE container in the following example.</para>
it should be non-transactional as the Spring Framework, rather than the
JEE container, will manage transactions.</para>
<para>The <literal>'txManager'</literal> bean in this case is of the <!-- TR: added the following clarification rather than embed it in the text above-->
<note>
<para>If the <interfacename>DataSource</interfacename>, 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.</para>
</note>
<para>The <literal>txManager</literal> bean in this case is of the
<classname>HibernateTransactionManager</classname> type. In the same way <classname>HibernateTransactionManager</classname> type. In the same way
as the <classname>DataSourceTransactionManager</classname> needs a as the <classname>DataSourceTransactionManager</classname> needs a
reference to the <interfacename>DataSource</interfacename>, the reference to the <interfacename>DataSource</interfacename>, the
...@@ -409,105 +444,114 @@ ...@@ -409,105 +444,114 @@
&lt;property name="sessionFactory" ref="sessionFactory" /&gt; &lt;property name="sessionFactory" ref="sessionFactory" /&gt;
&lt;/bean&gt;</programlisting> &lt;/bean&gt;</programlisting>
<para>With Hibernate and JTA transactions, we can simply use the <para>If you are using Hibernate and Java EE container managed JTA
<classname>JtaTransactionManager</classname> as with JDBC or any other transactions, then you should simply use the same
resource strategy.</para> <classname>JtaTransactionManager</classname> as in the previous JTA
example for JDBC.<!--Use it to do what? Below, this *what* is identical to JTA config
TR: I clarified this a bit
--></para>
<programlisting language="xml">&lt;bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/&gt;</programlisting> <programlisting language="xml">&lt;bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/&gt;</programlisting>
<para>Note that this is identical to JTA configuration for any resource, <note>
as these are global transactions, which can enlist any transactional <para>If you use JTA then your transacton manager definition will look
resource.</para> 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.</para>
</note>
<remark><para>In all these cases, application code will not need to change <para>In all these cases, application code does not need to change. You
at all. We can change how transactions are managed merely by changing can change how transactions are managed merely by changing configuration,
configuration, even if that change means moving from local to global even if that change means moving from local to global transactions or vice
transactions or vice versa.</para></remark> versa.</para>
</section> </section>
<section id="tx-resource-synchronization"> <section id="tx-resource-synchronization">
<title>Resource synchronization with transactions</title> <title>Synchronizing resources with transactions</title>
<para>It should now be clear how different transaction managers are <para>It should now be clear how you create different transaction
created, and how they are linked to related resources which need to be managers, and how they are linked to related resources that need to be
synchronized to transactions (for example synchronized to transactions (for example
<classname>DataSourceTransactionManager</classname> to a JDBC <classname>DataSourceTransactionManager</classname> to a JDBC
<interfacename>DataSource</interfacename>, <interfacename>DataSource</interfacename>,
<classname>HibernateTransactionManager</classname> to a Hibernate <classname>HibernateTransactionManager</classname> to a Hibernate
<interfacename>SessionFactory</interfacename>, and so forth). There <interfacename>SessionFactory</interfacename>, and so forth). This section
remains the question however of how the application code, directly or describes how the application code, directly or indirectly using a
indirectly using a persistence API (such as JDBC, Hibernate, and JDO), persistence API such as JDBC, Hibernate, or JDO, ensures that these
ensures that these resources are obtained and handled properly in terms of resources are created, reused, and cleaned up properly. The section also
proper creation/reuse/cleanup and trigger (optionally) transaction discusses how transaction synchronization is triggered (optionally)
synchronization via the relevant through the relevant
<interfacename>PlatformTransactionManager</interfacename>.</para> <interfacename>PlatformTransactionManager</interfacename>.<!--I broke into two sentences. Last part of sentence unclear,revise to say what triggers tx synch. Revise sentences if necessray.--></para>
<section id="tx-resource-synchronization-high"> <section id="tx-resource-synchronization-high">
<title>High-level approach</title> <title>High-level synchronization approach</title>
<para>The preferred approach is to use Spring's highest level <para>The preferred approach is to use Spring's highest level template
persistence integration APIs. These do not replace the native APIs, but based persistence integration APIs or to use native ORM APIs with
internally handle resource creation/reuse, cleanup, optional transaction transaction aware factory beans or proxies for managing the native
synchronization of the resources and exception mapping so that user data resource factories. These transaction aware solutions internally handle
access code doesn't have to worry about these concerns at all, but can resource creation and reuse, cleanup, optional transaction
concentrate purely on non-boilerplate persistence logic. Generally, the synchronization of the resources, and exception mapping. Thus user data
same <emphasis>template</emphasis> approach is used for all persistence access code does not have to address these tasks, but can be focused
APIs, with examples including the <classname>JdbcTemplate</classname>, purely on non-boilerplate persistence logic. Generally, you use the
<classname>HibernateTemplate</classname>, and native ORM API or a <emphasis>template</emphasis> approach for JDBC
<classname>JdoTemplate</classname> classes (detailed in subsequent access using the <classname>JdbcTemplate</classname>. All of these
chapters of this reference documentation.</para> solutions are detailed in subsequent chapters of this reference
documentation.<!--If this approach is preferred, why not give examples here as you do with less desirable approaches? At least provide--><!--x-refs? Also is it correct to refer to APIs, then give classes as examples? Should this be reworded?
TR: I re-wrote this to match the current preferred approaches--></para>
</section> </section>
<section id="tx-resource-synchronization-low"> <section id="tx-resource-synchronization-low">
<title>Low-level approach</title> <title>Low-level synchronization approach</title>
<para>At a lower level exist classes such as <para>Classes such as <classname>DataSourceUtils</classname> (for JDBC),
<classname>DataSourceUtils</classname> (for JDBC), <classname>EntityManagerFactoryUtils</classname> (for JPA),
<classname>SessionFactoryUtils</classname> (for Hibernate), <classname>SessionFactoryUtils</classname> (for Hibernate),
<classname>PersistenceManagerFactoryUtils</classname> (for JDO), and so <classname>PersistenceManagerFactoryUtils</classname> (for JDO), and so
on. When it is preferable for application code to deal directly with the on exist at a lower level. When you want the application code to deal
resource types of the native persistence APIs, these classes ensure that directly with the resource types of the native persistence APIs, you use
proper Spring Framework-managed instances are obtained, transactions are these classes to ensure that proper Spring Framework-managed instances
(optionally) synchronized, and exceptions which happen in the process are obtained, transactions are (optionally) synchronized, and exceptions
are properly mapped to a consistent API.</para> that occur in the process are properly mapped to a consistent
API.</para>
<para>For example, in the case of JDBC, instead of the traditional JDBC <para>For example, in the case of JDBC, instead of the traditional JDBC
approach of calling the <literal>getConnection()</literal> method on the approach of calling the <literal>getConnection()</literal> method on the
<interfacename>DataSource</interfacename>, you would instead use <interfacename>DataSource</interfacename>, you instead use Spring's
Spring's
<classname>org.springframework.jdbc.datasource.DataSourceUtils</classname> <classname>org.springframework.jdbc.datasource.DataSourceUtils</classname>
class as follows:</para> class as follows:</para>
<programlisting language="java">Connection conn = DataSourceUtils.getConnection(dataSource);</programlisting> <programlisting language="java">Connection conn = DataSourceUtils.getConnection(dataSource);</programlisting>
<para>If an existing transaction exists, and already has a connection <para>If an existing transaction already has a connection synchronized
synchronized (linked) to it, that instance will be returned. Otherwise, (linked) to it, that instance is returned. Otherwise, the method call
the method call will trigger the creation of a new connection, which triggers the creation of a new connection, which is (optionally)
will be (optionally) synchronized to any existing transaction, and made synchronized to any existing transaction, and made available for
available for subsequent reuse in that same transaction. As mentioned, subsequent reuse in that same transaction. As mentioned, any
this has the added advantage that any <exceptionname>SQLException</exceptionname> is wrapped in a Spring
<exceptionname>SQLException</exceptionname> will be wrapped in a Spring
Framework Framework
<exceptionname>CannotGetJdbcConnectionException</exceptionname> - one of <exceptionname>CannotGetJdbcConnectionException</exceptionname>, one of
the Spring Framework's hierarchy of unchecked DataAccessExceptions. This 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
<exceptionname>SQLException</exceptionname>, and ensures portability <exceptionname>SQLException</exceptionname>, and ensures portability
across databases: even across different persistence technologies.</para> across databases, even across different persistence technologies.</para>
<para>It should be noted that this will also work fine without Spring <para>This approach also works without Spring transaction management
transaction management (transaction synchronization is optional), so you (transaction synchronization is optional), so you can use it whether or
can use it whether or not you are using Spring for transaction not you are using Spring for transaction management.</para>
management.</para>
<para>Of course, once you've used Spring's JDBC support or Hibernate <para>Of course, once you have used Spring's JDBC support, JPA support
support, you will generally prefer not to use or Hibernate support, you will generally prefer not to use
<classname>DataSourceUtils</classname> or the other helper classes, <classname>DataSourceUtils</classname> or the other helper classes,
because you'll be much happier working via the Spring abstraction than because you will be much happier working through the Spring abstraction
directly with the relevant APIs. For example, if you use the Spring than directly with the relevant APIs. For example, if you use the Spring
<classname>JdbcTemplate</classname> or <literal>jdbc.object</literal> <classname>JdbcTemplate</classname> or <literal>jdbc.object</literal>
package to simplify your use of JDBC, correct connection retrieval 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.</para> code.</para>
<!--I don't understand this. Why tell them to use DataSourceUtils and then say you will prefer Spring abstraction? Why not give example of using Spring abstraction?-->
</section> </section>
<section id="tx-resource-synchronization-tadsp"> <section id="tx-resource-synchronization-tadsp">
...@@ -519,74 +563,73 @@ ...@@ -519,74 +563,73 @@
wraps the target <interfacename>DataSource</interfacename> to add wraps the target <interfacename>DataSource</interfacename> to add
awareness of Spring-managed transactions. In this respect, it is similar awareness of Spring-managed transactions. In this respect, it is similar
to a transactional JNDI <interfacename>DataSource</interfacename> as to a transactional JNDI <interfacename>DataSource</interfacename> as
provided by a J2EE server.</para> provided by a Java EE server.<!--What is the purpose of TransactionAwareDataSourceProxy, do you use it instead of 4.2 or 4.1 approaches or in addition to?--></para>
<para>It should almost never be necessary or desirable to use this <para>It should almost never be necessary or desirable to use this
class, except when existing code exists which must be called and passed class, except when existing code must be called and passed a standard
a standard JDBC <interfacename>DataSource</interfacename> interface JDBC <interfacename>DataSource</interfacename> interface implementation.
implementation. In that case, it's possible to still have this code be In that case, it is possible that this code is usable, but participating
usable, but participating in Spring managed transactions. It is in Spring managed transactions. It is preferable to write your new code
preferable to write your new code using the higher level abstractions by using the higher level abstractions mentioned above.</para>
mentioned above.</para>
</section> </section>
</section> </section>
<section id="transaction-declarative"> <section id="transaction-declarative">
<title>Declarative transaction management</title> <title>Declarative transaction management</title>
<remark>Most users of the Spring Framework choose declarative transaction <note>
management. It is the option with the least impact on application code, <para>Most Spring Framework users choose declarative transaction
and hence is most consistent with the ideals of a management. This option has the least impact on application code, and
<emphasis>non-invasive</emphasis> lightweight container.</remark> hence is most consistent with the ideals of a
<emphasis>non-invasive</emphasis> lightweight container.</para>
<para>The Spring Framework's declarative transaction management is made </note>
possible with Spring AOP, although, as the transactional aspects code
comes with the Spring Framework distribution and may be used in a <para>Spring Framework's declarative transaction management is made
boilerplate fashion, AOP concepts do not generally have to be understood possible with Spring aspect-oriented programming (AOP), although, as the
to make effective use of this code.</para> transactional aspects code comes with the Spring Framework distribution
and may be used in a boilerplate fashion, AOP concepts do not generally
<para>It may be helpful to begin by considering EJB CMT and explaining the have to be understood to make effective use of this code.</para>
similarities and differences with the Spring Framework's declarative
transaction management. The basic approach is similar: it is possible to <para>Spring Framework's declarative transaction management is similar to
specify transaction behavior (or lack of it) down to individual method EJB CMT in that you can specify transaction behavior (or lack of it) down
level. It is possible to make a <methodname>setRollbackOnly()</methodname> to individual method level. It is possible to make a
call within a transaction context if necessary. The differences <methodname>setRollbackOnly()</methodname> call within a transaction
are:</para> context if necessary. The differences between the two types of transaction
management are:</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para>Unlike EJB CMT, which is tied to JTA, the Spring Framework's <para>Unlike EJB CMT, which is tied to JTA, Spring Framework's
declarative transaction management works in any environment. It can declarative transaction management works in any environment. It can
work with JDBC, JDO, Hibernate or other transactions under the covers, work with JTA transactions or local transactions using JDBC, JPA,
with configuration changes only.</para> Hibernate or JDO by simple adjusting the configuration files.<!--Indicate what kind of config changes? Changes to what TR: rewrote this to hoefully make it more clear--></para>
</listitem> </listitem>
<listitem> <listitem>
<para>The Spring Framework enables declarative transaction management <para>You can apply Spring Framework declarative transaction
to be applied to any class, not merely special classes such as management to any class, not merely special classes such as
EJBs.</para> EJBs.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>The Spring Framework offers declarative <link <para>Spring Framework offers declarative <link
linkend="transaction-declarative-rolling-back"><emphasis>rollback linkend="transaction-declarative-rolling-back"><emphasis>rollback
rules</emphasis>:</link> this is a feature with no EJB equivalent. rules</emphasis>, </link>a feature with no EJB equivalent. Both
Both programmatic and declarative support for rollback rules is programmatic and declarative support for rollback rules is
provided.</para> provided.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>The Spring Framework gives you an opportunity to customize <para>Spring Framework enables you to customize transactional
transactional behavior, using AOP. For example, if you want to insert behavior, by using AOP. For example, you can insert custom behavior in
custom behavior in the case of transaction rollback, you can. You can the case of transaction rollback. You can also add arbitrary advice,
also add arbitrary advice, along with the transactional advice. With along with the transactional advice. With EJB CMT, cannot influence
EJB CMT, you have no way to influence the container's transaction the container's transaction management except with
management other than
<methodname>setRollbackOnly()</methodname>.</para> <methodname>setRollbackOnly()</methodname>.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>The Spring Framework does not support propagation of transaction <para>Spring Framework does not support propagation of transaction
contexts across remote calls, as do high-end application servers. If contexts across remote calls, as do high-end application servers. If
you need this feature, we recommend that you use EJB. However, you need this feature, we recommend that you use EJB. However,
consider carefully before using such a feature, because normally, one consider carefully before using such a feature, because normally, one
...@@ -603,48 +646,46 @@ ...@@ -603,48 +646,46 @@
main difference is that there is no longer any need to configure main difference is that there is no longer any need to configure
<classname>TransactionProxyFactoryBean</classname> beans.</para> <classname>TransactionProxyFactoryBean</classname> beans.</para>
<para>The old, pre-Spring 2.0 configuration style is still 100% valid <para>The pre-Spring 2.0 configuration style is still 100% valid
configuration; think of the new <literal>&lt;tx:tags/&gt;</literal> as configuration; think of the new <literal>&lt;tx:tags/&gt;</literal> as
simply defining <classname>TransactionProxyFactoryBean</classname> beans simply defining <classname>TransactionProxyFactoryBean</classname> beans
on your behalf.</para> on your behalf.</para>
</sidebar> </sidebar>
<para>The concept of rollback rules is important: they enable us to <para>The concept of rollback rules is important: they enable you to
specify which exceptions (and throwables) should cause automatic roll specify which exceptions (and throwables) <!--If no difference between exceptions and throwables, delete throwables.-->should
back. We specify this declaratively, in configuration, not in Java code. cause automatic rollback. You specify this declaratively, in
So, while we can still call <methodname>setRollbackOnly()</methodname>on configuration, not in Java code. So, although you can still call
the <interfacename>TransactionStatus</interfacename> object to roll the <methodname>setRollbackOnly()</methodname>on the
current transaction back programmatically, most often we can specify a <interfacename>TransactionStatus</interfacename> object to roll back the
rule that <exceptionname>MyApplicationException</exceptionname> must current transaction back, most often you can specify a rule that
always result in rollback. This has the significant advantage that <exceptionname>MyApplicationException</exceptionname> must always result
business objects don't need to depend on the transaction infrastructure. in rollback. The significant advantage to this option is that business
For example, they typically don't need to import any Spring APIs, objects do not depend on the transaction infrastructure. For example, they
transaction or other.</para> typically do not need to import Spring transaction APIs or other Spring
APIs.</para>
<para>While the EJB default behavior is for the EJB container to
automatically roll back the transaction on a <emphasis>system <para>Although EJB container default behavior automatically rolls back the
exception</emphasis> (usually a runtime exception), EJB CMT does not roll transaction on a <emphasis>system exception</emphasis> (usually a runtime
back the transaction automatically on an <emphasis>application exception), EJB CMT does not roll back the transaction automatically on an
exception</emphasis> (that is, a checked exception other than <emphasis>application exception</emphasis> (that is, a checked exception
<exceptionname>java.rmi.RemoteException</exceptionname>). While the Spring other than <exceptionname>java.rmi.RemoteException</exceptionname>). While
default behavior for declarative transaction management follows EJB the Spring default behavior for declarative transaction management follows
convention (roll back is automatic only on unchecked exceptions), it is EJB convention (roll back is automatic only on unchecked exceptions), it
often useful to customize this.</para> is often useful to customize this behavior.</para>
<!--customize this so that what happens?-->
<section id="tx-decl-explained"> <section id="tx-decl-explained">
<title>Understanding the Spring Framework's declarative transaction <title>Understanding Spring Framework's declarative transaction
implementation</title> implementation</title>
<para>The aim of this section is to dispel the mystique that is <para>It is not sufficient to tell you simply to annotate your classes
sometimes associated with the use of declarative transactions. It is all with the <interfacename>@Transactional</interfacename> annotation, add
very well for this reference documentation simply to tell you to the line (<literal>&lt;tx:annotation-driven/&gt;</literal>) to your
annotate your classes with the
<interfacename>@Transactional</interfacename> annotation, add the line
(<literal>'&lt;tx:annotation-driven/&gt;'</literal>) to your
configuration, and then expect you to understand how it all works. This configuration, and then expect you to understand how it all works. This
section will explain the inner workings of the Spring Framework's section explains the inner workings of Spring Framework's declarative
declarative transaction infrastructure to help you navigate your way transaction infrastructure in the event of transaction-related
back upstream to calmer waters in the event of transaction-related
issues.</para> issues.</para>
<para>The most important concepts to grasp with regard to the Spring <para>The most important concepts to grasp with regard to the Spring
...@@ -659,14 +700,14 @@ ...@@ -659,14 +700,14 @@
invocations</emphasis>.</para> invocations</emphasis>.</para>
<note> <note>
<para>Although knowledge of Spring AOP is not required to use Spring's <para>Spring AOP is covered in <xref linkend="aop" />.</para>
declarative transaction support, it can help. Spring AOP is thoroughly
covered in the chapter entitled <xref linkend="aop" />.</para>
</note> </note>
<para>Conceptually, calling a method on a transactional proxy looks like <para>Conceptually, calling a method on a transactional proxy looks like
this...</para> this...</para>
<!--I don't see this image in src file or in pdf. Maybe it was added to src after pdf was created?-->
<para><mediaobject> <para><mediaobject>
<imageobject role="fo"> <imageobject role="fo">
<imagedata align="center" fileref="images/tx.png" format="PNG" /> <imagedata align="center" fileref="images/tx.png" format="PNG" />
...@@ -679,13 +720,19 @@ ...@@ -679,13 +720,19 @@
</section> </section>
<section id="transaction-declarative-first-example"> <section id="transaction-declarative-first-example">
<title>A first example</title> <title>Example of declarative transaction implementation</title>
<para>Consider the following interface, and its attendant <para>Consider the following interface, and its attendant
implementation. (The intent is to convey the concepts, and using the implementation. This example uses the rote <classname>Foo</classname>
rote <classname>Foo</classname> and <classname>Bar</classname> tropes and <classname>Bar</classname> tropes so that you can concentrate on the
means that you can concentrate on the transaction usage and not have to transaction usage without focusing on the domain model. For the purposes
worry about the domain model.)</para> of this example, the fact that the
<classname>DefaultFooService</classname> class throws
<exceptionname>UnsupportedOperationException</exceptionname> 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
<exceptionname>UnsupportedOperationException</exceptionname>
instance.</para>
<programlisting language="java"><lineannotation>// the service interface that we want to make transactional</lineannotation> <programlisting language="java"><lineannotation>// the service interface that we want to make transactional</lineannotation>
...@@ -727,24 +774,14 @@ public class DefaultFooService implements FooService { ...@@ -727,24 +774,14 @@ public class DefaultFooService implements FooService {
}</programlisting> }</programlisting>
<para><emphasis>(For the purposes of this example, the fact that the <para>Assume that the first two methods of the
<classname>DefaultFooService</classname> class throws <interfacename>FooService</interfacename> interface<literal>,
<exceptionname>UnsupportedOperationException</exceptionname> instances getFoo(String)</literal> and <literal>getFoo(String, String),
in the body of each implemented method is good; it will allow us to see </literal>must execute in the context of a transaction with read-only
transactions being created and then rolled back in response to the semantics, and that the other methods<literal>,insertFoo(Foo)</literal>
<exceptionname>UnsupportedOperationException</exceptionname> instance and <literal>updateFoo(Foo),</literal> must execute in the context of a
being thrown.)</emphasis></para> transaction with read-write semantics. The following configuration is
explained in detail in the next few paragraphs.</para>
<para>Let's assume that the first two methods of the
<interfacename>FooService</interfacename> interface
(<literal>getFoo(String)</literal> and <literal>getFoo(String,
String)</literal>) have to execute in the context of a transaction with
read-only semantics, and that the other methods
(<literal>insertFoo(Foo)</literal> and
<literal>updateFoo(Foo)</literal>) 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.</para>
<programlisting language="xml"><lineannotation>&lt;!-- from the file <literal>'context.xml'</literal> --&gt;</lineannotation> <programlisting language="xml"><lineannotation>&lt;!-- from the file <literal>'context.xml'</literal> --&gt;</lineannotation>
&lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;?xml version="1.0" encoding="UTF-8"?&gt;
...@@ -798,49 +835,48 @@ public class DefaultFooService implements FooService { ...@@ -798,49 +835,48 @@ public class DefaultFooService implements FooService {
&lt;/beans&gt;</programlisting> &lt;/beans&gt;</programlisting>
<para>Let's pick apart the above configuration. We have a service object <para>Examine the preceding configuration. You want to make a service
(the <literal>'fooService'</literal> bean) that we want to make object, the <literal>fooService</literal> bean, transactional. The
transactional. The transaction semantics that we want to apply are transaction semantics to apply are encapsulated in the
encapsulated in the <literal>&lt;tx:advice/&gt;</literal> definition. <literal>&lt;tx:advice/&gt;</literal> definition. The
The <literal>&lt;tx:advice/&gt;</literal> definition reads as <literal>&lt;tx:advice/&gt;</literal> definition reads as
<quote><emphasis>... all methods on starting with <quote><emphasis>... all methods on starting with
<literal>'get'</literal> are to execute in the context of a read-only <literal>'get'</literal> are to execute in the context of a read-only
transaction, and all other methods are to execute with the default transaction, and all other methods are to execute with the default
transaction semantics</emphasis></quote>. The transaction semantics</emphasis></quote>. The
<literal>'transaction-manager'</literal> attribute of the <literal>transaction-manager</literal> attribute of the
<literal>&lt;tx:advice/&gt;</literal> tag is set to the name of the <literal>&lt;tx:advice/&gt;</literal> tag is set to the name of the
<interfacename>PlatformTransactionManager</interfacename> bean that is <interfacename>PlatformTransactionManager</interfacename> bean that is
going to actually <emphasis>drive</emphasis> the transactions (in this going to <emphasis>drive</emphasis> the transactions, in this case, the
case the <literal>'txManager'</literal> bean).</para> <literal>txManager</literal> bean.</para>
<tip> <tip>
<para>You can actually omit the <para>You can omit the <literal>transaction-manager</literal>
<literal>'transaction-manager'</literal> attribute in the attribute in the transactional advice
transactional advice (<literal>&lt;tx:advice/&gt;</literal>) if the (<literal>&lt;tx:advice/&gt;</literal>) if the bean name of the
bean name of the
<interfacename>PlatformTransactionManager</interfacename> that you <interfacename>PlatformTransactionManager</interfacename> that you
want to wire in has the name <literal>'transactionManager'</literal>. want to wire in has the name <literal>transactionManager</literal>. If
If the <interfacename>PlatformTransactionManager</interfacename> bean the <interfacename>PlatformTransactionManager</interfacename> bean
that you want to wire in has any other name, then you have to be that you want to wire in has any other name, then you must use the
explicit and use the <literal>'transaction-manager'</literal> <literal>transaction-manager</literal> attribute explicitly, as in the
attribute as in the example above.</para> preceding example.</para>
</tip> </tip>
<para>The <literal>&lt;aop:config/&gt;</literal> definition ensures that <para>The <literal>&lt;aop:config/&gt;</literal> definition ensures that
the transactional advice defined by the <literal>'txAdvice'</literal> the transactional advice defined by the <literal>txAdvice</literal> bean
bean actually executes at the appropriate points in the program. First executes at the appropriate points in the program. First you define a
we define a pointcut that matches the execution of any operation defined pointcut that matches the execution of any operation defined in the
in the <interfacename>FooService</interfacename> interface <interfacename>FooService</interfacename> interface
(<literal>'fooServiceOperation'</literal>). Then we associate the (<literal>fooServiceOperation</literal>). Then you associate the
pointcut with the <literal>'txAdvice'</literal> using an advisor. The pointcut with the <literal>txAdvice</literal> using an advisor. The
result indicates that at the execution of a result indicates that at the execution of a
<literal>'fooServiceOperation'</literal>, the advice defined by <literal>fooServiceOperation</literal>, the advice defined by
<literal>'txAdvice'</literal> will be run.</para> <literal>txAdvice</literal> will be run.</para>
<para>The expression defined within the <para>The expression defined within the
<literal>&lt;aop:pointcut/&gt;</literal> element is an AspectJ pointcut <literal>&lt;aop:pointcut/&gt;</literal> element is an AspectJ pointcut
expression; see the chapter entitled <xref linkend="aop" /> for more expression; see <xref linkend="aop" /> for more details on pointcut
details on pointcut expressions in Spring 2.0.</para> expressions in Spring 2.0.</para>
<para>A common requirement is to make an entire service layer <para>A common requirement is to make an entire service layer
transactional. The best way to do this is simply to change the pointcut transactional. The best way to do this is simply to change the pointcut
...@@ -850,26 +886,28 @@ public class DefaultFooService implements FooService { ...@@ -850,26 +886,28 @@ public class DefaultFooService implements FooService {
<programlisting language="xml">&lt;aop:config&gt; <programlisting language="xml">&lt;aop:config&gt;
&lt;aop:pointcut id="fooServiceMethods" expression="execution(* x.y.service.*.*(..))"/&gt; &lt;aop:pointcut id="fooServiceMethods" expression="execution(* x.y.service.*.*(..))"/&gt;
&lt;aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceMethods"/&gt; &lt;aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceMethods"/&gt;
&lt;/aop:config&gt;</programlisting> &lt;/aop:config&gt;</programlisting>
<para><emphasis>(This example assumes that all your service interfaces <para><note>
are defined in the <literal>'x.y.service'</literal> package; see the <para><emphasis>In this example it is assumed that all your service
chapter entitled <xref linkend="aop" /> for more interfaces are defined in the <literal>x.y.service</literal>
details.)</emphasis></para> package; see <xref linkend="aop" /> for more
details.</emphasis></para>
</note></para>
<para>Now that we've analyzed the configuration, you may be asking <para>Now that we've analyzed the configuration, you may be asking
yourself, <quote><emphasis>Okay... but what does all this configuration yourself, <quote><emphasis>Okay... but what does all this configuration
actually do?</emphasis></quote>.</para> actually do?</emphasis></quote>.</para>
<para>The above configuration is going to effect the creation of a <para>The above configuration will be used to create a transactional
transactional proxy around the object that is created from the proxy around the object that is created from the
<literal>'fooService'</literal> bean definition. The proxy will be <literal>fooService</literal> bean definition. <!--Clarify what you mean by around the object; do you mean associated with the object? Revise to clarify. Around is vague.-->The
configured with the transactional advice, so that when an appropriate proxy will be configured with the transactional advice, so that when an
method is invoked <emphasis>on the proxy</emphasis>, a transaction appropriate method is invoked <emphasis>on the proxy</emphasis>, a
<emphasis>may</emphasis> be started, suspended, be marked as read-only, transaction is started, suspended, marked as read-only, and so on,
etc., depending on the transaction configuration associated with that depending on the transaction configuration associated with that method.
method. Consider the following program that test drives the above Consider the following program that test drives the above
configuration.</para> configuration:</para>
<programlisting language="java">public final class Boot { <programlisting language="java">public final class Boot {
...@@ -880,12 +918,10 @@ public class DefaultFooService implements FooService { ...@@ -880,12 +918,10 @@ public class DefaultFooService implements FooService {
} }
}</programlisting> }</programlisting>
<para>The output from running the above program will look something like <para>The output from running the preceding program will resemble the
this. <emphasis>(Please note that the Log4J output and the stacktrace following. (The Log4J output and the stack trace from the
from the <exceptionname>UnsupportedOperationException</exceptionname> UnsupportedOperationException thrown by the insertFoo(..) method of the
thrown by the <methodname>insertFoo(..)</methodname> method of the DefaultFooService class have been truncated for clarity.)</para>
<classname>DefaultFooService</classname> class have been truncated in
the interest of clarity.)</emphasis></para>
<programlisting language="xml"> <lineannotation><emphasis role="bold">&lt;!-- the Spring container is starting up... --&gt;</emphasis></lineannotation> <programlisting language="xml"> <lineannotation><emphasis role="bold">&lt;!-- the Spring container is starting up... --&gt;</emphasis></lineannotation>
[AspectJInvocationContextExposingAdvisorAutoProxyCreator] - Creating implicit proxy [AspectJInvocationContextExposingAdvisorAutoProxyCreator] - Creating implicit proxy
...@@ -914,44 +950,47 @@ public class DefaultFooService implements FooService { ...@@ -914,44 +950,47 @@ public class DefaultFooService implements FooService {
[DataSourceUtils] - Returning JDBC Connection to DataSource [DataSourceUtils] - Returning JDBC Connection to DataSource
Exception in thread "main" java.lang.UnsupportedOperationException 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)
<lineannotation><emphasis role="bold">&lt;!-- AOP infrastructure stack trace elements removed for clarity --&gt;</emphasis></lineannotation> <lineannotation><emphasis role="bold">&lt;!-- AOP infrastructure stack trace elements removed for clarity --&gt;</emphasis></lineannotation>
at $Proxy0.insertFoo(Unknown Source) at $Proxy0.insertFoo(Unknown Source)
at Boot.main(Boot.java:11)</programlisting> at Boot.main(Boot.java:11)</programlisting>
</section> </section>
<section id="transaction-declarative-rolling-back"> <section id="transaction-declarative-rolling-back">
<title>Rolling back</title> <title>Rolling back a declarative transaction</title>
<para>The previous section outlined the basics of how to specify the <para>The previous section outlined the basics of how to specify
transactional settings for the classes, typically service layer classes, transactional settings for classes, typically service layer classes,
in your application in a declarative fashion. This section describes how declaratively in your application. This section describes how you can
you can control the rollback of transactions in a simple declarative control the rollback of transactions in a simple declarative
fashion.</para> fashion.</para>
<para>The recommended way to indicate to the Spring Framework's <para>The recommended way to indicate to Spring Framework's transaction
transaction infrastructure that a transaction's work is to be rolled infrastructure that a transaction's work is to be rolled back is to
back is to throw an <exceptionname>Exception</exceptionname> from code throw an <exceptionname>Exception</exceptionname> from code that is
that is currently executing in the context of a transaction. The Spring currently executing in the context of a transaction. Spring Framework's
Framework's transaction infrastructure code will catch any unhandled transaction infrastructure code, in its default configuration, will
<exceptionname>Exception</exceptionname> as it bubbles up the call catch any unhandled <exceptionname>Exception</exceptionname> as it
stack, and will mark the transaction for rollback.</para> bubbles up the call stack, and mark the transaction for rollback.<!--I changed to *can be configured* because next sentence says it does not do this by default in all cases.
TR: I changed it to *in its default configuration*--></para>
<para>Note however that the Spring Framework's transaction
infrastructure code will, by default, <emphasis>only</emphasis> mark a <para>However, Spring Framework's transaction infrastructure code, by
transaction for rollback in the case of runtime, unchecked exceptions; default, <emphasis>only</emphasis> mark a transaction for rollback in
that is, when the thrown exception is an instance or subclass of the case of runtime, unchecked exceptions; that is, when the thrown
exception is an instance or subclass of
<exceptionname>RuntimeException</exceptionname>. <exceptionname>RuntimeException</exceptionname>.
(<literal>Errors</literal> will also - by default - result in a (<exceptionname>Error</exceptionname>s will also - by default - result
rollback.) Checked exceptions that are thrown from a transactional in a rollback). Checked exceptions that are thrown from a transactional
method will <emphasis>not</emphasis> result in the transaction being method do <emphasis>not</emphasis> result in rollback.<!--I revised preceding because it says ONLY first case is rolled back by default, but then says Errors are also marked by default.
rolled back.</para>
<para>Exactly which <exceptionname>Exception</exceptionname> types mark TR: Errors aren't thrown by application code, only checked or unchecked exceptions are. So the Errors part is just clarifying that
a transaction for rollback can be configured. Find below a snippet of if the underlying application server infrastructure throws an Error the transaction will be rolled back--></para>
XML configuration that demonstrates how one would configure rollback for
a checked, application-specific <exceptionname>Exception</exceptionname> <para>You can configure exactly which
type.</para> <exceptionname>Exception</exceptionname> types mark a transaction for
rollback. The following XML snippet demonstrates how you configure
rollback for a checked, application-specific
<exceptionname>Exception</exceptionname> type.</para>
<programlisting language="xml">&lt;tx:advice id="txAdvice" transaction-manager="txManager"&gt; <programlisting language="xml">&lt;tx:advice id="txAdvice" transaction-manager="txManager"&gt;
&lt;tx:attributes&gt; &lt;tx:attributes&gt;
...@@ -961,10 +1000,9 @@ Exception in thread "main" java.lang.UnsupportedOperationException ...@@ -961,10 +1000,9 @@ Exception in thread "main" java.lang.UnsupportedOperationException
&lt;/tx:attributes&gt; &lt;/tx:attributes&gt;
&lt;/tx:advice&gt;</programlisting> &lt;/tx:advice&gt;</programlisting>
<para>It is also possible to specify 'no rollback rules', for those <para>You can also specify 'no rollback rules', if you do
times when you do <emphasis>not</emphasis> want a transaction to be <emphasis>not</emphasis> want a transaction rolled back when an
marked for rollback when an exception is thrown. In the example exception is thrown. The following example tells Spring Framework's
configuration below, we effectively are telling the Spring Framework's
transaction infrastructure to commit the attendant transaction even in transaction infrastructure to commit the attendant transaction even in
the face of an unhandled the face of an unhandled
<exceptionname>InstrumentNotFoundException</exceptionname>.</para> <exceptionname>InstrumentNotFoundException</exceptionname>.</para>
...@@ -976,13 +1014,13 @@ Exception in thread "main" java.lang.UnsupportedOperationException ...@@ -976,13 +1014,13 @@ Exception in thread "main" java.lang.UnsupportedOperationException
&lt;/tx:attributes&gt; &lt;/tx:attributes&gt;
&lt;/tx:advice&gt;</programlisting> &lt;/tx:advice&gt;</programlisting>
<para>When the Spring Framework's transaction infrastructure has caught <para>When Spring Framework's transaction infrastructure catches an
an exception and is consulting any configured rollback rules to exception and is consults configured rollback rules to determine whether
determine whether or not to mark the transaction for rollback, the to mark the transaction for rollback, the <emphasis>strongest</emphasis>
<emphasis>strongest</emphasis> matching rule wins. So in the case of the matching rule wins. So in the case of the following configuration, any
following configuration, any exception other than an exception other than an
<exceptionname>InstrumentNotFoundException</exceptionname> would result <exceptionname>InstrumentNotFoundException</exceptionname> results in a
in the attendant transaction being marked for rollback.</para> rollback of the attendant transaction.</para>
<programlisting language="xml">&lt;tx:advice id="txAdvice"&gt; <programlisting language="xml">&lt;tx:advice id="txAdvice"&gt;
&lt;tx:attributes&gt; &lt;tx:attributes&gt;
...@@ -990,10 +1028,10 @@ Exception in thread "main" java.lang.UnsupportedOperationException ...@@ -990,10 +1028,10 @@ Exception in thread "main" java.lang.UnsupportedOperationException
&lt;/tx:attributes&gt; &lt;/tx:attributes&gt;
&lt;/tx:advice&gt;</programlisting> &lt;/tx:advice&gt;</programlisting>
<para>The second way to indicate that a rollback is required is to do so <para>You can also indicate a required rollback
<emphasis>programmatically</emphasis>. Although very simple, this way is <emphasis>programmatically</emphasis>. Although very simple, this
quite invasive, and tightly couples your code to the Spring Framework's process is quite invasive, and tightly couples your code to Spring
transaction infrastructure, as can be seen below:</para> Framework's transaction infrastructure:</para>
<programlisting language="java">public void resolvePosition() { <programlisting language="java">public void resolvePosition() {
try { try {
...@@ -1007,7 +1045,7 @@ Exception in thread "main" java.lang.UnsupportedOperationException ...@@ -1007,7 +1045,7 @@ Exception in thread "main" java.lang.UnsupportedOperationException
<para>You are strongly encouraged to use the declarative approach to <para>You are strongly encouraged to use the declarative approach to
rollback if at all possible. Programmatic rollback is available should rollback if at all possible. Programmatic rollback is available should
you absolutely need it, but its usage flies in the face of achieving a you absolutely need it, but its usage flies in the face of achieving a
nice, clean POJO-based architecture.</para> clean POJO-based architecture.</para>
</section> </section>
<section id="transaction-declarative-diff-tx"> <section id="transaction-declarative-diff-tx">
...@@ -1015,17 +1053,18 @@ Exception in thread "main" java.lang.UnsupportedOperationException ...@@ -1015,17 +1053,18 @@ Exception in thread "main" java.lang.UnsupportedOperationException
beans</title> beans</title>
<para>Consider the scenario where you have a number of service layer <para>Consider the scenario where you have a number of service layer
objects, and you want to apply <emphasis>totally different</emphasis> objects, and you want to apply a <emphasis>totally different</emphasis>
transactional configuration to each of them. This is achieved by transactional configuration to each of them. You do this by defining
defining distinct <literal>&lt;aop:advisor/&gt;</literal> elements with distinct <literal>&lt;aop:advisor/&gt;</literal> elements with differing
differing <literal>'pointcut'</literal> and <literal>pointcut</literal> and <literal>advice-ref</literal> attribute
<literal>'advice-ref'</literal> attribute values.</para> values.</para>
<para>Let's assume that all of your service layer classes are defined in <para>As a point of comparison, first assume that all of your service
a root <literal>'x.y.service'</literal> package. To make all beans that layer classes are defined in a root <literal>x.y.service</literal>
are instances of classes defined in that package (or in subpackages) and package. To make all beans that are instances of classes defined in that
that have names ending in <literal>'Service'</literal> have the default package (or in subpackages) and that have names ending in
transactional configuration, you would write the following:</para> <literal>Service</literal> have the default transactional configuration,
you would write the following:</para>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt; <programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans" &lt;beans xmlns="http://www.springframework.org/schema/beans"
...@@ -1068,8 +1107,8 @@ Exception in thread "main" java.lang.UnsupportedOperationException ...@@ -1068,8 +1107,8 @@ Exception in thread "main" java.lang.UnsupportedOperationException
&lt;/beans&gt;</programlisting> &lt;/beans&gt;</programlisting>
<para>Find below an example of configuring two distinct beans with <para>The following example shows how to configure two distinct beans
totally different transactional settings.</para> with totally different transactional settings.</para>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt; <programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans" &lt;beans xmlns="http://www.springframework.org/schema/beans"
...@@ -1125,38 +1164,38 @@ Exception in thread "main" java.lang.UnsupportedOperationException ...@@ -1125,38 +1164,38 @@ Exception in thread "main" java.lang.UnsupportedOperationException
<section id="transaction-declarative-txadvice-settings"> <section id="transaction-declarative-txadvice-settings">
<title><literal>&lt;tx:advice/&gt;</literal> settings</title> <title><literal>&lt;tx:advice/&gt;</literal> settings</title>
<para>This section summarises the various transactional settings that <para>This section summarizes the various transactional settings that
can be specified using the <literal>&lt;tx:advice/&gt;</literal> tag. can be specified using the <literal>&lt;tx:advice/&gt;</literal> tag.
The default <literal>&lt;tx:advice/&gt;</literal> settings are:</para> The default <literal>&lt;tx:advice/&gt;</literal> settings are:</para>
<para><itemizedlist> <para><itemizedlist>
<listitem> <listitem>
<para>The <link linkend="tx-propagation">propagation <para><link linkend="tx-propagation">Propagation setting</link> is
setting</link> is <literal>REQUIRED</literal></para> <literal>REQUIRED.</literal></para>
</listitem> </listitem>
<listitem> <listitem>
<para>The isolation level is <literal>DEFAULT</literal></para> <para>Isolation level is <literal>DEFAULT.</literal></para>
</listitem> </listitem>
<listitem> <listitem>
<para>The transaction is read/write</para> <para>Transaction is read/write.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>The transaction timeout defaults to the default timeout of <para>Transaction timeout defaults to the default timeout of the
the underlying transaction system, or or none if timeouts are not underlying transaction system, or none if timeouts are not
supported</para> supported.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Any <exceptionname>RuntimeException</exceptionname> will <para>Any <exceptionname>RuntimeException</exceptionname> triggers
trigger rollback, and any checked rollback, and any checked <exceptionname>Exception</exceptionname>
<exceptionname>Exception</exceptionname> will not</para> does not.</para>
</listitem> </listitem>
</itemizedlist></para> </itemizedlist></para>
<para>These default settings can be changed; the various attributes of <para>You can change these default settings; the various attributes of
the <literal>&lt;tx:method/&gt;</literal> tags that are nested within the <literal>&lt;tx:method/&gt;</literal> tags that are nested within
<literal>&lt;tx:advice/&gt;</literal> and <literal>&lt;tx:advice/&gt;</literal> and
<literal>&lt;tx:attributes/&gt;</literal> tags are summarized <literal>&lt;tx:attributes/&gt;</literal> tags are summarized
...@@ -1166,6 +1205,14 @@ Exception in thread "main" java.lang.UnsupportedOperationException ...@@ -1166,6 +1205,14 @@ Exception in thread "main" java.lang.UnsupportedOperationException
<title><literal>&lt;tx:method/&gt;</literal> settings</title> <title><literal>&lt;tx:method/&gt;</literal> settings</title>
<tgroup cols="4"> <tgroup cols="4">
<colspec colnum="1" colwidth="1*" />
<colspec colnum="2" colwidth="0.4*" />
<colspec colnum="3" colwidth="0.6*" />
<colspec colnum="4" colwidth="2*" />
<thead> <thead>
<row> <row>
<entry>Attribute</entry> <entry>Attribute</entry>
...@@ -1186,13 +1233,12 @@ Exception in thread "main" java.lang.UnsupportedOperationException ...@@ -1186,13 +1233,12 @@ Exception in thread "main" java.lang.UnsupportedOperationException
<entry></entry> <entry></entry>
<entry><para>The method name(s) with which the transaction <entry><para>Method name(s) with which the transaction
attributes are to be associated. The wildcard (*) character attributes are to be associated. The wildcard (*) character
can be used to associate the same transaction attribute can be used to associate the same transaction attribute
settings with a number of methods; for example, settings with a number of methods; for example,
<literal>'get*'</literal>, <literal>get*</literal>, <literal>handle*</literal>,<literal>
<literal>'handle*'</literal>,<literal> 'on*Event'</literal>, on*Event</literal>, and so forth.</para></entry>
and so forth.</para></entry>
</row> </row>
<row> <row>
...@@ -1202,7 +1248,7 @@ Exception in thread "main" java.lang.UnsupportedOperationException ...@@ -1202,7 +1248,7 @@ Exception in thread "main" java.lang.UnsupportedOperationException
<entry>REQUIRED</entry> <entry>REQUIRED</entry>
<entry>The transaction propagation behavior</entry> <entry>Transaction propagation behavior.</entry>
</row> </row>
<row> <row>
...@@ -1212,7 +1258,7 @@ Exception in thread "main" java.lang.UnsupportedOperationException ...@@ -1212,7 +1258,7 @@ Exception in thread "main" java.lang.UnsupportedOperationException
<entry>DEFAULT</entry> <entry>DEFAULT</entry>
<entry>The transaction isolation level</entry> <entry>Transaction isolation level.</entry>
</row> </row>
<row> <row>
...@@ -1222,7 +1268,7 @@ Exception in thread "main" java.lang.UnsupportedOperationException ...@@ -1222,7 +1268,7 @@ Exception in thread "main" java.lang.UnsupportedOperationException
<entry>-1</entry> <entry>-1</entry>
<entry>The transaction timeout value (in seconds)</entry> <entry>Transaction timeout value (in seconds).</entry>
</row> </row>
<row> <row>
...@@ -1242,9 +1288,9 @@ Exception in thread "main" java.lang.UnsupportedOperationException ...@@ -1242,9 +1288,9 @@ Exception in thread "main" java.lang.UnsupportedOperationException
<entry></entry> <entry></entry>
<entry><para>The <literal>Exception(s)</literal> that will <entry><para><literal>Exception(s)</literal> that trigger
trigger rollback; comma-delimited. For example, rollback; comma-delimited. For example,
<literal>'com.foo.MyBusinessException,ServletException'</literal></para></entry> <literal>com.foo.MyBusinessException,ServletException.</literal></para></entry>
</row> </row>
<row> <row>
...@@ -1254,10 +1300,10 @@ Exception in thread "main" java.lang.UnsupportedOperationException ...@@ -1254,10 +1300,10 @@ Exception in thread "main" java.lang.UnsupportedOperationException
<entry></entry> <entry></entry>
<entry><para>The <literal>Exception(s)</literal> that will <entry><para><literal>Exception(s)</literal> that do
<emphasis>not</emphasis> trigger rollback; comma-delimited. <emphasis>not</emphasis> trigger rollback; comma-delimited.
For example, For example,
<literal>'com.foo.MyBusinessException,ServletException'</literal></para></entry> <literal>com.foo.MyBusinessException,ServletException.</literal></para></entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
...@@ -1267,25 +1313,17 @@ Exception in thread "main" java.lang.UnsupportedOperationException ...@@ -1267,25 +1313,17 @@ Exception in thread "main" java.lang.UnsupportedOperationException
<section id="transaction-declarative-annotations"> <section id="transaction-declarative-annotations">
<title>Using <interfacename>@Transactional</interfacename></title> <title>Using <interfacename>@Transactional</interfacename></title>
<note>
<para>The functionality offered by the
<interfacename>@Transactional</interfacename> annotation and the
support classes is only available to you if you are using at least
Java 5 (Tiger).</para>
</note>
<para>In addition to the XML-based declarative approach to transaction <para>In addition to the XML-based declarative approach to transaction
configuration, you can also use an annotation-based approach to configuration, you can use an annotation-based approach. Declaring
transaction configuration. Declaring transaction semantics directly in transaction semantics directly in the Java source code puts the
the Java source code puts the declarations much closer to the affected declarations much closer to the affected code. There is not much danger
code, and there is generally not much danger of undue coupling, since of undue coupling, because code that is meant to be used transactionally
code that is meant to be used transactionally is almost always deployed is almost always deployed that way anyway.</para>
that way anyway.</para>
<para>The ease-of-use afforded by the use of the <para>The ease-of-use afforded by the use of the
<interfacename>@Transactional</interfacename> annotation is best <interfacename>@Transactional</interfacename> annotation is best
illustrated with an example, after which all of the details will be illustrated with an example, which is explained in the text that
explained. Consider the following class definition:</para> follows. Consider the following class definition:</para>
<programlisting language="java"><lineannotation>// the service class that we want to make transactional</lineannotation> <programlisting language="java"><lineannotation>// the service class that we want to make transactional</lineannotation>
<emphasis role="bold">@Transactional</emphasis> <emphasis role="bold">@Transactional</emphasis>
...@@ -1302,7 +1340,7 @@ public class DefaultFooService implements FooService { ...@@ -1302,7 +1340,7 @@ public class DefaultFooService implements FooService {
<para>When the above POJO is defined as a bean in a Spring IoC <para>When the above POJO is defined as a bean in a Spring IoC
container, the bean instance can be made transactional by adding merely container, the bean instance can be made transactional by adding merely
<emphasis>one</emphasis> line of XML configuration, like so:</para> <emphasis>one</emphasis> line of XML configuration:</para>
<programlisting language="xml"><lineannotation>&lt;!-- from the file <literal>'context.xml'</literal> --&gt;</lineannotation> <programlisting language="xml"><lineannotation>&lt;!-- from the file <literal>'context.xml'</literal> --&gt;</lineannotation>
&lt;?xml version="1.0" encoding="UTF-8"?&gt; &lt;?xml version="1.0" encoding="UTF-8"?&gt;
...@@ -1335,76 +1373,78 @@ public class DefaultFooService implements FooService { ...@@ -1335,76 +1373,78 @@ public class DefaultFooService implements FooService {
&lt;/beans&gt;</programlisting> &lt;/beans&gt;</programlisting>
<tip> <tip>
<para>You can actually omit the <para>You can omit the <literal>transaction-manager</literal>
<literal>'transaction-manager'</literal> attribute in the attribute in the <literal>&lt;tx:annotation-driven/&gt;</literal> tag
<literal>&lt;tx:annotation-driven/&gt;</literal> tag if the bean name if the bean name of the
of the <interfacename>PlatformTransactionManager</interfacename> that <interfacename>PlatformTransactionManager</interfacename> that you
you want to wire in has the name want to wire in has the name <literal>transactionManager</literal>. If
<literal>'transactionManager'</literal>. If the the <interfacename>PlatformTransactionManager</interfacename> bean
<interfacename>PlatformTransactionManager</interfacename> bean that that you want to dependency-inject has any other name, then you have
you want to dependency inject has any other name, then you have to be to use the <literal>transaction-manager</literal> attribute
explicit and use the <literal>'transaction-manager'</literal> explicitly, as in the preceding example.</para>
attribute as in the example above.</para>
</tip> </tip>
<sidebar> <sidebar>
<title>Method visibility and <title>Method visibility and
<interfacename>@Transactional</interfacename></title> <interfacename>@Transactional</interfacename></title>
<para>When using proxies, the <para>When using proxies, you should apply the
<interfacename>@Transactional</interfacename> annotation should only <interfacename>@Transactional</interfacename> annotation only to
be applied to methods with <emphasis>public</emphasis> visibility. If methods with <emphasis>public</emphasis> visibility. If you do
you do annotate protected, private or package-visible methods with the annotate protected, private or package-visible methods with the
<interfacename>@Transactional</interfacename> annotation, no error <interfacename>@Transactional</interfacename> annotation, no error is
will be raised, but the annotated method will not exhibit the raised, but the annotated method does not exhibit the configured
configured transactional settings. Consider the use of AspectJ (see transactional settings. Consider the use of AspectJ (see below) if you
below) if you need to annotate non-public methods.</para> need to annotate non-public methods.</para>
</sidebar> </sidebar>
<para>The <interfacename>@Transactional</interfacename> annotation may <para>You can place the <interfacename>@Transactional</interfacename>
be placed before an interface definition, a method on an interface, a annotation before an interface definition, a method on an interface, a
class definition, or a <emphasis>public</emphasis> method on a class. class definition, or a <emphasis>public</emphasis> method on a class.
However, please note that the mere presence of the However, the mere presence of the
<interfacename>@Transactional</interfacename> annotation is not enough <interfacename>@Transactional</interfacename> annotation is not enough
to actually turn on the transactional behavior - the to activate the transactional behavior. The
<interfacename>@Transactional</interfacename> annotation <emphasis>is <interfacename>@Transactional</interfacename> annotation is simply
simply metadata</emphasis> that can be consumed by something that is metadata that can be consumed by something<!--Please identify *something* .-->
<interfacename>@Transactional</interfacename>-aware and that can use the that is <interfacename>@Transactional</interfacename>-aware and that can
metadata to configure the appropriate beans with transactional behavior. use the metadata to configure the appropriate beans with transactional
In the case of the above example, it is the presence of the behavior. In the preceding example, the
<literal>&lt;tx:annotation-driven/&gt;</literal> element that <literal>&lt;tx:annotation-driven/&gt;</literal> element
<emphasis>switches on</emphasis> the transactional behavior.</para> <emphasis>switches on</emphasis> the transactional behavior.</para>
<para>The Spring team's recommendation is that you only annotate <para><tip>
concrete classes with the <interfacename>@Transactional</interfacename> <para>Spring recommends that you only annotate concrete classes (and
annotation, as opposed to annotating interfaces. You certainly can place methods of concrete classes) with the
the <interfacename>@Transactional</interfacename> annotation on an <interfacename>@Transactional</interfacename> annotation, as opposed
interface (or an interface method), but this will only work as you would to annotating interfaces. You certainly can place the
expect it to if you are using interface-based proxies. The fact that <interfacename>@Transactional</interfacename> annotation on an
annotations are <emphasis>not inherited</emphasis> means that if you are interface (or an interface method), but this works only as you would
using class-based proxies (<literal>proxy-target-class="true"</literal>) expect it to if you are using interface-based proxies. The fact that
or the weaving-based aspect (<literal>mode="aspectj"</literal>) then the annotations are <emphasis>not inherited</emphasis> means that if you
transaction settings will not be recognised by the proxying/weaving are using class-based proxies
infrastructure and the object will not be wrapped in a transactional (<literal>proxy-target-class="true"</literal>) or the weaving-based
proxy (which would be decidedly <emphasis>bad</emphasis>). So please do aspect (<literal>mode="aspectj"</literal>), then the transaction
take the Spring team's advice and only annotate concrete classes (and settings are not recognized by the proxying and weaving
the methods of concrete classes) with the infrastructure, and the object will not be wrapped in a
<interfacename>@Transactional</interfacename> annotation.</para> transactional proxy, which would be decidedly
<emphasis>bad</emphasis>.</para>
<para><emphasis>Note: In proxy mode (which is the default), only </tip></para>
'external' method calls coming in through the proxy will be
intercepted.</emphasis> This means that 'self-invocation', i.e. a method <note>
within the target object calling some other method of the target object, <para>In proxy mode (which is the default), only external method calls
won't lead to an actual transaction at runtime even if the invoked coming in through the proxy are intercepted. This means that
method is marked with self-invocation, in effect, a method within the target object calling
<interfacename>@Transactional</interfacename>!</para> another method of the target object, will not lead to an actual
transaction at runtime even if the invoked method is marked with
<interfacename>@Transactional</interfacename>.</para>
</note>
<para>Consider the use of AspectJ mode (see below) if you expect <para>Consider the use of AspectJ mode (see below) if you expect
self-invocations to be wrapped with transactions as well. In this case, self-invocations to be wrapped with transactions as well. <!--*see below* is not clear re AspectJmode. Provide clear x-ref to mode in table below, or to Using Transactional with AspectJ section. Also clarify reference to *as well*. As well as what?--><!--Below, *in this case* meaning in *what* case? Explain what table shows.-->In
there won't be a proxy in the first place; instead, the target class this case, there will not be a proxy in the first place; instead, the
will be 'weaved' (i.e. its byte code will be modified) in order to turn target class will be weaved (that is, its byte code will be modified) in
<interfacename>@Transactional</interfacename> into runtime behavior on order to turn <interfacename>@Transactional</interfacename> into runtime
any kind of method.</para> behavior on any kind of method.</para>
<para><table id="tx-annotation-driven-settings"> <para><table id="tx-annotation-driven-settings">
<title><literal>&lt;tx:annotation-driven/&gt;</literal> <title><literal>&lt;tx:annotation-driven/&gt;</literal>
...@@ -1427,8 +1467,8 @@ public class DefaultFooService implements FooService { ...@@ -1427,8 +1467,8 @@ public class DefaultFooService implements FooService {
<entry>transactionManager</entry> <entry>transactionManager</entry>
<entry><para>The name of transaction manager to use. Only <entry><para>Name of transaction manager to use. Only required
required if the name of the transaction manager is not if the name of the transaction manager is not
<literal>transactionManager</literal>, as in the example <literal>transactionManager</literal>, as in the example
above.</para></entry> above.</para></entry>
</row> </row>
...@@ -1438,18 +1478,17 @@ public class DefaultFooService implements FooService { ...@@ -1438,18 +1478,17 @@ public class DefaultFooService implements FooService {
<entry>proxy</entry> <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 beans to be proxied using Spring's AOP framework (following
proxy semantics, as discussed above, applying to method calls proxy semantics, as discussed above, applying to method calls
coming in through the proxy only). The alternative mode coming in through the proxy only). The alternative mode
"aspectj" will instead weave the affected classes with "aspectj" instead weaves the affected classes with Spring's
Spring's AspectJ transaction aspect (modifying the target AspectJ transaction aspect, modifying the target class byte
class byte code in order to apply to any kind of method call). code to apply to any kind of method call. AspectJ weaving
AspectJ weaving requires spring-aspects.jar on the classpath requires spring-aspects.jar in the classpath as well as
as well as load-time weaving (or compile-time weaving) load-time weaving (or compile-time weaving) enabled. (See
enabled. (See the section entitled <xref <xref linkend="aop-aj-ltw-spring" /> for details on how to set
linkend="aop-aj-ltw-spring" /> for details on how to set up up load-time weaving.)</para></entry>
load-time weaving.)</para></entry>
</row> </row>
<row> <row>
...@@ -1460,14 +1499,13 @@ public class DefaultFooService implements FooService { ...@@ -1460,14 +1499,13 @@ public class DefaultFooService implements FooService {
<entry><para>Applies to proxy mode only. Controls what type of <entry><para>Applies to proxy mode only. Controls what type of
transactional proxies are created for classes annotated with transactional proxies are created for classes annotated with
the <interfacename>@Transactional</interfacename> annotation. the <interfacename>@Transactional</interfacename> annotation.
If "<literal>proxy-target-class</literal>" attribute is set to If the <literal>proxy-target-class</literal> attribute is set
"<literal>true</literal>", then class-based proxies will be to <literal>true</literal>, then class-based proxies are
created. If "<literal>proxy-target-class</literal>" is created. If <literal>proxy-target-class</literal> is
"<literal>false</literal>" or if the attribute is omitted, <literal>false</literal> or if the attribute is omitted, then
then standard JDK interface-based proxies will be created. standard JDK interface-based proxies are created. (See <xref
(See the section entitled <xref linkend="aop-proxying" /> for linkend="aop-proxying" /> for a detailed examination of the
a detailed examination of the different proxy different proxy types.)</para></entry>
types.)</para></entry>
</row> </row>
<row> <row>
...@@ -1476,49 +1514,48 @@ public class DefaultFooService implements FooService { ...@@ -1476,49 +1514,48 @@ public class DefaultFooService implements FooService {
<entry>Ordered.LOWEST_PRECEDENCE</entry> <entry>Ordered.LOWEST_PRECEDENCE</entry>
<entry><para>Defines the order of the transaction advice that <entry><para>Defines the order of the transaction advice that
will be applied to beans annotated with is applied to beans annotated with
<interfacename>@Transactional</interfacename>. More on the <interfacename>@Transactional</interfacename>. (For more
rules related to ordering of AOP advice can be found in the information about the rules related to ordering of AOP advice,
AOP chapter (see section <xref see <xref linkend="aop-ataspectj-advice-ordering" />.) No
linkend="aop-ataspectj-advice-ordering" />). Note that not specified ordering means that the AOP subsystem determines the
specifying any ordering will leave the decision as to what order of the advice.</para></entry>
order advice is run in to the AOP subsystem.</para></entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
</table></para> </table></para>
<note> <note>
<para>The "<literal>proxy-target-class</literal>" attribute on the <para>The <literal>proxy-target-class</literal> attribute on the
<literal>&lt;tx:annotation-driven/&gt;</literal> element controls what <literal>&lt;tx:annotation-driven/&gt;</literal> element controls what
type of transactional proxies are created for classes annotated with type of transactional proxies are created for classes annotated with
the <interfacename>@Transactional</interfacename> annotation. If the <interfacename>@Transactional</interfacename> annotation. If
"<literal>proxy-target-class</literal>" attribute is set to <literal>proxy-target-class</literal> attribute is set to
"<literal>true</literal>", then class-based proxies will be created. <literal>true</literal>, class-based proxies are created. If
If "<literal>proxy-target-class</literal>" is <literal>proxy-target-class</literal> is <literal>false</literal> or
"<literal>false</literal>" or if the attribute is omitted, then if the attribute is omitted, standard JDK interface-based proxies are
standard JDK interface-based proxies will be created. (See the section created. (See <xref linkend="aop-proxying" /> for a discussion of the
entitled <xref linkend="aop-proxying" /> for a detailed examination of different proxy types.)</para>
the different proxy types.)</para>
</note> </note>
<note> <note>
<para>Note that <literal>&lt;tx:annotation-driven/&gt;</literal> only <para><literal>&lt;tx:annotation-driven/&gt;</literal> only looks for
looks for <interfacename>@Transactional</interfacename> on beans in <interfacename>@Transactional</interfacename> on beans in the same
the same application context it is defined in. This means that, if you application context it is defined in. This means that, if you put
put <literal>&lt;tx:annotation-driven/&gt;</literal> in a <literal>&lt;tx:annotation-driven/&gt;</literal> in a
<interfacename>WebApplicationContext</interfacename> for a <interfacename>WebApplicationContext</interfacename> for a
<classname>DispatcherServlet</classname>, it only checks for <classname>DispatcherServlet</classname>, it only checks for
<interfacename>@Transactional</interfacename> beans in your <interfacename>@Transactional</interfacename> beans in your
controllers, and not your services. See <xref linkend="mvc-servlet" /> controllers, and not your services. <!--I don't understand the logic of preceding explanation. Also identify *it* in first sentence of Note.-->See
for more information.</para> <xref linkend="mvc-servlet" /> for more information.</para>
</note> </note>
<para>The most derived location takes precedence when evaluating the <para>The most derived location takes precedence when evaluating the
transactional settings for a method. In the case of the following transactional settings for a method. <!--Do you need to clarify what *most derived* location means? Lowest level?-->In
example, the <classname>DefaultFooService</classname> class is annotated the case of the following example, the
at the class level with the settings for a read-only transaction, but <classname>DefaultFooService</classname> class is annotated at the class
the <interfacename>@Transactional</interfacename> annotation on the 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 <methodname>updateFoo(Foo)</methodname> method in the same class takes
precedence over the transactional settings defined at the class precedence over the transactional settings defined at the class
level.</para> level.</para>
...@@ -1545,33 +1582,34 @@ public class DefaultFooService implements FooService { ...@@ -1545,33 +1582,34 @@ public class DefaultFooService implements FooService {
transactional semantics; for example, <quote><emphasis>start a brand transactional semantics; for example, <quote><emphasis>start a brand
new read-only transaction when this method is invoked, suspending any new read-only transaction when this method is invoked, suspending any
existing transaction</emphasis></quote>. The default existing transaction</emphasis></quote>. The default
<interfacename>@Transactional</interfacename> settings are:</para> <interfacename>@Transactional</interfacename> settings are as
follows:</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para>The propagation setting is <para>Propagation setting is
<literal>PROPAGATION_REQUIRED</literal></para> <literal>PROPAGATION_REQUIRED.</literal></para>
</listitem> </listitem>
<listitem> <listitem>
<para>The isolation level is <para>Isolation level is
<literal>ISOLATION_DEFAULT</literal></para> <literal>ISOLATION_DEFAULT.</literal></para>
</listitem> </listitem>
<listitem> <listitem>
<para>The transaction is read/write</para> <para>Transaction is read/write.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>The transaction timeout defaults to the default timeout of <para>Transaction timeout defaults to the default timeout of the
the underlying transaction system, or or none if timeouts are not underlying transaction system, or to none if timeouts are not
supported</para> supported.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Any <exceptionname>RuntimeException</exceptionname> will <para>Any <exceptionname>RuntimeException</exceptionname> triggers
trigger rollback, and any checked rollback, and any checked <exceptionname>Exception</exceptionname>
<exceptionname>Exception</exceptionname> will not</para> does not.<!--Bullet list above does not exactly map to properties in table.ok?--></para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
...@@ -1601,7 +1639,7 @@ public class DefaultFooService implements FooService { ...@@ -1601,7 +1639,7 @@ public class DefaultFooService implements FooService {
<entry>enum: <classname>Propagation</classname></entry> <entry>enum: <classname>Propagation</classname></entry>
<entry>optional propagation setting</entry> <entry>Optional propagation setting.</entry>
</row> </row>
<row> <row>
...@@ -1609,7 +1647,7 @@ public class DefaultFooService implements FooService { ...@@ -1609,7 +1647,7 @@ public class DefaultFooService implements FooService {
<entry>enum: <classname>Isolation</classname></entry> <entry>enum: <classname>Isolation</classname></entry>
<entry>optional isolation level</entry> <entry>Optional isolation level.</entry>
</row> </row>
<row> <row>
...@@ -1617,7 +1655,7 @@ public class DefaultFooService implements FooService { ...@@ -1617,7 +1655,7 @@ public class DefaultFooService implements FooService {
<entry>boolean</entry> <entry>boolean</entry>
<entry>read/write vs. read-only transaction</entry> <entry>Read/write vs. read-only transaction</entry>
</row> </row>
<row> <row>
...@@ -1625,63 +1663,63 @@ public class DefaultFooService implements FooService { ...@@ -1625,63 +1663,63 @@ public class DefaultFooService implements FooService {
<entry>int (in seconds granularity)</entry> <entry>int (in seconds granularity)</entry>
<entry>the transaction timeout</entry> <entry>Transaction timeout.</entry>
</row> </row>
<row> <row>
<entry><literal>rollbackFor</literal></entry> <entry><literal>rollbackFor</literal></entry>
<entry>an array of <classname>Class</classname> objects, <entry>Array of <classname>Class</classname> objects, which
which must be derived from must be derived from
<classname>Throwable</classname></entry> <classname>Throwable.</classname></entry>
<entry>an optional array of exception classes which <entry>Optional array of exception classes that <emphasis
<emphasis role="bold">must</emphasis> cause rollback</entry> role="bold">must</emphasis> cause rollback.</entry>
</row> </row>
<row> <row>
<entry><literal>rollbackForClassname</literal></entry> <entry><literal>rollbackForClassname</literal></entry>
<entry>an array of <classname></classname> class names. <entry>Array of class names. Classes must be derived from
Classes must be derived from <classname>Throwable.</classname></entry>
<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</emphasis> cause rollback</entry> <emphasis role="bold">must</emphasis> cause
rollback.</entry>
</row> </row>
<row> <row>
<entry><literal>noRollbackFor</literal></entry> <entry><literal>noRollbackFor</literal></entry>
<entry>an array of <classname>Class</classname> objects, <entry>Array of <classname>Class</classname> objects, which
which must be derived from must be derived from
<classname>Throwable</classname></entry> <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> role="bold">must not</emphasis> cause rollback.</entry>
</row> </row>
<row> <row>
<entry><literal>noRollbackForClassname</literal></entry> <entry><literal>noRollbackForClassname</literal></entry>
<entry>an array of <classname>String</classname> class <entry>Array of <classname>String</classname> class names,
names, which must be derived from which must be derived from
<classname>Throwable</classname></entry> <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 <emphasis role="bold">must not</emphasis> cause
rollback</entry> rollback.</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
</table></para> </table></para>
<para>Currently it is not possible to have explicit control over the <para>Currently you cannot have explicit control over the name of a
name of a transaction, where 'name' means the transaction name that transaction, where 'name' means the transaction name that will be
will be shown in a transaction monitor, if applicable (for example, shown in a transaction monitor, if applicable (for example, WebLogic's
WebLogic's transaction monitor), and in logging output. For transaction monitor), and in logging output. For declarative
declarative transactions, the transaction name is always the transactions, the transaction name is always the fully-qualified class
fully-qualified class name + "." + method name of the name + "." + <!--Meaning of symbols is unclear.-->method name of the
transactionally-advised class. For example, if the transactionally-advised class. For example, if the
<methodname>handlePayment(..)</methodname> method of the <methodname>handlePayment(..)</methodname> method of the
<classname>BusinessService</classname> class started a transaction, <classname>BusinessService</classname> class started a transaction,
...@@ -1693,15 +1731,18 @@ public class DefaultFooService implements FooService { ...@@ -1693,15 +1731,18 @@ public class DefaultFooService implements FooService {
<section id="tx-propagation"> <section id="tx-propagation">
<title>Transaction propagation</title> <title>Transaction propagation</title>
<para><emphasis>Please note that this section of the Spring reference <!--Changed heading to be more explicit. These are settings, right?
documentation is <emphasis>not</emphasis> an introduction to transaction TR: changed it back; it's not just settings, the section discusses propagation in general as well as the settings-->
propagation proper; rather it details some of the semantics regarding
transaction propagation in Spring.</emphasis></para> <para>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.</para>
<para>In the case of Spring-managed transactions, please be aware of the <para>In Spring-managed transactions, be aware of the difference between
difference between <emphasis>physical</emphasis> and <emphasis>physical</emphasis> and <emphasis>logical</emphasis>
<emphasis>logical</emphasis> transactions, and how the propagation transactions, and how the propagation setting applies to this
setting applies to this difference.</para> difference.</para>
<section id="tx-propagation-required"> <section id="tx-propagation-required">
<title>Required</title> <title>Required</title>
...@@ -1718,28 +1759,28 @@ public class DefaultFooService implements FooService { ...@@ -1718,28 +1759,28 @@ public class DefaultFooService implements FooService {
<para>When the propagation setting is <para>When the propagation setting is
<literal>PROPAGATION_REQUIRED</literal>, a <literal>PROPAGATION_REQUIRED</literal>, a
<emphasis>logical</emphasis> transaction scope is created for each <emphasis>logical</emphasis> transaction scope is created for each
method that it gets applied to. Each such logical transaction scope method that to which the setting is applied. Each such logical
can individually decide on rollback-only status, with an outer transaction scope can determine rollback-only status individually,
transaction scope being logically independent from the inner with an outer transaction scope being logically independent from the
transaction scope. Of course, in case of standard inner transaction scope. Of course, in case of standard
<literal>PROPAGATION_REQUIRED</literal> behavior, they will be mapped <literal>PROPAGATION_REQUIRED</literal> behavior, all these scopes<!--OK? Need to identify *they*.-->
to the same physical transaction. So a rollback-only marker set in the will be mapped to the same physical transaction. So a rollback-only
inner transaction scope does affect the outer transactions chance to marker set in the inner transaction scope does affect the outer
actually commit (as you would expect it to).</para> transaction's chance to actually commit (as you would expect it
to).<!--Do you need to explain what an inner transaction scope as opposed to an outer transaction scope?--></para>
<para>However, in the case where an inner transaction scopes sets the
rollback-only marker, the outer transaction itself has not decided on <para>However, in the case where an inner transaction scope sets the
the rollback itself, and so the rollback (silently triggered by the rollback-only marker, the outer transaction has not decided on the
inner transaction scope) is unexpected: a corresponding rollback itself, and so the rollback (silently triggered by the inner
<classname>UnexpectedRollbackException</classname> will be thrown at transaction scope) is unexpected. A corresponding
that point. This is <emphasis>expected behavior</emphasis> so that the <classname>UnexpectedRollbackException</classname> is thrown at that
point. This is <emphasis>expected behavior</emphasis> so that the
caller of a transaction can never be misled to assume that a commit 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 was performed when it really was not. So if an inner transaction (of
the outer caller is not aware of) silently marks a transaction as which the outer caller is not aware) silently marks a transaction as
rollback-only, the outer caller would still innocently call commit - rollback-only, the outer caller still calls commit. The outer caller
and needs to receive an needs to receive an <classname>UnexpectedRollbackException</classname>
<classname>UnexpectedRollbackException</classname> to indicate clearly to indicate clearly that a rollback was performed instead.</para>
that a rollback was performed instead.</para>
</section> </section>
<section id="tx-propagation-requires_new"> <section id="tx-propagation-requires_new">
...@@ -1755,10 +1796,11 @@ public class DefaultFooService implements FooService { ...@@ -1755,10 +1796,11 @@ public class DefaultFooService implements FooService {
<caption><para>PROPAGATION_REQUIRES_NEW</para></caption> <caption><para>PROPAGATION_REQUIRES_NEW</para></caption>
</mediaobject></para> </mediaobject></para>
<para><literal>PROPAGATION_REQUIRES_NEW</literal>, in contrast, uses a <para><literal>PROPAGATION_REQUIRES_NEW</literal>, in contrast to
<type>PROPAGATION_REQUIRED</type>, uses a
<emphasis>completely</emphasis> independent transaction for each <emphasis>completely</emphasis> independent transaction for each
affected transaction scope. In that case, the underlying physical 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 independently, with an outer transaction not affected by an inner
transaction's rollback status.</para> transaction's rollback status.</para>
</section> </section>
...@@ -1766,66 +1808,64 @@ public class DefaultFooService implements FooService { ...@@ -1766,66 +1808,64 @@ public class DefaultFooService implements FooService {
<section id="tx-propagation-nested"> <section id="tx-propagation-nested">
<title>Nested</title> <title>Nested</title>
<para><literal>PROPAGATION_NESTED</literal> is different again in that <para><literal>PROPAGATION_NESTED</literal> uses a
it uses a <emphasis>single</emphasis> physical transaction with <emphasis>single</emphasis> physical transaction with multiple
multiple savepoints that it can roll back to. Such partial rollbacks savepoints that it can roll back to. Such partial rollbacks allow an
allow an inner transaction scope to trigger a rollback <emphasis>for inner transaction scope to trigger a rollback <emphasis>for its
its scope</emphasis>, with the outer transaction being able to scope</emphasis>, with the outer transaction being able to continue
continue the physical transaction despite some operations having been the physical transaction despite some operations having been rolled
rolled back. This is typically mapped onto JDBC savepoints, so will back. This setting is typically mapped onto JDBC savepoints, so will
only work with JDBC resource transactions (see Spring's only work with JDBC resource transactions. See Spring's
<classname>DataSourceTransactionManager</classname>).</para> <classname>DataSourceTransactionManager</classname>.</para>
</section> </section>
</section> </section>
<section id="transaction-declarative-applying-more-than-just-tx-advice"> <section id="transaction-declarative-applying-more-than-just-tx-advice">
<title>Advising transactional operations</title> <title>Advising transactional operations<!--Need better heading? Executing transactional advice?--></title>
<para>Consider the situation where you would like to execute <para>Suppose you want to execute <emphasis>both</emphasis>
<emphasis>both</emphasis> transactional <emphasis>and</emphasis> (to transactional <emphasis>and</emphasis> some basic profiling advice. How
keep things simple) some basic profiling advice. How do you effect this do you effect this in the context of
in the context of using
<literal>&lt;tx:annotation-driven/&gt;</literal>?</para> <literal>&lt;tx:annotation-driven/&gt;</literal>?</para>
<para>What we want to see when we invoke the <para>When you invoke the <methodname>updateFoo(Foo)</methodname>
<methodname>updateFoo(Foo)</methodname> method is:</para> method, you want to see the following actions:<!--I changed this to a numbered list because language indicated that one thing happens after another.--></para>
<itemizedlist> <orderedlist>
<listitem> <listitem>
<para>the configured profiling aspect starting up,</para> <para>Configured profiling aspect starts up.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>then the transactional advice executing,</para> <para>Transactional advice executes.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>then the method on the advised object executing</para> <para>Method on the advised object executes.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>then the transaction committing (we'll assume a sunny day <para>Transaction commits.</para>
scenario here),</para>
</listitem> </listitem>
<listitem> <listitem>
<para>and then finally the profiling aspect reporting (somehow) <para>Profiling aspect reports exact duration of the whole
exactly how long the whole transactional method invocation transactional method invocation.</para>
took</para>
</listitem> </listitem>
</itemizedlist> </orderedlist>
<note> <note>
<para>This chapter is not concerned with explaining AOP in any great <para>This chapter is not concerned with explaining AOP in any great
detail (except as it applies to transactions). Please see the chapter detail (except as it applies to transactions). See <xref
entitled <xref linkend="aop" /> for detailed coverage of the various linkend="aop" /> for detailed coverage of the following AOP
bits and pieces of the following AOP configuration (and AOP in configuration and AOP in general.</para>
general).</para>
</note> </note>
<para>Here is the code for a simple profiling aspect. The ordering of <para>Here is the code for a simple profiling aspect discussed above.
advice is controlled via the <interfacename>Ordered</interfacename> <!--If you mean this code produces actions above, say that. TR: added 'discussed above'-->The
interface. For full details on advice ordering, see <xref ordering of advice is controlled through the
<interfacename>Ordered</interfacename> interface. For full details on
advice ordering, see <xref
linkend="aop-ataspectj-advice-ordering" />.</para> linkend="aop-ataspectj-advice-ordering" />.</para>
<programlisting language="java">package x.y; <programlisting language="java">package x.y;
...@@ -1909,15 +1949,14 @@ public class SimpleProfiler implements Ordered { ...@@ -1909,15 +1949,14 @@ public class SimpleProfiler implements Ordered {
&lt;/beans&gt;</programlisting> &lt;/beans&gt;</programlisting>
<para>The result of the above configuration will be a <para>The result of the above configuration is a
<literal>'fooService'</literal> bean that has profiling and <literal>fooService</literal> bean that has profiling and transactional
transactional aspects applied to it <emphasis>in that order</emphasis>. aspects applied to it <emphasis>in the desired order</emphasis>. <!--By *that order,* indicate whether you mean the numbered process or the above example? Or are they the same?
The configuration of any number of additional aspects is effected in a TR: changed to 'desired'; seems clear that the desired order is profiling first followed by transactional aspect-->You
similar fashion.</para> configure any number of additional aspects in similar fashion.</para>
<para>Finally, find below some example configuration for effecting the <para>The following example effects the same setup as above, but uses
same setup as above, but using the purely XML declarative the purely XML declarative approach.</para>
approach.</para>
<programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt; <programlisting language="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans" &lt;beans xmlns="http://www.springframework.org/schema/beans"
...@@ -1970,17 +2009,15 @@ public class SimpleProfiler implements Ordered { ...@@ -1970,17 +2009,15 @@ public class SimpleProfiler implements Ordered {
&lt;/beans&gt;</programlisting> &lt;/beans&gt;</programlisting>
<para>The result of the above configuration will be a <para>The result of the above configuration will be a
<literal>'fooService'</literal> bean that has profiling and <literal>fooService</literal> bean that has profiling and transactional
transactional aspects applied to it <emphasis>in that order</emphasis>. aspects applied to it <emphasis>in that order</emphasis>. If you want
If we wanted the profiling advice to execute <emphasis>after</emphasis> the profiling advice to execute <emphasis>after</emphasis> the
the transactional advice on the way in, and <emphasis>before</emphasis> transactional advice on the way in, and <emphasis>before</emphasis> the
the transactional advice on the way out, then we would simply swap the transactional advice on the way out, then you simply swap the value of
value of the profiling aspect bean's <literal>'order'</literal> property the profiling aspect bean's <literal>order</literal> property so that it
such that it was higher than the transactional advice's order is higher than the transactional advice's order value.<!--Do you mean ...transactional advice *bean's* order value?--></para>
value.</para>
<para>You configure additional aspects in similar fashion.</para>
<para>The configuration of any number of additional aspects is achieved
in a similar fashion.</para>
</section> </section>
<section id="transaction-declarative-aspectj"> <section id="transaction-declarative-aspectj">
...@@ -1989,26 +2026,25 @@ public class SimpleProfiler implements Ordered { ...@@ -1989,26 +2026,25 @@ public class SimpleProfiler implements Ordered {
<para>It is also possible to use the Spring Framework's <para>It is also possible to use the Spring Framework's
<interfacename>@Transactional</interfacename> support outside of a <interfacename>@Transactional</interfacename> support outside of a
Spring container by means of an AspectJ aspect. To use this support you Spring container by means of an AspectJ aspect. To do so, you first
must first annotate your classes (and optionally your classes' methods annotate your classes (and optionally your classes' methods) with the
with the <interfacename>@Transactional</interfacename> annotation, and <interfacename>@Transactional</interfacename> annotation, and then you
then you must link (weave) your application with the link (weave) your application with the
<classname>org.springframework.transaction.aspectj.AnnotationTransactionAspect</classname> <classname>org.springframework.transaction.aspectj.AnnotationTransactionAspect</classname>
defined in the <filename defined in the <filename
class="libraryfile">spring-aspects.jar</filename> file. The aspect must class="libraryfile">spring-aspects.jar</filename> file. The aspect must
also be configured with a transaction manager. You could of course use also be configured with a transaction manager. You can of course use the
the Spring Framework's IoC container to take care of dependency Spring Framework's IoC container to take care of dependency-injecting
injecting the aspect. The simplest way to configure the transaction the aspect. The simplest way to configure the transaction management
management aspect is to use the aspect is to use the <literal>&lt;tx:annotation-driven/&gt;</literal>
<literal>'&lt;tx:annotation-driven/&gt;'</literal> element and specify element and specify the <literal>mode</literal> attribute to
the <literal>mode</literal> attribute to <literal>asepctj</literal> as <literal>asepctj</literal> as described in <xref
described in <xref linkend="transaction-declarative-annotations" />. linkend="transaction-declarative-annotations" />. Because we're focusing
Since we're focusing here on applications running outside of a Spring here on applications running outside of a Spring container, we'll show
container, we'll show you how to do it programmatically.</para> you how to do it programmatically.</para>
<note> <note>
<para>Prior to continuing, you may well want to read the previous <para>Prior to continuing, you may want to read <xref
sections entitled <xref
linkend="transaction-declarative-annotations" /> and <xref linkend="transaction-declarative-annotations" /> and <xref
linkend="aop" /> respectively.</para> linkend="aop" /> respectively.</para>
</note> </note>
...@@ -2040,9 +2076,9 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr ...@@ -2040,9 +2076,9 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr
<classname>AnnotationTransactionAspect</classname> you must either build <classname>AnnotationTransactionAspect</classname> you must either build
your application with AspectJ (see the <ulink your application with AspectJ (see the <ulink
url="http://www.eclipse.org/aspectj/doc/released/devguide/index.html">AspectJ url="http://www.eclipse.org/aspectj/doc/released/devguide/index.html">AspectJ
Development Guide</ulink>) or use load-time weaving. See the section Development Guide</ulink>) or use load-time weaving. See <xref
entitled <xref linkend="aop-aj-ltw" /> for a discussion of load-time linkend="aop-aj-ltw" /> for a discussion of load-time weaving with
weaving with AspectJ.</para> AspectJ.</para>
</section> </section>
</section> </section>
...@@ -2064,11 +2100,11 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr ...@@ -2064,11 +2100,11 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>If you are going to use programmatic transaction management, the <para>The Spring team generally recommends the
Spring team generally recommends using the <classname>TransactionTemplate</classname> for programmatic transaction
<classname>TransactionTemplate</classname>. The second approach is similar management. The second approach is similar to using the JTA
to using the JTA <interfacename>UserTransaction</interfacename> API <interfacename>UserTransaction</interfacename> API, although exception
(although exception handling is less cumbersome).</para> handling is less cumbersome.</para>
<section id="tx-prog-template"> <section id="tx-prog-template">
<title>Using the <classname>TransactionTemplate</classname></title> <title>Using the <classname>TransactionTemplate</classname></title>
...@@ -2082,20 +2118,20 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr ...@@ -2082,20 +2118,20 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr
what the developer wants to do.</para> what the developer wants to do.</para>
<note> <note>
<para>As you will immediately see in the examples that follow, using <para>As you will see in the examples that follow, using the
the <classname>TransactionTemplate</classname> absolutely couples you <classname>TransactionTemplate</classname> absolutely couples you to
to Spring's transaction infrastructure and APIs. Whether or not Spring's transaction infrastructure and APIs. Whether or not
programmatic transaction management is suitable for your development programmatic transaction management is suitable for your development
needs is a decision that you will have to make yourself.</para> needs is a decision that you will have to make yourself.</para>
</note> </note>
<para>Application code that must execute in a transactional context, and <para>Application code that must execute in a transactional context, and
that will use the <classname>TransactionTemplate</classname> explicitly, that will use the <classname>TransactionTemplate</classname> explicitly,
looks like this. You, as an application developer, will write a looks like the following. You, as an application developer, write a
<interfacename>TransactionCallback</interfacename> implementation <interfacename>TransactionCallback</interfacename> implementation
(typically expressed as an anonymous inner class) that will contain all (typically expressed as an anonymous inner class) that contains the code
of the code that you need to have execute in the context of a that you need to execute in the context of a transaction. You then pass
transaction. You will then pass an instance of your custom an instance of your custom
<interfacename>TransactionCallback</interfacename> to the <interfacename>TransactionCallback</interfacename> to the
<methodname>execute(..)</methodname> method exposed on the <methodname>execute(..)</methodname> method exposed on the
<classname>TransactionTemplate</classname>.</para> <classname>TransactionTemplate</classname>.</para>
...@@ -2124,8 +2160,8 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr ...@@ -2124,8 +2160,8 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr
}</programlisting> }</programlisting>
<para>If there is no return value, use the convenient <para>If there is no return value, use the convenient
<classname>TransactionCallbackWithoutResult</classname> class via an <classname>TransactionCallbackWithoutResult</classname> class with an
anonymous class like so:</para> anonymous class as follows:</para>
<programlisting language="java">transactionTemplate.execute(new <emphasis <programlisting language="java">transactionTemplate.execute(new <emphasis
role="bold">TransactionCallbackWithoutResult</emphasis>() { role="bold">TransactionCallbackWithoutResult</emphasis>() {
...@@ -2138,7 +2174,7 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr ...@@ -2138,7 +2174,7 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr
<para>Code within the callback can roll the transaction back by calling <para>Code within the callback can roll the transaction back by calling
the <literal>setRollbackOnly()</literal> method on the supplied the <literal>setRollbackOnly()</literal> method on the supplied
<interfacename>TransactionStatus</interfacename> object.</para> <interfacename>TransactionStatus</interfacename> object:</para>
<programlisting language="java">transactionTemplate.execute(new TransactionCallbackWithoutResult() { <programlisting language="java">transactionTemplate.execute(new TransactionCallbackWithoutResult() {
...@@ -2155,15 +2191,15 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr ...@@ -2155,15 +2191,15 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr
<section id="tx-prog-template-settings"> <section id="tx-prog-template-settings">
<title>Specifying transaction settings</title> <title>Specifying transaction settings</title>
<para>Transaction settings such as the propagation mode, the isolation <para>You can specify transaction settings such as the propagation
level, the timeout, and so forth can be set on the mode, the isolation level, the timeout, and so forth on the
<classname>TransactionTemplate</classname> either programmatically or <classname>TransactionTemplate</classname> either programmatically or
in configuration. <classname>TransactionTemplate</classname> instances in configuration. <classname>TransactionTemplate</classname> instances
by default have the <link by default have the <link
linkend="transaction-declarative-txadvice-settings">default linkend="transaction-declarative-txadvice-settings">default
transactional settings</link>. Find below an example of transactional settings</link>. The following example shows the
programmatically customizing the transactional settings for a specific programmatic customization of the transactional settings for a
<classname>TransactionTemplate</classname>.</para> specific <classname>TransactionTemplate:</classname></para>
<programlisting language="java">public class SimpleService implements Service { <programlisting language="java">public class SimpleService implements Service {
...@@ -2180,11 +2216,11 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr ...@@ -2180,11 +2216,11 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr
} }
}</programlisting> }</programlisting>
<para>Find below an example of defining a <para>The following example defines a
<classname>TransactionTemplate</classname> with some custom <classname>TransactionTemplate</classname> with some custom
transactional settings, using Spring XML configuration. The transactional settings, using Spring XML configuration. The
'<literal>sharedTransactionTemplate</literal>' can then be injected <literal>sharedTransactionTemplate</literal> can then be injected into
into as many services as are required.</para> as many services as are required.</para>
<programlisting language="xml">&lt;bean id="sharedTransactionTemplate" <programlisting language="xml">&lt;bean id="sharedTransactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate"&gt; class="org.springframework.transaction.support.TransactionTemplate"&gt;
...@@ -2198,12 +2234,11 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr ...@@ -2198,12 +2234,11 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr
instances do not maintain any conversational state. instances do not maintain any conversational state.
<classname>TransactionTemplate</classname> instances <classname>TransactionTemplate</classname> instances
<emphasis>do</emphasis> however maintain configuration state, so while a <emphasis>do</emphasis> however maintain configuration state, so while a
number of classes may choose to share a single instance of a number of classes may share a single instance of a
<classname>TransactionTemplate</classname>, if a class needed to use a <classname>TransactionTemplate</classname>, if a class needs to use a
<classname>TransactionTemplate</classname> with different settings (for <classname>TransactionTemplate</classname> with different settings (for
example, a different isolation level), then two distinct example, a different isolation level), then you need to create two
<classname>TransactionTemplate</classname> instances would need to be distinct <classname>TransactionTemplate</classname> instances.</para>
created and used.</para>
</section> </section>
<section id="transaction-programmatic-ptm"> <section id="transaction-programmatic-ptm">
...@@ -2213,11 +2248,11 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr ...@@ -2213,11 +2248,11 @@ AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager); </progr
<para>You can also use the <para>You can also use the
<interfacename>org.springframework.transaction.PlatformTransactionManager</interfacename> <interfacename>org.springframework.transaction.PlatformTransactionManager</interfacename>
directly to manage your transaction. Simply pass the implementation of directly to manage your transaction. Simply pass the implementation of
the <interfacename>PlatformTransactionManager</interfacename> you're the <interfacename>PlatformTransactionManager</interfacename> you are
using to your bean via a bean reference. Then, using the using to your bean through a bean reference. Then, using the
<interfacename>TransactionDefinition</interfacename> and <interfacename>TransactionDefinition</interfacename> and
<interfacename>TransactionStatus</interfacename> objects you can <interfacename>TransactionStatus</interfacename> objects you can
initiate transactions, rollback and commit.</para> initiate transactions, roll back, and commit.</para>
<programlisting language="java">DefaultTransactionDefinition def = new DefaultTransactionDefinition(); <programlisting language="java">DefaultTransactionDefinition def = new DefaultTransactionDefinition();
<lineannotation>// explicitly setting the transaction name is something that can only be done programmatically</lineannotation> <lineannotation>// explicitly setting the transaction name is something that can only be done programmatically</lineannotation>
...@@ -2270,27 +2305,27 @@ txManager.commit(status);</programlisting> ...@@ -2270,27 +2305,27 @@ txManager.commit(status);</programlisting>
location for the latter object, which varies by application server. Having location for the latter object, which varies by application server. Having
access to the JTA <interfacename>TransactionManager</interfacename> allows access to the JTA <interfacename>TransactionManager</interfacename> allows
for enhanced transaction semantics, in particular supporting transaction for enhanced transaction semantics, in particular supporting transaction
suspension. Please see the <classname>JtaTransactionManager</classname> suspension. See the <classname>JtaTransactionManager</classname> Javadocs
Javadocs for details.</para> for details.</para>
<para>Spring's <classname>JtaTransactionManager</classname> is the <para>Spring's <classname>JtaTransactionManager</classname> is the
standard choice when running on J2EE application servers, known to work on standard choice to run on Java EE application servers, and is known to
all common servers. Its advanced functionality such as transaction work on all common servers. Advanced functionality such as transaction
suspension is known to work on many servers as well - including GlassFish, suspension works on many servers as well -- including GlassFish, JBoss,
JBoss, Geronimo and Oracle OC4J - without any special configuration Geronimo, and Oracle OC4J -- without any special configuration required.
required. However, for fully supported transaction suspension and further However, for fully supported transaction suspension and further advanced
advanced integration, Spring ships special adapters for IBM WebSphere and integration, Spring ships special adapters for IBM WebSphere, BEA WebLogic
BEA WebLogic and also for Oracle OC4J. We'll discuss these adapters in the Server, and Oracle OC4J. These adapters iare discussed in the following
following sections.</para> sections.</para>
<para><emphasis>For standard scenarios, including WebLogic, WebSphere and <para><emphasis>For standard scenarios, including WebLogic Server,
OC4J, consider using the convenient WebSphere and OC4J, consider using the convenient
<literal>'&lt;tx:jta-transaction-manager/&gt;'</literal> configuration <literal>&lt;tx:jta-transaction-manager/&gt;</literal> configuration
element.</emphasis> This will automatically detect the underlying server element.</emphasis> When configured, this element automatically detects
and choose the best transaction manager available for the platform. This the underlying server and chooses the best transaction manager available
means that you won't have to configure server-specific adapter classes (as for the platform. This means that you won't have to configure
discussed in the following sections) explicitly; they will rather be server-specific adapter classes (as discussed in the following sections)
chosen automatically, with the standard explicitly; rather, they are chosen automatically, with the standard
<classname>JtaTransactionManager</classname> as default fallback.</para> <classname>JtaTransactionManager</classname> as default fallback.</para>
<section id="transaction-application-server-integration-websphere"> <section id="transaction-application-server-integration-websphere">
...@@ -2299,18 +2334,18 @@ txManager.commit(status);</programlisting> ...@@ -2299,18 +2334,18 @@ txManager.commit(status);</programlisting>
<para>On WebSphere 6.1.0.9 and above, the recommended Spring JTA <para>On WebSphere 6.1.0.9 and above, the recommended Spring JTA
transaction manager to use is transaction manager to use is
<classname>WebSphereUowTransactionManager</classname>. This special <classname>WebSphereUowTransactionManager</classname>. This special
adapter leverages IBM's <interfacename>UOWManager</interfacename> API adapter leverages IBM's <interfacename>UOWManager</interfacename> API,
which is available in WebSphere Application Server 6.0.2.19 or above and which is available in WebSphere Application Server 6.0.2.19 and later
6.1.0.9 or above. With this adapter, Spring-driven transaction and 6.1.0.9 and later. With this adapter, Spring-driven transaction
suspension (suspend/resume as initiated by suspension (suspend/resume as initiated by
<literal>PROPAGATION_REQUIRES_NEW</literal>) is officially supported by <literal>PROPAGATION_REQUIRES_NEW</literal>) is officially supported by
IBM!</para> IBM!</para>
</section> </section>
<section id="transaction-application-server-integration-weblogic"> <section id="transaction-application-server-integration-weblogic">
<title>BEA WebLogic</title> <title>BEA WebLogic Server</title>
<para>On WebLogic 9.0 or above, you will generally prefer to use the <para>On WebLogic Server 9.0 or above, you typically would use the
<classname>WebLogicJtaTransactionManager</classname> instead of the <classname>WebLogicJtaTransactionManager</classname> instead of the
stock <classname>JtaTransactionManager</classname> class. This special stock <classname>JtaTransactionManager</classname> class. This special
WebLogic-specific subclass of the normal WebLogic-specific subclass of the normal
...@@ -2324,17 +2359,17 @@ txManager.commit(status);</programlisting> ...@@ -2324,17 +2359,17 @@ txManager.commit(status);</programlisting>
<section id="transaction-application-server-integration-oc4j"> <section id="transaction-application-server-integration-oc4j">
<title>Oracle OC4J</title> <title>Oracle OC4J</title>
<para>Spring ships a special adapter class for OC4J 10.1.3 or above: <para>Spring ships a special adapter class for OC4J 10.1.3 or later
<classname>OC4JJtaTransactionManager</classname>. This is analogous to called <classname>OC4JJtaTransactionManager</classname>. This class is
the <classname>WebLogicJtaTransactionManager</classname> class discussed analogous to the <classname>WebLogicJtaTransactionManager</classname>
in the previous section, providing similar value-adds on OC4J: class discussed in the previous section, providing similar value-adds on
transaction names and per-transaction isolation levels.</para> OC4J: transaction names and per-transaction isolation levels.</para>
<para>Note that the full JTA functionality, including transaction <para>The full JTA functionality, including transaction suspension,
suspension, works fine with Spring's works fine with Spring's <classname>JtaTransactionManager</classname> on
<classname>JtaTransactionManager</classname> on OC4J as well. The OC4J as well. The special
special <classname>OC4JJtaTransactionManager</classname> adapter simply <classname>OC4JJtaTransactionManager</classname> adapter simply provides
provides value-adds beyond standard JTA.</para> value-adds beyond standard JTA.</para>
</section> </section>
</section> </section>
...@@ -2345,19 +2380,20 @@ txManager.commit(status);</programlisting> ...@@ -2345,19 +2380,20 @@ txManager.commit(status);</programlisting>
<title>Use of the wrong transaction manager for a specific <title>Use of the wrong transaction manager for a specific
<interfacename>DataSource</interfacename></title> <interfacename>DataSource</interfacename></title>
<para>You should take care to use the <emphasis>correct</emphasis> <para>Use the <emphasis>correct</emphasis>
<interfacename>PlatformTransactionManager</interfacename> implementation <interfacename>PlatformTransactionManager</interfacename> implementation
for their requirements. Used properly, the Spring Framework merely based on your choice of transactional technologies and requirements.<!--for *what* requirements? Identify *their* TR: clarified this a bit-->
provides a straightforward and portable abstraction. If you are using Used properly, the Spring Framework merely provides a straightforward
global transactions, you <emphasis>must</emphasis> use the and portable abstraction. If you are using global transactions, you
<emphasis>must</emphasis> use the
<classname>org.springframework.transaction.jta.JtaTransactionManager</classname> <classname>org.springframework.transaction.jta.JtaTransactionManager</classname>
class (or an <link class (or an <link
linkend="transaction-application-server-integration">application linkend="transaction-application-server-integration">application
server-specific subclass</link> of it) for all your transactional server-specific subclass</link> of it) for all your transactional
operations. Otherwise the transaction infrastructure will attempt to operations. Otherwise the transaction infrastructure attempts to perform
perform local transactions on resources such as container local transactions on resources such as container
<interfacename>DataSource</interfacename> instances. Such local <interfacename>DataSource</interfacename> 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.</para> them as errors.</para>
</section> </section>
</section> </section>
...@@ -2365,17 +2401,17 @@ txManager.commit(status);</programlisting> ...@@ -2365,17 +2401,17 @@ txManager.commit(status);</programlisting>
<section id="transaction-resources"> <section id="transaction-resources">
<title>Further Resources</title> <title>Further Resources</title>
<para>Find below links to further resources about the Spring Framework's <para>For more information about Spring Framework's transaction
transaction support.</para> support:</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para><ulink <para><ulink
url="http://www.javaworld.com/javaworld/jw-01-2009/jw-01-spring-transactions.html">Distributed url="http://www.javaworld.com/javaworld/jw-01-2009/jw-01-spring-transactions.html">Distributed
transactions in Spring, with and without XA</ulink> is a JavaWorld transactions in Spring, with and without XA</ulink> is a JavaWorld
feature where SpringSource's David Syer guides you through seven presentation in which SpringSource's David Syer guides you through
patterns for distributed transactions in Spring applications, three of seven patterns for distributed transactions in Spring applications,
them with XA and four without.</para> three of them with XA and four without.</para>
</listitem> </listitem>
<listitem> <listitem>
...@@ -2383,8 +2419,8 @@ txManager.commit(status);</programlisting> ...@@ -2383,8 +2419,8 @@ txManager.commit(status);</programlisting>
Transaction Design Strategies</ulink> is a book available from <ulink Transaction Design Strategies</ulink> is a book available from <ulink
url="http://www.infoq.com/">InfoQ</ulink> that provides a well-paced url="http://www.infoq.com/">InfoQ</ulink> that provides a well-paced
introduction to transactions in Java. It also includes side-by-side introduction to transactions in Java. It also includes side-by-side
examples of how to configure and use transactions using both the examples of how to configure and use transactions with both the Spring
Spring Framework and EJB3.</para> Framework and EJB3.</para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</section> </section>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册