Implementing Transactions in JBI Components

Implementing Transactions in Binding Components in open-esb in Glassfish

The JBI specification though says that the JBI component can get the Transaction Manager from the component context it does not say anything about how does the components or the JBI runtime should support transactions. The JBI container implementation is free to choose the way it can give the Transaction Manager handle to the component and the component is free to implement the way it wants to participate in a distributed transaction.

Whenever we talk about transactions one thing that comes to our mind is atomicity of the set of operations that falls with in a boundary. Atomicity of the operations is achieved by ACID properties (Atomic - either full or null, C – Consistency, I - Isolation D – Durable) with in the boundary that is Transactional Context. Transactional Context is the association between the Transactional Operations on the resources and components that are invoking the transactions. Hence the Transactional Context encompasses an over seer of the Transactional Context (Transactional Manager), who can orchestrate the transaction, the resources represented by their managers, and the application components that are participating the transaction. There must be a set contract amongst the players in the transactional context so that the ATOMicity is achieved. The transaction can be depicted in a pictorial form as below:




When we are in a distributed transactional environment there would be multiple threads that would be participating in a transaction and they would be sharing a transactional context. There will be one Transaction Manager for over seeing the transaction. The above model is followed by a consortium of global vendors of different kinds of resources for interoperability and transactional context propagation in the form of X-Open distributed Transaction propagation model. This model consists of the following 5 component contracts amongst the participating components.

  • TX – Application-Transaction Manager contract

  • AX/XA – Transaction Manager-Resource Manager contract

  • XA+ -- Different Transaction Managers domains participating via communication thru' Resource Managers

  • TXRPC – Application Programming with in Global Transactions

  • CRM-OSI-TP – Resource Manager and OSI Transaction Processing Service.

Normal XA Transactions involves 2 phase commit protocol in which during the first phase the resource managers enlist the transactions and once all the Resources that are participating in the transactions are enlisted, the TM calls for 2 nd phase on the transaction which will call for committing the transaction. If by any chance there is a failure before all the resources go into a prepare state, while recovery Transaction Manager calls rollback on the transaction. If the failure happens after the prepare since all the resources are already prepared Transaction Manager calls for a commit. The heuristics are taken into consideration while commit/rollback.

For each of the Actors there following is the description for specified interfaces:

  1. TX Interface: This is an interface between the application program and the transaction manager, and is implemented by the transaction manager. This interface provides transaction demarcation services, by allowing the application programs to bound transactional operations within global transactions. This interface consists of the following functions:

 

  1. XA Interface: A bidirectional interface between resource managers and transaction managers. This interface specifies two sets of functions. The first set, called as xa_\*() functions are implemented by resource managers for use by the transaction manager. The second set of functions, called as ax_\*() functions, are implemented by the transaction manager for use by resource managers.

Since distributed transactions involve disparate systems (Java based, CORBA OTS based and MTS), understanding some details about each of this will help in implementing transactions for that particular kind of component.

There are 2 ways of Transaction Handling in JBI Components. This post concentrates only on Glassfish with open-esb implementation and does not talk much about interoperability.

JBI exchanges can convey J2EE transaction information between the requestor of a JBI service and the provider of the JBI service. This comes in the form of a method on MessageExchange.setProperty(MessageExchange.JTA_TRANSACTION_PROPERTY_NAME, transaction) and the complementary MessageExchange.getProperty(). When set by the requestor, before the first DeliveryChannel.send(), this property can be retrieved by either side.

  1. Use the Application Server environment for handling transactions: This gives the user the flexibility that the AppServer will enlist/delist the transactions for you. For this the component should use the resources that are there in the domain.xml. We only need to suspend and resume the transaction since there is a thread swap apart from commit/rollback in case if we are inbound and are initiating transaction. In this case since the resource is enlisted there in the domain.xml the recovery mechanism of the AppServer will take care of the recovery of the resource and the BC need not bother about the recovery. This mandates to find out a way for modification of the domain.xml for the binding component or use asadmin console for having the resource in domain.xml in case of Sun Application Server. In case of JBoss this might have to do with \*-ds.xml and in other cases of Weblogic/ WS it might be tough since this depends on TM's and the XA enabled resources availability from outside the AppServer context.  

  2. Use Manual enlisting/delisting: This version is for where we choose to have manual enlisting and delisting of the transactions. The other things like suspend/resume and commit/rollback would be the same as above. Manual enlisting and delisting has the advantage of BC implementing that portion but then how does the recovery happen and where do we store the resource for recovery? For the purpose of recovery there are 2 interfaces 1 implemented by the Application Server and the other by the NMR to give a hook for the component to enlist with the TM so that the recovery can be handled.

The new interface RecoveryResourceRegistry, is exposed by AppServer to obtain XAResource objects from JBI components for recovery. During recovery, application server will use this interface to retrieve the XAResource objects from JBI components. This is a singleton registry class, that will be used by jbi lifecycle to register a listener (RecoveryResourceListener) class.

(com.sun.enterprise.resource.RecoveryResourceRegistry)

         public class RecoveryResourceRegistry {
              public static RecoveryResourceRegistry getInstance();
              public void addRecoveryResourceListener(com.sun.enterprise.resource.
              RecoveryResourceListener);
              public java.util.Set getListeners();
         }

The NMR uses the following interface for the purpose
(
com.sun.enterprise.resource.RecoveryResourceListener)

public interface RecoveryResourceListener{
    
javax.transaction.xa.XAResource[] getXAResources();
    
void recoveryStarted();
         void recoveryCompleted();
 }

Appserver will use the RecoveryResourceListener instance from the jbi implementation to obtain the XAResource objects for recovery (In our case SunASJBIFramework extends com.sun.jbi.framework.JBIFramework implements RecoveryResourceListener). It also gives two recovery life cycle operations that can potentially be used for some house keeping operations.

The method getXAResources() from the SunASJBIFramework will give the XAResources the BC registered with the com.sun.jbi.framework.ComponentContext. In fact the ComponentContext will in turn call the deliveryChannel.registerXAResource(XAResource) which will call internally com.sun.jbi.messaging.MessageService.addXAResouce(XAResource). These added XAResources are utilized during recovery by the SunASJBIFramework.

public javax.transaction.xa.XAResource[] getXAResources(){
    try{
        // Generate the equivalent of a PREPARE event.

                super.prepare();
    }
catch (javax.jbi.JBIException jEx){

    }
    // At this point we should have collected all local XAResources declared by JBI Components.
    //The environment is EnvironmentContext implements com.sun.jbi.EnvironmentContext and the

          // NormalizedMessageService is the com.sun.jbi.messaging.MessagingService

    return (getEnvironment().getNormalizedMessageService().getXAResources());
}

Potential Issues with each of the implementation:

  1. Using AppServer environment:

    1. Advantages:

      1. User does not need to worry about the enlistment/delistment.

      2. User does not need to worry about the recovery since the resource is available in the domain.xml

    2. Disadvantages:

      1. Across application servers this might not work since though we can fiddle with Sun and JBOSS since Open Source, we do need to have a way to work with the Weblogic and WebSphere. And we are not sure whether XADataSource/XAResource is available from the Application Server Context or not. Also the TransactionManager is the same TM as in case of SUNAS implementation. (in case of SUNAS the TM we get is from Appserver directly)

        public TransactionManager getTransactionManager() throws Exception {
                            TransactionManager transactionManager =
                                    (javax.transaction.TransactionManager)
                                    getEnvironment().getNamingContext().lookup(
                                "java:appserver/TransactionManager");
                                    return transactionManager;

              }

This implementation will be having issues, unless otherwise standardized, since though this has the flexibility of propagating transaction across the J2EE components and the binding components the same might not be true with other implementations.

      1. Using this might force us to port the whole of NMR or JBI implementation on to other Application Servers.

  1. Use Manual enlisting/delisting:

    1. Advantages:

      1. This gives the flexibility of implementing the enlistment/delistment the BC specific way does not tie down for an AS implementation.

    2. Disadvantages:

      1. Unless the interfaces we are implementing above RecoverResourceRegistry and the RecoverResourceListener as part of JBI specification and make them available with the NMR by default we will again have the issue of porting across the application servers. Currently they are specific to the NMR of the SUNAS.

      2. The issue of storing the XAResources with respect to manual enlistment and delistment still remain since the NMR has to handle recovery. (This can be over come by putting the componentContext.registerXAResource(component.getXAResource()) in the ComponentLifeCycle init() method.)

I will be talking more about the implementation in respect of 3 types of systems (JTS, OTS, MTS) in my next posts on the same subject.


Comments:

Post a Comment:
Comments are closed for this entry.
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 2015
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