6 Replies Latest reply: Nov 29, 2012 4:55 AM by 901275 RSS

    Local transaction support when BPEL invokes JCA adapter

    901275
      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
          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
            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
              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
                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
                  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
                    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 ?