By Neeraj Verma 2008-11-14
The following case studies test the transaction capabilities of the spring framework’s DataSourceTransactionManager.
1. Create a model and make one of
the methods transactional PROPAGATION_REQUIRED. Call the method and throw an
exception.
-> This
should roll back the database transaction.
Description:
This case study has a TestModel calling a DataManager that is transaction enabled. The data manager’s method is coded to throw a RuntimeException after executing the insert statement.
Expected Results
The expected result is that the transaction will be rolled back since the datamanager’s method is transactional.
Summary of results:
Database changes were rolled back.
TestModel
public class TestModelImpl implements TestModel {
private OrgPeopleDataManager orgPeopleDataManager;
/* (non-Javadoc)
* @see orgcommon.TestModel#initializeCountries()
*/
public void initializeCountries() {
orgPeopleDataManager.initializeCountries();
}
public void deleteAllCountries() {
orgPeopleDataManager.deleteAllCountries();
}
OrgPeopleDataManager
public class JdbcOrgPeopleDataManager implements OrgPeopleDataManager {
private JdbcTemplate jdbcTemplate;
public void deleteAllCountries() {
jdbcTemplate.update("delete from country");
}
public void initializeCountries() {
jdbcTemplate.update("insert into country values (1, 'test country', 'Test Country')");
throw new RuntimeException("test");
}
Test Case
package orgcommon;
public class AddCountryTest extends BaseTestCase {
public void testAddCountry() {
TestModel testModel = (TestModel) context.getBean("testModel");
testModel.deleteAllCountries();
testModel.initializeCountries();
}
}
Configuration
<bean name="orgPeopleDataManagerTarget" class="orgpeople.JdbcOrgPeopleDataManager"/>
<bean id="orgPeopleDataManager"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref bean="transactionManager"/></property>
<property name="target"><ref bean="orgPeopleDataManagerTarget"/></property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean name="testModel" class="orgcommon.TestModelImpl">
<property name="orgPeopleDataManager" ref="orgPeopleDataManager"/>
</bean>
Log output
0 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Using transaction
object
[org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@c4bc34]
0 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new
transaction with name [orgpeople.OrgPeopleDataManager.deleteAllCountries]:
PROPAGATION_REQUIRED,ISOLATION_DEFAULT
157
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Acquired Connection
[com.mysql.jdbc.Connection@91f005] for JDBC transaction
157
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection
[com.mysql.jdbc.Connection@91f005] to manual commit
157
[main] DEBUG org.springframework.jdbc.core.JdbcTemplate - Executing SQL update [delete from country]
172
[main] DEBUG org.springframework.jdbc.core.JdbcTemplate - SQL update affected 0 rows
172
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering beforeCommit
synchronization
172
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering beforeCompletion
synchronization
172
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Initiating transaction commit
172
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Committing JDBC transaction on Connection
[com.mysql.jdbc.Connection@91f005]
172
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering afterCommit
synchronization
172
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering afterCompletion
synchronization
172
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection
[com.mysql.jdbc.Connection@91f005] after transaction
172
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Using transaction object
[org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@1afb0c7]
172
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [orgpeople.OrgPeopleDataManager.initializeCountries]:
PROPAGATION_REQUIRED,ISOLATION_DEFAULT
328
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Acquired Connection
[com.mysql.jdbc.Connection@2515] for JDBC transaction
328
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection
[com.mysql.jdbc.Connection@2515] to manual commit
328
[main] DEBUG org.springframework.jdbc.core.JdbcTemplate - Executing SQL update [insert into country
values (1, 'test country', 'Test Country')]
328
[main] DEBUG org.springframework.jdbc.core.JdbcTemplate - SQL update affected 1 rows
328
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering beforeCompletion
synchronization
328
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Initiating transaction rollback
328
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Rolling back JDBC transaction on Connection
[com.mysql.jdbc.Connection@2515]
609
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering afterCompletion
synchronization
609
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection
[com.mysql.jdbc.Connection@2515] after transaction
Try the same as above but the exception will be in the TestModel
TestModel
public class TestModelImpl implements TestModel {
private OrgPeopleDataManager orgPeopleDataManager;
public void initializeCountries() {
orgPeopleDataManager.initializeCountries();
throw new RuntimeException("test");
}
}
Expected Results
Database connection will not rollback
Actual Results
Database connection did not rollback.
In this case study we will instead make the testModel’s method transactional.
Expected Result
The transaction will roll back since the TestModel’s method was transactional.
Summary of results
It actually was transactional
Configuration
<bean name="orgPeopleDataManager" class="orgpeople.JdbcOrgPeopleDataManager"/>
<bean id="testModel"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref bean="transactionManager"/></property>
<property name="target"><ref bean="testModelTarget"/></property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean name="testModelTarget" class="orgcommon.TestModelImpl">
<property name="orgPeopleDataManager" ref="orgPeopleDataManager"/>
</bean>
Log output
0 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Using transaction
object [org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@1541147]
0 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new
transaction with name [orgcommon.TestModel.deleteAllCountries]:
PROPAGATION_REQUIRED,ISOLATION_DEFAULT
157 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Acquired Connection
[com.mysql.jdbc.Connection@18e18a3] for JDBC transaction
157 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection
[com.mysql.jdbc.Connection@18e18a3] to manual commit
157 [main]
DEBUG org.springframework.jdbc.core.JdbcTemplate - Executing SQL update [delete from country]
157 [main]
DEBUG org.springframework.jdbc.core.JdbcTemplate - SQL update affected 0 rows
173 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering beforeCommit
synchronization
173 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering beforeCompletion
synchronization
173 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Initiating transaction commit
173 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Committing JDBC transaction on Connection
[com.mysql.jdbc.Connection@18e18a3]
173 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering afterCommit
synchronization
173 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering afterCompletion
synchronization
173 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection
[com.mysql.jdbc.Connection@18e18a3] after transaction
173 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Using transaction object
[org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@18041e0]
173 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [orgcommon.TestModel.initializeCountries]:
PROPAGATION_REQUIRED,ISOLATION_DEFAULT
329 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Acquired Connection
[com.mysql.jdbc.Connection@278e83] for JDBC transaction
329 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection
[com.mysql.jdbc.Connection@278e83] to manual commit
329 [main]
DEBUG org.springframework.jdbc.core.JdbcTemplate - Executing SQL update [insert into country
values (1, 'test country', 'Test Country')]
329 [main]
DEBUG org.springframework.jdbc.core.JdbcTemplate - SQL update affected 1 rows
329 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering beforeCompletion
synchronization
329 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Initiating transaction rollback
329 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Rolling back JDBC transaction on Connection
[com.mysql.jdbc.Connection@278e83]
376 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering afterCompletion
synchronization
376 [main]
DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection
[com.mysql.jdbc.Connection@278e83] after transaction
TestModel
is transactional. Data Manager’s method does not support transactions (PROPAGATION_NOT_SUPPORTED).
Expected
result:
After throwing
an exception in the outer method, the inner method should commit and the outer
method should rollback.
Summery of
results:
Performed as expected.
<bean name="orgPeopleDataManagerTarget" class="orgpeople.JdbcOrgPeopleDataManager"/>
<bean name="testModelTarget" class="orgcommon.TestModelImpl">
<property name="orgPeopleDataManager" ref="orgPeopleDataManager"/>
</bean>
<bean id="orgPeopleDataManager"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref bean="transactionManager"/></property>
<property name="target"><ref bean="orgPeopleDataManagerTarget"/></property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_NOT_SUPPORTED</prop>
</props>
</property>
</bean>
<bean id="testModel"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref bean="transactionManager"/></property>
<property name="target"><ref bean="testModelTarget"/></property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
Log of results
0 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Using transaction object [org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@1198ff2]
0 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [orgcommon.TestModel.deleteAllCountries]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
157 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Acquired Connection [com.mysql.jdbc.Connection@3a0ab1] for JDBC transaction
157 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection [com.mysql.jdbc.Connection@3a0ab1] to manual commit
157 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Using transaction object [org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@107108e]
157 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Suspending current transaction
157 [main] DEBUG org.springframework.jdbc.core.JdbcTemplate - Executing SQL update [delete from country]
376 [main] DEBUG org.springframework.jdbc.core.JdbcTemplate - SQL update affected 1 rows
376 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering beforeCommit synchronization
376 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering beforeCompletion synchronization
391 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering afterCommit synchronization
391 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering afterCompletion synchronization
391 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Resuming suspended transaction
391 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering beforeCommit synchronization
391 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering beforeCompletion synchronization
391 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Initiating transaction commit
391 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Committing JDBC transaction on Connection [com.mysql.jdbc.Connection@3a0ab1]
391 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering afterCommit synchronization
391 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering afterCompletion synchronization
391 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection [com.mysql.jdbc.Connection@3a0ab1] after transaction
391 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Using transaction object [org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@166f9b9]
391 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [orgcommon.TestModel.initializeCountries]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
547 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Acquired Connection [com.mysql.jdbc.Connection@1fb3211] for JDBC transaction
547 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection [com.mysql.jdbc.Connection@1fb3211] to manual commit
547 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Using transaction object [org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@940b84]
547
[main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Suspending current
transaction
547 [main] DEBUG org.springframework.jdbc.core.JdbcTemplate - Executing SQL update [insert into country values (1, 'test country', 'Test Country')]
703 [main] DEBUG org.springframework.jdbc.core.JdbcTemplate - SQL update affected 1 rows
703 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering beforeCommit synchronization
703 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering beforeCompletion synchronization
703 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering afterCommit synchronization
703 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering afterCompletion synchronization
703 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Resuming suspended transaction
703 [main] DEBUG org.springframework.jdbc.core.JdbcTemplate - Executing SQL update [insert into country values (2, 'test country outside', 'Test Country outside')]
703 [main] DEBUG org.springframework.jdbc.core.JdbcTemplate - SQL update affected 1 rows
703 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering beforeCompletion synchronization
703 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Initiating transaction rollback
703 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Rolling back JDBC transaction on Connection [com.mysql.jdbc.Connection@1fb3211]
719 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Triggering afterCompletion synchronization
719 [main] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager - Releasing JDBC Connection [com.mysql.jdbc.Connection@1fb3211] after transaction