10 Replies Latest reply on Nov 16, 2006 8:32 AM by bdruth

    XFire

      Mark or Kevin -

      I saw some posts to the CeltiXfire incubator list about getting commit access for you & some other JBoss folks involved with JBossTS - is this a precursor to getting WS-TX support in XFire via JBossTS?

      What's the status of this? Do you have some working handlers already for the current XFire release?

      Cheers,
      Brice

        • 1. Re: XFire
          marklittle

          Not yet. Slow progress, but we'll get there.

          • 2. Re: XFire
            kconner

            Yes, I have (very recently) received commit access for CXF. The purpose of gaining commit access is to enable the ESB project to work closely with CXF.

            Getting JBossTS to work in XFire is not something we have discussed so far, although it would be possible to do this.

            • 3. Re: XFire

               

              "mark.little@jboss.com" wrote:
              Not yet. Slow progress, but we'll get there.


              Have you come across any "issues" with XFire integration, or just need time to get to it? If its the latter, I may take a stab at it myself - we have a vested interest to see if we can get JBossTS working with the XFire dynamic client.

              • 4. Re: XFire
                kconner

                It is the latter :-)

                • 5. Re: XFire

                   

                  "Kevin.Conner@jboss.com" wrote:
                  It is the latter :-)


                  OK, sounds good. That's not to say I won't come up with issues, but at least none have been discovered so far.

                  • 6. Re: XFire
                    marklittle

                    +1

                    • 7. Re: XFire

                      OK, so - crash course in JDOM ;-)

                      Looking at XFire handlers & the jax-rpc handlers, the main difference appears to be that in jax-rpc, one works with SOAP abstractions, whereas in XFire, one manipulates the JDOM directly (I could be off-base, but all the examples appear to point to this).

                      So, to that end, here's the setup/serialization/insertion of the coordination context into the SOAP header, ala XFire:

                      Element coordHeader = new Element(
                       CoordinationConstants.WSCOOR_ELEMENT_COORDINATION_CONTEXT, // localName
                       CoordinationConstants.WSCOOR_PREFIX, // namespace prefix
                       CoordinationConstants.WSCOOR_NAMESPACE); // namespace URI
                       coordHeader.setNamespace(Namespace.getNamespace(CoordinationConstants.WSCOOR_PREFIX, CoordinationConstants.WSCOOR_NAMESPACE));
                      
                       JDOMStreamWriter out = new JDOMStreamWriter(coordHeader);
                       coordinationContext.writeContent(out);
                      
                       Element xfHeader = message.getOrCreateHeader();
                       xfHeader.addContent(coordHeader);
                      


                      Most of the rest of the handler is verbatim from the existing jax-rpc processor. I haven't tested this yet (I need to get my JAX-RPC based test environment working first, so I have a 'control' environment to test against) - but, it looks like this pretty much takes care of what needs to happen in the outgoing handler.

                      Here's the full class:

                      /**
                       *
                       */
                      package org.jboss.ts.contrib.xfire.client;
                      
                      import org.codehaus.xfire.MessageContext;
                      import org.codehaus.xfire.exchange.OutMessage;
                      import org.codehaus.xfire.handler.AbstractHandler;
                      import org.codehaus.xfire.util.stax.JDOMStreamWriter;
                      import org.jdom.Element;
                      import org.jdom.Namespace;
                      
                      import com.arjuna.mw.wsc.context.Context;
                      import com.arjuna.mw.wst.BusinessActivityManager;
                      import com.arjuna.mw.wst.BusinessActivityManagerFactory;
                      import com.arjuna.mw.wst.TransactionManager;
                      import com.arjuna.mw.wst.TransactionManagerFactory;
                      import com.arjuna.webservices.wscoor.CoordinationConstants;
                      import com.arjuna.webservices.wscoor.CoordinationContextType;
                      
                      /**
                       * XFireHeaderContextProcessor.
                       * @author BDR011
                       *
                       */
                      public class XFireHeaderContextProcessor extends AbstractHandler {
                      
                       /**
                       * @see org.codehaus.xfire.handler.Handler#invoke(org.codehaus.xfire.MessageContext)
                       * @param context
                       * @throws Exception
                       */
                       public void invoke(MessageContext context) throws Exception {
                      
                       OutMessage message = context.getOutMessage();
                      
                       if (null == message) {
                       return;
                       }
                      
                       try
                       {
                       /*
                       * There should either be an Atomic Transaction *or* a Business Activity
                       * associated with the thread.
                       */
                       final TransactionManager transactionManager = TransactionManagerFactory.transactionManager() ;
                       final BusinessActivityManager businessActivityManager = BusinessActivityManagerFactory.businessActivityManager() ;
                      
                       final Context atContext ;
                       if (transactionManager != null)
                       {
                       final com.arjuna.mwlabs.wst.at.context.TxContextImple txContext =
                       (com.arjuna.mwlabs.wst.at.context.TxContextImple)transactionManager.currentTransaction() ;
                       atContext = (txContext == null ? null : txContext.context()) ;
                       }
                       else
                       {
                       atContext = null ;
                       }
                      
                       final Context baContext ;
                       if (businessActivityManager != null)
                       {
                       final com.arjuna.mwlabs.wst.ba.context.TxContextImple txContext =
                       (com.arjuna.mwlabs.wst.ba.context.TxContextImple)businessActivityManager.currentTransaction() ;
                       baContext = (txContext == null ? null : txContext.context()) ;
                       }
                       else
                       {
                       baContext = null ;
                       }
                      
                       final CoordinationContextType coordinationContext ;
                       if (atContext != null)
                       {
                       coordinationContext = atContext.getCoordinationContext() ;
                       }
                       else if (baContext != null)
                       {
                       coordinationContext = baContext.getCoordinationContext() ;
                       }
                       else
                       {
                       coordinationContext = null ;
                       }
                      
                       if (coordinationContext != null)
                       {
                       Element coordHeader = new Element(
                       CoordinationConstants.WSCOOR_ELEMENT_COORDINATION_CONTEXT, // localName
                       CoordinationConstants.WSCOOR_PREFIX, // namespace prefix
                       CoordinationConstants.WSCOOR_NAMESPACE); // namespace URI
                       coordHeader.setNamespace(Namespace.getNamespace(CoordinationConstants.WSCOOR_PREFIX, CoordinationConstants.WSCOOR_NAMESPACE));
                      
                       JDOMStreamWriter out = new JDOMStreamWriter(coordHeader);
                       coordinationContext.writeContent(out);
                      
                       Element xfHeader = message.getOrCreateHeader();
                       xfHeader.addContent(coordHeader);
                       }
                       }
                       catch (final Throwable th) {
                       // TODO: handle exception
                       }
                       }
                      
                      }
                      
                      


                      • 8. Re: XFire

                        One other difference between XFire and JAX-RPC w/r/t handlers is that apparently XFire distinguishes between In, Out, and Fault handlers, instead of having a handler that handles the request/response/fault as JAX-RPC does. Regardless of what's being handled, all XFire handlers extend AbstractHandler, so there's probably a way to have one defined Handler process the request/response/fault - but, at the moment, the AbstractHandler just defines an 'invoke()' - so, it would be up to the class to delegate that responsibility, assuming its possible to detect if the In/Out/or Fault chain is being processed.

                        Anyway - I have created In/Out handlers for both the client & the service. For the client, the "out" handler does the interesting work, the "in" handler just suspends the transaction (what's this do?). For the service, its just the opposite - the "in" handler processes the SOAP header and creates the local CoordinationContextType, the "out" handler just suspends.

                        None of this is tested yet (it just compiles) - but once I have a working JAX-RPC proof working, I can start testing this.


                        client.In:

                        /**
                         *
                         */
                        package org.jboss.ts.contrib.xfire.client;
                        
                        import org.codehaus.xfire.MessageContext;
                        import org.codehaus.xfire.handler.AbstractHandler;
                        
                        import com.arjuna.mw.wst.BusinessActivityManager;
                        import com.arjuna.mw.wst.BusinessActivityManagerFactory;
                        import com.arjuna.mw.wst.TransactionManager;
                        import com.arjuna.mw.wst.TransactionManagerFactory;
                        
                        /**
                         * XFireOutHeaderContextProcessor.
                         * @author BDR011
                         *
                         */
                        public class XFireInHeaderContextProcessor extends AbstractHandler {
                        
                         /**
                         * @see org.codehaus.xfire.handler.Handler#invoke(org.codehaus.xfire.MessageContext)
                         * @param context
                         * @throws Exception
                         */
                         public void invoke(MessageContext context) throws Exception {
                         suspendTransaction();
                         }
                        
                         /**
                         * Suspend the current transaction.
                         */
                         private void suspendTransaction()
                         {
                         try
                         {
                         /*
                         * There should either be an Atomic Transaction *or* a Business Activity
                         * associated with the thread.
                         */
                         final TransactionManager transactionManager = TransactionManagerFactory.transactionManager() ;
                         final BusinessActivityManager businessActivityManager = BusinessActivityManagerFactory.businessActivityManager() ;
                        
                         if (transactionManager != null)
                         {
                         transactionManager.suspend() ;
                         }
                        
                         if (businessActivityManager != null)
                         {
                         businessActivityManager.suspend() ;
                         }
                         }
                         catch (final Throwable th) {
                         // TODO: handle exception
                         }
                         }
                        }
                        


                        client.Out:
                        /**
                         *
                         */
                        package org.jboss.ts.contrib.xfire.client;
                        
                        import org.codehaus.xfire.MessageContext;
                        import org.codehaus.xfire.exchange.OutMessage;
                        import org.codehaus.xfire.handler.AbstractHandler;
                        import org.codehaus.xfire.util.stax.JDOMStreamWriter;
                        import org.jdom.Element;
                        import org.jdom.Namespace;
                        
                        import com.arjuna.mw.wsc.context.Context;
                        import com.arjuna.mw.wst.BusinessActivityManager;
                        import com.arjuna.mw.wst.BusinessActivityManagerFactory;
                        import com.arjuna.mw.wst.TransactionManager;
                        import com.arjuna.mw.wst.TransactionManagerFactory;
                        import com.arjuna.webservices.wscoor.CoordinationConstants;
                        import com.arjuna.webservices.wscoor.CoordinationContextType;
                        
                        /**
                         * XFireOutHeaderContextProcessor.
                         * @author BDR011
                         *
                         */
                        public class XFireOutHeaderContextProcessor extends AbstractHandler {
                        
                         /**
                         * @see org.codehaus.xfire.handler.Handler#invoke(org.codehaus.xfire.MessageContext)
                         * @param context
                         * @throws Exception
                         */
                         public void invoke(MessageContext context) throws Exception {
                        
                         OutMessage message = context.getOutMessage();
                        
                         if (null == message) {
                         return;
                         }
                        
                         try
                         {
                         /*
                         * There should either be an Atomic Transaction *or* a Business Activity
                         * associated with the thread.
                         */
                         final TransactionManager transactionManager = TransactionManagerFactory.transactionManager() ;
                         final BusinessActivityManager businessActivityManager = BusinessActivityManagerFactory.businessActivityManager() ;
                        
                         final Context atContext ;
                         if (transactionManager != null)
                         {
                         final com.arjuna.mwlabs.wst.at.context.TxContextImple txContext =
                         (com.arjuna.mwlabs.wst.at.context.TxContextImple)transactionManager.currentTransaction() ;
                         atContext = (txContext == null ? null : txContext.context()) ;
                         }
                         else
                         {
                         atContext = null ;
                         }
                        
                         final Context baContext ;
                         if (businessActivityManager != null)
                         {
                         final com.arjuna.mwlabs.wst.ba.context.TxContextImple txContext =
                         (com.arjuna.mwlabs.wst.ba.context.TxContextImple)businessActivityManager.currentTransaction() ;
                         baContext = (txContext == null ? null : txContext.context()) ;
                         }
                         else
                         {
                         baContext = null ;
                         }
                        
                         final CoordinationContextType coordinationContext ;
                         if (atContext != null)
                         {
                         coordinationContext = atContext.getCoordinationContext() ;
                         }
                         else if (baContext != null)
                         {
                         coordinationContext = baContext.getCoordinationContext() ;
                         }
                         else
                         {
                         coordinationContext = null ;
                         }
                        
                         if (coordinationContext != null)
                         {
                         Element coordHeader = new Element(
                         CoordinationConstants.WSCOOR_ELEMENT_COORDINATION_CONTEXT, // localName
                         CoordinationConstants.WSCOOR_PREFIX, // namespace prefix
                         CoordinationConstants.WSCOOR_NAMESPACE); // namespace URI
                         coordHeader.setNamespace(Namespace.getNamespace(CoordinationConstants.WSCOOR_PREFIX, CoordinationConstants.WSCOOR_NAMESPACE));
                        
                         JDOMStreamWriter out = new JDOMStreamWriter(coordHeader);
                         coordinationContext.writeContent(out);
                        
                         Element xfHeader = message.getOrCreateHeader();
                         xfHeader.addContent(coordHeader);
                         }
                         }
                         catch (final Throwable th) {
                         // TODO: handle exception
                         }
                         }
                        
                        }
                        


                        service.In:
                        /**
                         *
                         */
                        package org.jboss.ts.contrib.xfire.service;
                        
                        import java.util.Iterator;
                        
                        import org.codehaus.xfire.MessageContext;
                        import org.codehaus.xfire.exchange.InMessage;
                        import org.codehaus.xfire.handler.AbstractHandler;
                        import org.codehaus.xfire.util.stax.JDOMStreamReader;
                        import org.jdom.Element;
                        
                        import com.arjuna.mw.wst.BusinessActivityManagerFactory;
                        import com.arjuna.mw.wst.TransactionManagerFactory;
                        import com.arjuna.mw.wst.TxContext;
                        import com.arjuna.webservices.wsat.AtomicTransactionConstants;
                        import com.arjuna.webservices.wsba.BusinessActivityConstants;
                        import com.arjuna.webservices.wscoor.CoordinationConstants;
                        import com.arjuna.webservices.wscoor.CoordinationContextType;
                        
                        /**
                         * XFireOutHeaderContextProcessor.
                         * @author BDR011
                         *
                         */
                        public class XFireInHeaderContextProcessor extends AbstractHandler {
                        
                         /**
                         * @see org.codehaus.xfire.handler.Handler#invoke(org.codehaus.xfire.MessageContext)
                         * @param context
                         * @throws Exception
                         */
                         public void invoke(MessageContext context) throws Exception {
                         InMessage message = context.getInMessage();
                        
                         if (null != message && null != message.getHeader()) {
                         Element xfHeader = message.getHeader();
                         Element coordHeader = getHeaderElement(
                         xfHeader, // the full header
                         CoordinationConstants.WSCOOR_NAMESPACE, // the namespace URI
                         CoordinationConstants.WSCOOR_ELEMENT_COORDINATION_CONTEXT); // the element name
                         JDOMStreamReader in = new JDOMStreamReader(coordHeader);
                        
                         final CoordinationContextType cc = new CoordinationContextType(in);
                         final String coordinationType = cc.getCoordinationType().getValue() ;
                         if (AtomicTransactionConstants.WSAT_PROTOCOL.equals(coordinationType))
                         {
                         final TxContext txContext = new com.arjuna.mwlabs.wst.at.context.TxContextImple(cc) ;
                         TransactionManagerFactory.transactionManager().resume(txContext) ;
                         }
                         else if (BusinessActivityConstants.WSBA_PROTOCOL_ATOMIC_OUTCOME.equals(coordinationType))
                         {
                         final TxContext txContext = new com.arjuna.mwlabs.wst.ba.context.TxContextImple(cc);
                         BusinessActivityManagerFactory.businessActivityManager().resume(txContext) ;
                         }
                         else
                         {
                         // TODO: handle unknown coordination type
                         }
                         }
                         }
                        
                         /**
                         * Retrieve the first header matching the uri and name.
                         * @param soapEnvelope The soap envelope containing the header.
                         * @param uri The uri of the header element.
                         * @param name The name of the header element.
                         * @return The header element or null if not found.
                         */
                         private Element getHeaderElement(final Element messageHeader, final String uri, final String name)
                         {
                         if (messageHeader != null)
                         {
                         final Iterator headerIter = messageHeader.getDescendants() ;
                         while(headerIter.hasNext())
                         {
                         final Element current = (Element) headerIter.next() ;
                         if (match(name, current.getName()) &&
                         match(uri, current.getNamespaceURI()))
                         {
                         return current ;
                         }
                         }
                         }
                         return null ;
                         }
                        
                         /**
                         * Do the two references match?
                         * @param lhs The first reference.
                         * @param rhs The second reference.
                         * @return true if the references are both null or if they are equal.
                         */
                         private boolean match(final Object lhs, final Object rhs)
                         {
                         if (lhs == null)
                         {
                         return (rhs == null) ;
                         }
                         else
                         {
                         return lhs.equals(rhs) ;
                         }
                         }
                        }
                        


                        service.Out:
                        /**
                         *
                         */
                        package org.jboss.ts.contrib.xfire.service;
                        
                        import org.codehaus.xfire.MessageContext;
                        import org.codehaus.xfire.handler.AbstractHandler;
                        
                        import com.arjuna.mw.wst.BusinessActivityManager;
                        import com.arjuna.mw.wst.BusinessActivityManagerFactory;
                        import com.arjuna.mw.wst.TransactionManager;
                        import com.arjuna.mw.wst.TransactionManagerFactory;
                        
                        /**
                         * XFireOutHeaderContextProcessor.
                         * @author BDR011
                         *
                         */
                        public class XFireOutHeaderContextProcessor extends AbstractHandler {
                        
                         /**
                         * @see org.codehaus.xfire.handler.Handler#invoke(org.codehaus.xfire.MessageContext)
                         * @param context
                         * @throws Exception
                         */
                         public void invoke(MessageContext context) throws Exception {
                         suspendTransaction();
                         }
                        
                         /**
                         * Suspend the current transaction.
                         */
                         private void suspendTransaction()
                         {
                         try
                         {
                         /*
                         * There should either be an Atomic Transaction *or* a Business Activity
                         * associated with the thread.
                         */
                         final TransactionManager transactionManager = TransactionManagerFactory.transactionManager() ;
                         final BusinessActivityManager businessActivityManager = BusinessActivityManagerFactory.businessActivityManager() ;
                        
                         if (transactionManager != null)
                         {
                         transactionManager.suspend() ;
                         }
                        
                         if (businessActivityManager != null)
                         {
                         businessActivityManager.suspend() ;
                         }
                         }
                         catch (final Throwable th)
                         {
                         // TODO: handle exception
                         }
                         }
                        }
                        


                        • 9. Re: XFire
                          kconner

                          Yep, this looks good. The interceptor really is as simple as that :-)

                          • 10. Re: XFire

                            Excellent. OK - once I've grokked what Mark wrote in my WS-TX post, I'll hopefully be closer to testing this. I just briefly read through it, but either its too early or I need to read through it a couple more times :)

                            -Brice