LAMS uses JTA based transaction management and JNDI datasources. JTA based transaction management was selected over the Spring Hibernate based transaction manager for two main reasons:
- Supports the use of transactions over multiple Hibernate sessions.
- Allows data to be stored in different locations, for example we may decide to split the core tables and the tools tables into different databases.
Transactions management is done using Spring. All service objects should use the transactionManager bean defined in lams.jar. This is needed to tie all the transactions together.
All service objects should declare the transaction propogation requirements in the Spring bean definition. Don't forget that the default Spring implementation is to rollback on Runtime exceptions only - if your code throws Checked Exceptions then these also need to be defined if you want them to trigger a rollback. If you do set up the transaction to rollback on checked exceptions, then please document this clearly - so that users of your class know that the transaction will be marked
as rollback only and not try to continue the transaction.
Do not use ISOLATION_READ_COMMITTED in your Spring transaction definitions. This option is not supported by the JTA manager. The database itself should be configured to use read committed isolation. See Database Conventions and Datasources for more details.
MySQL and 2 Phase Commit
MySQL 5.x supports XA protocols and these protocols are required for the JBOSS JTA support to correctly commit database changes. But we have been unable to turn on the MySQL XA support as we get an exception thrown after a few transactions.
Therefore currently there is no guarantee that all the classes will rollback properly when a database error occurs. However if this situation arises, it should be no worse than using the HibernateTransactionManager. We hope in the future to be able to turn on the MySQL XA support.
Note: We have not been able to make the transaction management fail, even modifying the database part way through the Java transaction.
Why not use HibernateTransactionManager?
The simplest way to use Spring and Hibernate is to use org.springframework.orm.hibernate3.HibernateTransactionManager. However this manager is tied to a single Hibernate session (org.springframework.orm.hibernate3.LocalSessionFactoryBean) and so we end up with one transaction manager for the core classes, and another transaction manager for each tool.
When the tool, the content repostitory and the other core functionality interact, there is a chance of inconsistent data occuring in the database. For example assume a tool calls the content repository to store a file. After the call to the content repository is completed, the tool creates or updates its own data objects. Should the call to the database to store the tool data objects fail, or if the tool throws an exception based after calling the content repository, then the tool data will not be stored but the content repository data will have be written to the database. In many cases, it will only result in some unnecessary data being written to the databas. But it has the potential to be a serious issue. Hence the selection of the org.springframework.transaction.jta.JtaTransactionManager.