This discussion is archived
6 Replies Latest reply: Nov 29, 2012 2:55 AM by 901275 RSS

Local transaction support when BPEL invokes JCA adapter

901275 Newbie
Currently Being Moderated
Hi all,

I've implemented a BPEL process consisting of multiple invoke activities to my (custom) JCA Resource Adapter which connects to an EIS.
My concern is to support local transactions. Here are some code snippets describing what I've done so far.

Declare the transaction support at deployment time (ra.xml)
<transaction-support>LocalTransaction</transaction-support>
Implementer class of ManagedConnection interface
public class MyManagedConnection implements ManagedConnection {

     ...

     public XAResource getXAResource() throws ResourceException {
         throw new NotSupportedException("XA Transactions not supported");
     }

     public LocalTransaction getLocalTransaction() throws ResourceException {
         return new MyLocalTransaction(this);
     }
     
        public void sendTheEvent(int eventType, Object connectionHandle) {
             ConnectionEvent event = new ConnectionEvent(this, eventType);
         
             if (connectionHandle != null) {
                event.setConnectionHandle(connectionHandle);
             }

            ConnectionEventListener listener = getEventListener();
          
         switch (eventType) {
          case ConnectionEvent.CONNECTION_CLOSED:
               listener.connectionClosed(event); break;
          case ConnectionEvent.LOCAL_TRANSACTION_STARTED:
               listener.localTransactionStarted(event); break;
          case ConnectionEvent.LOCAL_TRANSACTION_COMMITTED:
               listener.localTransactionCommitted(event); break;
          case ConnectionEvent.LOCAL_TRANSACTION_ROLLEDBACK:
               listener.localTransactionRolledback(event); break;
          case ConnectionEvent.CONNECTION_ERROR_OCCURRED:
               listener.connectionErrorOccurred(event); break;
          default: break;
         }
        }
}
Implementer class of LocalTransaction interface
public class MyLocalTransaction implements javax.resource.spi.LocalTransaction {

     private MyManagedConnection mc = null;
     
     public MyLocalTransaction(MyManagedConnection mc) {
         this.mc = mc;
     }     
     
     @Overide
     public void begin() throws ResourceException {
         mc.sendTheEvent(ConnectionEvent.LOCAL_TRANSACTION_STARTED, mc);
     }
     
     @Override
     public void commit() throws ResourceException {
         eis.commit(); //eis specific method
         mc.sendTheEvent(ConnectionEvent.LOCAL_TRANSACTION_COMMITTED, mc);
     }     
     
     @Override
     public void rollback() throws ResourceException {
         eis.rollback(); //eis specific method
         mc.sendTheEvent(ConnectionEvent.LOCAL_TRANSACTION_ROLLEDBACK, mc);
     }
}
Uppon BPEL process completion, MyLocalTransaction.commit() is called. However, localTransactionCommitted(event) fails and I get the following error:
Error committing transaction:; nested exception is: weblogic.transaction.nonxa.NonXAException: java.lang.IllegalStateException: 
[Connector:199175]This ManagedConnection is managed by container for its transactional behavior and has been enlisted to JTA transaction by container; 
application/adapter must not call the local transaction begin/commit/rollback API. Reject event LOCAL_TRANSACTION_COMMITTED from adapter.
Could someone give me some directions to proceed ?

My current installation consists of:
1. Oracle SOA Suite / JDeveoper 11g (11.1.1.4.0),
2. WebLogic Server 10.3.4


Thank you for your time,
George
  • 1. Re: Local transaction support when BPEL invokes JCA adapter
    vladodias Guru
    Currently Being Moderated
    Hi,

    These links may help...

    http://acharyavivek.wordpress.com/2012/10/10/transaction-in-soa-11g/

    http://docs.oracle.com/cd/E23943_01/dev.1111/e10224/soa_transactions.htm#CHDCABGC

    Cheers,
    Vlad
  • 2. Re: Local transaction support when BPEL invokes JCA adapter
    901275 Newbie
    Currently Being Moderated
    Hi Vlad,

    I have just one Synchronous BPEL process without using the following property:
    <property name="bpel.config.transaction" many="false" type="xs:string">required | requiresNew</property>
    My understanding is that the property is only necessary in case where a caller BPEL process, calls a callee BPEL.
    So my composite does not contain "transaction-specific" properties at all.

    Your second reference link mentions: "Oracle BPEL Process Manager by default creates a new transaction on a request basis"
    http://docs.oracle.com/cd/E14571_01/integration.1111/e10224/soa_transactions.htm#CHDHIAIH

    What I realize is that when BPEL process starts execution (let's say via Oracle EM console), a new transaction is initiated through which
    all operations will be performed. That's what I need. Moreover, I want a commit to be executed upon BPEL process completion.

    If I remove the ConnectionEventListener methods localTransactionCommitted(event) and localTransactionRolledback(event) (see source code snippet),
    BPEL process terminates as expected. Do I really need to explicitly send event notifications for commit and rollback to the server ?
    I currently use notifications only on begin and close (ConnectionEventListener localTransactionStarted(), connectionClosed() respectively)
    public class MyLocalTransaction implements javax.resource.spi.LocalTransaction {
     
         private MyManagedConnection mc = null;
         
         public MyLocalTransaction(MyManagedConnection mc) {
             this.mc = mc;
         }     
         
         @Overide
         public void begin() throws ResourceException {
             mc.sendTheEvent(ConnectionEvent.LOCAL_TRANSACTION_STARTED, mc);
         }
         
         @Override
         public void commit() throws ResourceException {
             eis.commit(); //eis specific method
                //do not call sendTheEvent()
         }     
         
         @Override
         public void rollback() throws ResourceException {
             eis.rollback(); //eis specific method
                //do not call sendTheEvent()
         }
    }
    I checked (through de-compilation) the code for MQSeriesAdapter which supports Local Transaction and it does send event notifications for begin/commit/rollback.

    I am confused. Could someone explain me the case and what steps should I follow ?

    Regards,
    George
  • 3. Re: Local transaction support when BPEL invokes JCA adapter
    vladodias Guru
    Currently Being Moderated
    The important fact is that BPEL will be always in a transaction... Apparently your adapter is participation in the BPEL JTA transaction (rather than creating a new one)... Thus, when trying to send a local commit, it will fail because "This ManagedConnection is managed by container for its transactional behavior and has been enlisted to JTA transaction by container"...

    So you got to see what's better for your case, participate on BPEL transaction and let BPEL commit the transaction for you or somehow put your JCA adapter in a transaction context different than the BPEL one...

    Hope this helps...

    Cheers,
    Vlad
  • 4. Re: Local transaction support when BPEL invokes JCA adapter
    901275 Newbie
    Currently Being Moderated
    Hi all, I have another question in continuation of my previous post.

    Let me first describe you the case:
    -- Implemented a BPEL process consisting of multiple invoke activities to my (custom) JCA Resource Adapter which connects to an EIS.
    -- Used the partner link property idempotent=false to start new transaction(s) when necessary according to business case's needs.
    -- Created a client tester via Web Service Proxy wizard to call my BPEL process from Java.

    Note:_ My adapter implements javax.resource.spi.LocalTransaction interface but not javax.resource.cci.LocalTransaction. See the following
    code snippets.

    Implementer class of javax.resource.spi.ManagedConnection interface
    public class MyManagedConnection implements ManagedConnection {
    
        /* (non-Javadoc)
         * @see javax.resource.spi.ManagedConnection#getLocalTransaction()
         */
        @Override
        public LocalTransaction getLocalTransaction() throws ResourceException {
             return new MySpiLocalTransaction(this);      
        }
    }
    Implementer class of javax.resource.spi.LocalTransaction interface
    public class MySpiLocalTransaction implements LocalTransaction {
         /* (non-Javadoc)
          * @see javax.resource.spi.LocalTransaction#begin()
          */
         @Overide
         public void begin() throws ResourceException {
         }
         
         /* (non-Javadoc)
          * @see javax.resource.spi.LocalTransaction#commit()
          */     
         @Override
         public void commit() throws ResourceException {
             eis.commit(); //eis specific method
         }     
         
         /* (non-Javadoc)
          * @see javax.resource.spi.LocalTransaction#rollback()
          */     
         @Override
         public void rollback() throws ResourceException {
             eis.rollback(); //eis specific method
         }
    }
    Implementer class of javax.resource.cci.Connection interface
    public class MyConnection implements Connection {
    
        /* (non-Javadoc)
         * @see javax.resource.cci.Connection#getLocalTransaction()
         */
        @Override
        public LocalTransaction getLocalTransaction() throws ResourceException {
             return null;
        }
    }
    I run the test and everything works as expected:
    -- javax.resource.spi.LocalTransaction#begin() is explicitly called after each transaction initialization
    -- javax.resource.spi.LocalTransaction#commit() is explicitly called accordingly (depending on idempotent property)
    -- After the completion of the run, my EIS has been updated and the process's state is "Completed" (checked through Enterprise Manager web interface)

    When i run the test for the 2nd time, neither javax.resource.spi.LocalTransaction#begin() nor javax.resource.spi.LocalTransaction#commit() is called and my test fails.
    I suppose that no transaction is created. Any idea why this happens and how to solve my problem ?

    Regards,
    George
  • 5. Re: Local transaction support when BPEL invokes JCA adapter
    vladodias Guru
    Currently Being Moderated
    898272 wrote:
    ... neither javax.resource.spi.LocalTransaction#begin() nor javax.resource.spi.LocalTransaction#commit() is called ...
    How did you observe that? I suggest you include debug logging directly on MySpiLocalTransaction class to certify...
    When in the second call you have different behaviour than in the first call, usually the cause is an object that is not cleared/released properly... In your case the suspect would be the "eis" object...
  • 6. Re: Local transaction support when BPEL invokes JCA adapter
    901275 Newbie
    Currently Being Moderated
    Hi Vlad, thank you again for your immediate response.

    With regards to your first comment. I already have been using logs, so I confirm that neither javax.resource.spi.LocalTransaction#begin() nor javax.resource.spi.LocalTransaction#commit()
    is called in the 2nd run.

    I think it might be helpful for our discussion if I give you the call trace for a successful (the first one) run.

    After I deploy my custom JCA Resource Adapter, I create a javax.resource.cci.ConnectionFactory through Oracle EM web application and the following methods are called:
    -- MyManagedConnectionFactory()
    (Constructor of the implementer class of the javax.resource.spi.ManagedConnectionFactory interface)
    
    -- javax.resource.spi.ManagedConnectionFactory#createManagedConnection(javax.security.auth.Subject, javax.resource.spi.ConnectionRequestInfo)
    
    -- MyManagedConnection()
    (Constructor of the implementer class of the javax.resource.spi.ManagedConnection interface)
    
    -- javax.resource.spi.ManagedConnection#addConnectionEventListener(javax.resource.spi.ConnectionEventListener)
    
    -- javax.resource.spi.ManagedConnection#getLocalTransaction()
    
    -- MySpiLocalTransaction(MyManagedConnection)
    (Constructor of the implementer class of the javax.resource.spi.LocalTransaction interface)
    
    -- javax.resource.spi.ManagedConnectionFactory#createConnectionFactory(javax.resource.spi.ConnectionManager)
    
    -- MyConnectionFactory(javax.resource.spi.ManagedConnectionFactory, javax.resource.spi.ConnectionManager)
    (Constructor of the implementer class of the javax.resource.cci.ConnectionFactory interface)
    BPEL process consists of multiple invoke activities to my (custom) JCA Resource Adapter which connects to an EIS. Client tester invokes BPEL process, and execution starts.
    Here is the method call trace for the last invoke (after which, commit is executed). The logs for all the rest invocations are identical:
    -- javax.resource.cci.ConnectionFactory#getConnection()
    
    -- javax.resource.spi.ManagedConnection#getConnection(javax.security.auth.Subject, javax.resource.spi.ConnectionRequestInfo)
    
    -- MyConnection(MyManagedConnection)
    (Constructor of the implementer class of the javax.resource.cci.Connection interface)
    
    -- javax.resource.cci.Connection#close()
    (I don't understand why close() is called here, any idea ?)
    
    -- javax.resource.cci.ConnectionFactory#getConnection()
    
    -- javax.resource.spi.ManagedConnection#getConnection(javax.security.auth.Subject, javax.resource.spi.ConnectionRequestInfo)
    
    -- MyConnection(MyManagedConnection)
    (Constructor of the implementer class of the javax.resource.cci.Connection interface)
    
    -- javax.resource.cci.Connection#createInteraction()
    
    -- MyInteraction(javax.resource.cci.Connection)
    (Constructor of the implementer class of the javax.resource.cci.Interaction interface)
    
    -- javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, javax.resource.cci.Record, javax.resource.cci.Record)
    
    -- javax.resource.spi.LocalTransaction#commit()
    I would expect that after the last commit() - meaning that BPEL process is done, and its state is "Completed" - Weblogic server would call the following:
    javax.resource.cci.Connection#close()
    However it doesn't. Do I miss something ?

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points