Declarative transaction is a spring transaction strategy. The other strategies are programmatic transaction and local transaction. There are two ways to accomplish declarative transaction, through xml or through annotations. In this tutorial we look at xml based declarative transaction. The advantage of a declarative transaction is that all transaction demarcation happens through the xml and no extra coding needs to be done. It is also possible to declarative modify the transaction attributes without touching the code. Also changing the transaction managers is only a matter of modifying the transactionmanager bean. The disadvantage is that declarative transactions does not give a fine grained control over setting the transaction boundaries. However, in most cases, method level transaction settings suffice.
the tx namesapce (http://www.springframework.org/schema/tx) defines xml elements for setting up transactions. The main element is <tx:advice>. Define an advice using this element. Create a pointcut (see the tutorial on Aspects to understand pointcuts) to define which beans participate in the transaction. Wire the advice and pointcut into an advisor. The advice element has an attribute called transaction-manager. This can be set to the Transaction Manager. However, if there is a bean whose id is transactionManager then it will be used by default and need not be set in the advice. see the example below for more details. The advice element defines the transaction attributes of the methods using the <tx:method> element. The method element takes in a name which is the name of the method to which the transaction attributes are attached. It can use a wildcard character * (e.g. add* matches all methods starting with add). Please look at the tutorial on transaction
attributes to get a better understanding.
Sample Program Overview
The sample program demonstrates spring declarative transaction. Consider a banking system where amount is transferrred from one account to another account. Money is debited from the first account and credited to the second account. If a problem occurs then the transaction is rolled back. So in case, the amount is debited from the first account and before being credited to the second account, an error occurs then the transaction is rolled back and the money is credited back to the first account.
We will create the Account class with members as number and balance.
We will create the AccountDao class with database access methods .
We will create the AccountService class with members as accountDao.
We will create the DbUtil class with members as dataSource.
We will also create the spring-config.xml.
Finally, we will test our setup using TestSpringProgrammaticTransactions class which will load Spring context and get a reference to AccountService class. We will create two accounts and transfer money from one account to another.
Create the Account (see sample code below). This class represents a bank account.
Create members number and balance (see lines 5-6 below)
Create accessor methods for number and balance (see lines 18-32 below).
Create the debit() method to remove money from the account (see lines 34-36 below).
Create the credit() method to add money to the account (see lines 38-40 below).
Create the AccountDao (see sample code below). This represents the
Data Access Layer
through which data will be stored and retrieved from the database.
Note that AccountDao extends from JdbcDaoSupport (see line 10 below). This class uses JDBC based approach to interact with the database. (See
Spring JdbcDaoSupport Trail
for further details).
Create the insert() method to add a new Account (see lines 13-20 below).
Create the update() method to update balance in aa Account (see lines 22-30 below).
Create the select() method to fetch an Account from database (see lines 32-36 below).
Create the AccountRowMapper class to map JDBC
to Account class.
Create the AccountService (see sample code below).
Create members accountDao(see line 6 below)
Create accessor methods for accountDao (see lines 8-14 below).
Create the create() method to create a new account (see lines 16-18 below).
Create transferFunds() method (see lines 20-26 below). It is used to successfully transfer funds from one account to another.
Also create transferFundsException() method (see lines 28-36 below). It throws an Exception to simulate an error during fund transfer.
Note that there is no logic in this class to handle transactions which demonstrates declarative transaction management. This is a very important benefit of using declarative transactions where-in the business logic code need not be polluted with transaction handling related details.
Create the DbUtil (see sample code below). This class used only to create the necessary PERSON table in the database.
Create members dataSource (see line 11 below)
Create accessor methods for dataSource (see lines 13-19 below).
Create the initialize method and execute the ‘CREATE TABLE’ statement to create the PERSON table (see lines 21-32)
Create the spring-config.xml file (see below).
The dependency injection chart for the spring-config is as follows:
The key point to notice here is that the transaction is declaratively managed using Spring aspects through the
tag. The pointcut for the aspect is defined for methods of AccountService class (see line 31 below). This aspect refers to the transaction advice (see line 32 below) below.
The transaction advice is applicable for all methods whose names starts from ‘transferFunds’ (see line 37 below). The transaction should roll back when any exception occurs (see line 38 below). The transaction advice refers to Spring’s transaction manager (see line 35 below). This demonstrates the usage of declarative transaction management.
The transaction manager is defined using
class (see lines 42-45 below).
The database parameters defined for dataSource bean (see lines 47-53 below) correspond to the HyperSQL in-memory database.
We also declare the dbUtil bean which initializes the database by creating the ACCOUNT table with NUMBER and BALANCE columns (see lines 55-59 below).
Finally, we need a java program to test our setup.This is done by TestSpringDeclarativeTransactions (see source code below).
We need to tell Spring framework to use the ‘spring-config.xml’ to load our beans (see line 13 below).
We get the reference to AccountService class through Spring using the bean name ‘accountService’ (see line 14 below).
Create two new accounts with account numbers ‘ACC01’ and ‘ACC02’ (see lines 17-24 below).
Transfer 50 dollars from account ‘ACC01’ to account ‘ACC02’ using accountService.transferFunds() method. (see lines 28-33 below). This demonstrates the scenario where amount is successfully transferred from one account to another.
Again transfer 10 dollars from account ‘ACC01’ to account ‘ACC02’ using accountService.transferFundsException() method. (see lines 38-49 below). In this case an exception occurs during fund transfer and the entire operations fails. Note that the balance amounts in accounts remains unaltered. This demonstrates the usage of declarative transactions to rollback an operation when an error occurs.
This sample program has been packaged as a jar installer which will copy the source code (along with all necessary dependencies) on your machine and automatically run the program for you as shown in the steps below. To run the sample program, you only need Java Runtime Environment (JRE) on your machine and nothing else.
(Alternatively you can go the folder containing the springdeclarativetransactions-installer.jar and execute the jar using
java -jar springdeclarativetransactions-installer.jar
This source code for this program is downloaded in the folder specified by you (say, C:\Temp) as an eclipse project called
. All the required libraries have also been downloaded and placed in the same location. You can open this project from Eclipe IDE and directly browse the source code. See below for details of the project structure.