Pre-requisite trails
Concept Overview
There are predominantly three transaction strategies for spring based transactions – Local Transactions, programmatic transactions and declarative transactions. In this tutorial we look at programmatic transactions.
Programmatic transactions give a greater control to the user in setting up the transaction boundaries. It is possible to set up transaction boundaries to a part of the code (you will see later see that declarative transaction generally set transaction boundaries at method level). However, the transaction management code needs to be inserted into the program logic and hence is intrusive. Spring provides a template for programmatic transaction.
The template class is org.springframework.transaction.support.TransactionTemplate. It uses default Transaction Attributes (PROPAGATION_REQUIRED, ISOLATION_DEFAULT, TIMEOUT_DEFAULT, readOnly=false). It needs to be injected with a transaction manager, which should be an implementation of
PlatFormTransactionManager (e.g. DataSourceTransactionManager). To change the transaction attributes use the following constructor.
public TransactionTemplate(PlatformTransactionManager transactionManager, TransactionDefinition transactionDefinition)
Use the DefaultTransactionDefinition and set the transaction attributes there.
The main method of the transaction template is the execute method with the following signature
publicT execute(TransactionCallback action) throws TransactionException
The TransactionCallback is a callback method that handles the actual transaction code. Please see the example below for more details. The transaction manager is configured as a bean in the application context and passed to the transactiontemplate.
Sample Program Overview
The sample program demonstrates Spring programmatic 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 and transactionTemplate.
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.
- cglib.jar
- commons-logging.jar
- hsqldb.jar
- log4j.jar
- org.springframework.aop.jar
- org.springframework.asm.jar
- org.springframework.beans.jar
- org.springframework.context.jar
- org.springframework.context.support.jar
- org.springframework.core.jar
- org.springframework.expression.jar
- org.springframework.jdbc.jar
- org.springframework.transaction.jar
Create the Account (see sample code below). This 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
ResultSet
to Account class.
Create the AccountService (see sample code below).
Create members accountDao and transactionTemplate (see lines 9-10 below)
Create accessor methods for accountDao and transactionTemplate(see lines 12-26 below).
Create transferFunds() method (see lines 32-46 below). It is used to successfully transfer funds from one account to another.
It uses TransactionTemplate().execute() method to programmatically manage transactions (see line 50 below).
Also create transferFundsException() method (see lines 48-72 below). It shows that when an Exception occurs during a transaction, all the changes are rolled back.
Throw an Exception to simulate the scenario that an error occurs during funds transfer (see line 60 below).
Note that the exception is caught and transaction is rolled back using TransactionStatus.setRollbackOnly() (see line 66 below). This ensures that all changes made to the database until that point are rolled back and demonstrates programmatic transaction management.
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:
Note how
DataSourceTransactionManager
is injected into
TransactionTemplate
which in turn is injected into
AccountDao
. This enables programmatic management of transactions in AccountDao.
Finally, we need a java program to test our setup.This is done by TestSpringProgrammaticTransactions (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 case 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-42 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 programmatic 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 springprogrammatictransactions-installer.jar and execute the jar using
java -jar springprogrammatictransactions-installer.jar
command)
This source code for this program is downloaded in the folder specified by you (say, C:\Temp) as an eclipse project called
springprogrammatictransactions
. 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.