Using transactions in JDBC BC

A while back there was a discussion about implementing transactions in components in JBI environment. I would like to share today how we implemented transactions in case of JDBC BC.

In any component we have 2 ways of communication, Outbound and Inbound. If the component sends out the message from NMR to the external system its outbound and if the component receives the message from the external system its inbound. JDBC supports transactions in both outbound as well as inbound cases.

Transaction enlistment (Implicit and Explicit): open-esb uses internally Transaction Manager from the Application server. So the call componentContext.getTransactionManager() returns the TM from the Glassfish implementation. When we are talking about Transactions its basically an agreement amongst the Transaction Manager of the AppServer, Resource Manager of the Resource under consideration and the connection pool(s) of the resource implemented by AppServer as in case of default JDBC and JMS or provided by any 3 rd party library. For an background on Transaction Handling in open-esb visit http://blogs.sun.com/narayanaa/entry/implementing_transactions_in_jbi_components. In cases of the external systems where we do not have XAResource implementation the component needs to implement the same and it can choose to implement manual enlistment. In cases like JDBC where in the Driver has the provision of creation of XADataSource which internally uses XAResource, component does not need to enlist the XAResource explicitly, since the AppServer after the creation of the XADatasource will take care of the enlistment automatically.

JDBC BC utilizes automatic enlistment of the resources. One thing we need to remember is even when we create the XADataSource for creation of the connection pool the XSDataSource is not available as XADataSource outside the AppServer boundary in JBI Container, rather the same is only available as normal DataSource. But despite this DataSource can participate in transactions as in case of XADataSource. The JDBC BC utilizes the same for participating in XATransaction. The user if he wants that the JDBC BC be participating in the XATransaction has to set the Transaction property as shown below during the design time:



This property has to be set in the WSDL in the Binding section. The Inbound  JDBC operation utilize this property during the runtime to participate in XATransaction. The outbound does not need to have this property since it only checks the property one the message exchange MessageExchange.JTA_TRANSACTION_PROPERTY_NAME, for validating whether transaction is set and participates in the transaction if this property is set. The Data source that is pointed from the AppServer from which the WSDL is generated must actually be created as XADataSource from with in the AppServer. This property is set in AppServer as shown in figure from the AppServer's Admin Console:

1. Create Connection Pool based on XADataSource and give all the necessary connection parameters required for the same while creation in the 2 nd step while creation of the XADS.



  1. Create JDBC Resource from the Connection Pool thus created:





What happens under the hood?

Outbound: The Binding component gets the Transaction Manager from the component context. Since BPEL sends the transactional context the component checks for the transactional property and sets connection.setAutoCommit(false); and then resumes the transaction.

mTxManager = (TransactionManager) context.getTransactionManager();

transaction=(Transaction)inonly.getProperty(MessageExchange.JTA_TRANSACTION_PROPERTY_NAME);

if (transaction != null) {

    mTxManager.resume(transaction);

}

// get the connection from the endpoint bean

connection = getDatabaseConnection(epb);

if(transaction != null) {

    connection.setAutoCommit(false);

}

The catch bloc contains the code if the Done status has not come from processing of the message :

catch (final Exception ex) {

success = false;

mLogger.log(Level.WARNING,

OutboundMessageProcessor.mMessages.getString("OMP_Failed_writing"), ex);

inonly.setError(ex);

if (transaction != null) {

transaction.setRollbackOnly();

}

}


after the message processing and setting the message exchange the transaction is suspended.


if (transaction != null) {

mTxManager.suspend();

}



you can see the code by checking out and looking at com.sun.jbi.jdbcbc.OutboundMessageProcessor


Inbound: In case of Inbound the JDBC BC initiates the transaction and either commits or rollbacks the transaction based on the message exchange property.


mTxManager = (TransactionManager) context.getTransactionManager();


if (mXAEnabled.equalsIgnoreCase("XATransaction")) {

mTxManager.begin();

}


connection = getDatabaseConnection(jndiName);

Transaction tx = mTxManager.getTransaction();


if (rs != null) {

final JDBCNormalizer normalizer = new JDBCNormalizer();

inMsg = normalizer.normalizeSelectInbound(rs, exchange, meta, epb, mPKName);


final List tempList = epb.getProcessList();

if (!(tempList.isEmpty())) {

// mTxHelper.handleInbound(exchange);

exchange.setMessage(inMsg, "in");

if (tx != null) {

mExchange.setProperty(MessageExchange.JTA_TRANSACTION_PROPERTY_NAME, tx);

mTxManager.suspend();

}

mChannel.send(exchange);

epb.getEndpointStatus().incrementSentRequests();

InboundMessageProcessor.mInboundExchanges.put(exchangeId, new ListenerMeta(

System.currentTimeMillis(), this));

} else {

try {

tx.commit();

} catch (Exception ex) {

mLogger.log(Level.SEVERE, "IMP_XA_TX_COMMIT_FAILED", new Object[] { "commit", ex });

throw ex;

}

}

// mTableExistsFlag = new Object();

}


catch (final Exception ex) {

mLogger.log(Level.SEVERE, "Exception in processing send only. ", ex);

Transaction tx = mTxManager.getTransaction();

if(tx != null ) {

tx.rollback();

}

}


You can have a look at the code in com.sun.jbi.jdbcbc.InboundMessageProcessor;

I tried to give you a glimpse of the transaction implementation in JDBC BC which utilizes automatic enlistment. MSMQ BC in contrast utilizes manual enlistment, since though the MSMQ has Resource manager and MTS has its own way of doing the things MSMQ BC has to access the Resources the JTA way and has to implement the transactional APIs in Java and it internally utilizes the JNI calls for talking the MS environment.

Having said that I have to talk about implementation of Manual enlistment and the CRMP in the in-out pattern of implementation. I will talking about them in future.

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

I was part of Sun R&D in Java CAPS and later Glassfish ESB. I moved from R&D to Consulting. I am currently working as a Solution Architect in Oracle Consulting Services (India). I was sharing my experience w.r.t. Java CAPS and other technologies during Sun period. Now in Oracle world I share my experiences with Oracle FMW product line as well as other Oracle Technologies and products.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today