Discussions

EJB design: How 2 avoid Non-XA resource enlisting in global transaction?

  1. Hey,

    I am using container managed transaction in a stateless session bean. We are using two datasources, one xa and non-xa. I am using these two datasources in a single transaction and i am getting an exception that both can't participate in the same transaction. Actually for the non-xa resource, we are commiting within the non-xa database manager and can be thought of as a resource manager local transaction (RMLT).

    Is there a way that I don't want to enlist my non-xa resource with transaction manager?

    I come across the following approaches in weblogic & websphere respectively and we need to support both.

    Weblogic: They have an option of Simulate Two Phase for Non XA, but they are saying to be careful with this option as for Example, Non XA says OK during prepare phase and then any thing happens to the XA later and XA rolls back, Non-XA can't revert, so they generate some heuristics in this case.

    Websphere :
    1)They support Multiple Read only XAs(no changes) and one Non-XA.
       In our case, our XA and Non-XA resources will be modified.

    2) Multiple XAs(READ/WRITE) and one LAST PARTICIPANT NON-XA.
       Probably we can use this in our case, but in this case all our updates to Non-XA should be last(updates to XAs should be done prior to Non-XA), right now our code takes care of it before XAs. Let us say we follow this approach, does this work on weblogic too if we enable emulate two phase for this non-xa??


    THE EASY WAY COULD BE IF THERE IS A WAY TO AVOID MY NON-XA RESOURCE TO BE ENLISTED WITH THE GLOBAL(DISTRIBUTED) TRANSACTION MANAGER.

    Appreciate your help.

    Thanks,
    Rao Kotha.
  2. I got the following solution. I thought this custom solution is better than relying on app servers and different options provided by different
    app servers.

    Let us say you have a update method that updates multiple XA resources and one Non-XA resource, I want to commit all or none. I dont
    want my Non-XA resource to participate in global transaction, so I will create a method that will do updates to Non-XA resource
    and I use the transaction attribute "NotSupported" and I call this method from a method that particpates in transaction. See the
    following snippet to understand this.


    /* It updates mutliple XA resources and one Non-XA resource. Transaction-attribute can be Requires, Requires-New, Mandatory */
    public void boolean update() throws Exception{
    boolean commit = true;
    try{
    commit = updateXA();
    if ( false == commit ){
    return false;
    }

    /* It came here means, XA updates are successful */

    /* Now update Non-XA resource */
    commit = updateNonXA();
    }
    catch(Exception e){
    commit = false;
    throw e;
    }
    finally{
    if( !commit ){
    /*rollback the entire transaction that rolls back the resources that participated in transaction.

    In a way it rolls back XA updates if any

    No need to rollback Non-XA updates, if non-xa update went through successfully, we dont come here

    If Non-XA update is not done then we dont roll back its changes, we need only XA changes.*/
    ctx.rollbackOnly();
    }
    }
    }

    /* Do updates to multiple XA resources here
    Transaction-attribute must be Mandatory or Requires(we know the caller is running in transaction ;) )*/
    public void boolean update() throws Exception{

    }

    /* Do updates to single Non-XA resources here
    Transaction-attribute must be NotSupported, It should ignore the global transaction */
    public void boolean update() throws Exception{

    }

    Appreciate if you can share your views on this.

    Thanks,
    Rao Kotha.
  3. I have used this same technique for many years when this sort of "last participant" situation comes up. Mostly it has been when one resource has a completely independent tran mgr of its own. Similar to the WAS LastParticipant, it only works for one "oddball" resource -- thankfully most resources you use in enterprise-level apps are tran aware.

    Note to the original thread: notice it doesn't matter when in the tran you actually code the updates to the XA and non-XA resources, all that matters is when you COMMIT them and the order of commit. This may reduce how much of your code you have to restructure to achieve this technique. For example, you won't have to change your dozen individual updates that may be mixed in with your XA updates, but only change the two commits at the end which - since there are only two by definition - are easy to switch in order. if you need to.