Transaction using JTA and POJO (jdbc )as DAO implementation in traditional way:
JDBC transactions are not always suitable for some enterprise applications needs. If the transactions span multiple DAOs or multiple databases (or external resources), the transactions sometimes have to be demarcated with JTA and is seperated from DAO. The caller is responsible for demarcating the transaction, and the DAO participates in a global transaction.
The transaction managements in these cases are distributed in nature. The underlying transaction managements (resource manager) have to coordinate together to satisfy the transaction boundary you defined in the application.
The application we are developing need to support concurrently conecting to different databases using different DAO implementations and external applications using JCA. One big problem we are facing is transaction propagation. We also want to fine-grained control some transaction operations.
The development context is that we have session beans,mdb plus POJO (jdbc) as dao implementation. cause, jdbc using connection object to define the transaction, but we define the transaction boundaries in session bean. So, we need the ejb container transaction manager coordinates with jdbc counterpart. The solution for this is that we define XA data source and using txconnection object in jdbc codes ,instead of general jdbc connection object. DO NOT DEFINE any transaction boundaries or commit, rollback inside jdbc codes.
We've tried to another approach to pass Transaction Context as parameter to POJO DAO, but it's too complex and lot of low level coding and control(Thread Save), Also there are too many restrictions, and we eventually gave up.
Some codes examples for the simple and practical solution on this problem:
public void createOrderWithDAO_JTA() {
Exception caught = null;
/*
* This DAO expects the caller to demarcate the transaction using JTA. This DAO access database1.
*/
WarehouseDAO dao1 = MyDAOFactory.getWarehouseJTA_DAO();
/*
* This DAO expects the caller to demarcate the transaction using JTA. This DAO access database2.
*/
OrderDAO dao2 = MyDAOFactory.getOrderJTA_DAO();
/*
* This publisher publishes messages to a JMS Topic and expects the caller to demarcate the transaction.
* When creating session, make sure it is transacted.
*/
MessagePublisher publisher = null;
UserTransaction utx = ResourceManager.getUserTransaction();
try {
/*
* Execute the transaction.
* This transaction accesses three resources:
* 1) a JMS Topic.
* 2) two different JDBC DataSources.
*/
utx.begin();
dao2.createOrder(....);
dao1.updateWareHouse(....);
publisher.publishTextMessage("Order Confirm Message....");
utx.commit();
} catch (Exception ex) {
log.error(ex);
caught = ex;
if (utx != null) {
try {
utx.rollback();
} catch (SystemException sysex) {
log.error(sysex);
}
}
} finally {
if (dao != null) {
dao.close();
dao = null;
}
if (publisher != null) {
publisher.close();
publisher = null;
}
if (caught != null) {
throw new DAORuntimeException(caught);
}
}
}
.....
In dao implementation:
conn = DBUtil.getXADBConnection();
.....
I think this is a painful solution (especially for complex applications) and not attractive at all. but Spring address this kind of problem in an elegant way(like EJB CMT).From the codes as jove shown, i can sense the advantage of Spring framework, though it seems Spring currently does not support multiple database or external resource (distributed) transaction at the moment.