3 Replies Latest reply on Feb 15, 2011 12:22 PM by jhalliday

    CoordinationContext

    canastasiou

      We are using JBoss 5.1.0.GA and have deployed a web service. Our aim is to make this WS 2PC enabled. We have installed XTS and have added the necessary annotations:

       

       

      @Stateless
      @WebService
      @TransactionAttribute(value=TransactionAttributeType.SUPPORTS)
      @TransactionManagement(value=TransactionManagementType.CONTAINER)
      @EndpointConfig(configName = "Standard WSSecurity Endpoint")
      @Addressing(enabled=true, required=true)
      @SOAPBinding(style=Style.RPC,use=Use.LITERAL,parameterStyle=ParameterStyle.WRAPPED)
      

       

      The client who calls our WS is in .NET. Whenever they call us we get the following exception:

       

       

      ERROR [org.jboss.ws.core.jaxws.SOAPFaultHelperJAXWS] (http-0.0.0.0-8089-1) SOAP request exception
      javax.xml.ws.soap.SOAPFaultException: Unprocessed 'mustUnderstand' header element: {http://docs.oasis-open.org/ws-tx/wscoor/2006/06}CoordinationContext
          at org.jboss.ws.core.jaxws.SOAPFaultHelperJAXWS.getSOAPFaultException(SOAPFaultHelperJAXWS.java:84)
          at org.jboss.ws.core.jaxws.binding.SOAP11BindingJAXWS.throwFaultException(SOAP11BindingJAXWS.java:107)
          at org.jboss.ws.core.CommonSOAP11Binding.verifyUnderstoodHeader(CommonSOAP11Binding.java:86)
          at org.jboss.ws.core.CommonSOAPBinding.checkMustUnderstand(CommonSOAPBinding.java:962)
          at org.jboss.ws.core.server.ServiceEndpointInvoker.invoke(ServiceEndpointInvoker.java:194)
          at org.jboss.wsf.stack.jbws.RequestHandlerImpl.processRequest(RequestHandlerImpl.java:474)
          at org.jboss.wsf.stack.jbws.RequestHandlerImpl.handleRequest(RequestHandlerImpl.java:295)
          at org.jboss.wsf.stack.jbws.RequestHandlerImpl.doPost(RequestHandlerImpl.java:205)
          at org.jboss.wsf.stack.jbws.RequestHandlerImpl.handleHttpRequest(RequestHandlerImpl.java:131)
          at org.jboss.wsf.common.servlet.AbstractEndpointServlet.service(AbstractEndpointServlet.java:85)
          at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
          at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
          at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
          at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
          at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
          at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
          at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
          at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
          at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
          at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
          at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
          at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
          at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
          at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
          at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
          at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
          at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)
          at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
          at java.lang.Thread.run(Thread.java:595)
      

       

      How do we solve this? I cannot find any answers in Google about this.

        • 1. Re: CoordinationContext
          adinn

          canastasiou wrote:

           

          We are using JBoss 5.1.0.GA and have deployed a web service. Our aim is to make this WS 2PC enabled. We have installed XTS and have added the necessary annotations:

          @Stateless
          @WebService
          @TransactionAttribute(value=TransactionAttributeType.SUPPORTS)
          @TransactionManagement(value=TransactionManagementType.CONTAINER)
          @EndpointConfig(configName = "Standard WSSecurity Endpoint")
          @Addressing(enabled=true, required=true)
          @SOAPBinding(style=Style.RPC,use=Use.LITERAL,parameterStyle=ParameterStyle.WRAPPED)

           

          I'm very interested in your choice of these 'necessary annotations' as a way to guarantee that the your web service is '2pc enabled'. However, I'm afraid that there is no J2EE sandard defining annotations which serve this purpose. The WSAT and WSBA standards on which XTS is based do allow you to build transactional web services but they require you to do more work than simply annotate your web service.There is at present no standard  way of ensuring that an EJB executes inside a normal Java (JTA) transaction when a web servcie is invoked within a web service transaction.

           

           

          If you are simply interested in enabling your web service to be implemented by a transactional EJB then JBoss provides software which can be used to do what you want. Amongst other things, this package will resolve the problem you are seeing with the mustUnderstand header. It is provided as source code so you will have to obtain and build it yourself. Obtain the  JBossTS 4.6.1.GA_CP07 source release  and look in directory txBridge. [oops, this is  not  the directory you were looking  for -- see  below for  the correct location] The README file will tell you how to build and deploy the txBridge code. The demo example should show you how to configure your own application. Essentially you should only need to add a specific WS server sde handler.

           

           

          canastasiou wrote:


          ERROR [org.jboss.ws.core.jaxws.SOAPFaultHelperJAXWS] (http-0.0.0.0-8089-1) SOAP request exception
          javax.xml.ws.soap.SOAPFaultException: Unprocessed 'mustUnderstand' header element: {http://docs.oasis-open.org/ws-tx/wscoor/2006/06}CoordinationContext
              at org.jboss.ws.core.jaxws.SOAPFaultHelperJAXWS.getSOAPFaultException(SOAPFaultHelperJAXWS.java:84)
              at org.jboss.ws.core.jaxws.binding.SOAP11BindingJAXWS.throwFaultException(SOAP11BindingJAXWS.java:107)
              . . .

           

          Ok, here are the details of what is going wrong and the explanation of why. This will also explain to you how much the XTS code and bridge code actually does for you. (Much more complete details of how XTS works can be found in  the XTS programmers guide which is in the xts/docs directory of the full release).

           

          This error is happening because the web service client is passing details of the .NET WSAT transaction (a CoordinationContext) in the header of the web service request. Your transactional web service needs to remove this header and respond to it. Any changes it makes must occur as part of the larger WS transaction. This has two halves. Firstly, the web service must ensure that it locks data it wants to read or write while the transaction  is active and that when it unlocks the data the changes are only installed if the larger WSAT transaction has committed. If the WSAT transaction has rolled back then the data must be restored to what it was before the locks were taken. Second, it must contact the WSAT transaction coordinator whose URL is contained in the CoordinationContext and enlist as a a participant (the coordinator may be running on the client machine or on some other machine). This means that at some later point when the client calls commit or rollback the coordinator will send the web service PREPARE, COMMIT or ROLLBACK messages. These messages allow it to persist its changes to disk so that it can cope with a crash after prepare and then subsequently unlock and either roll forward or roll back changes, deleting the logged recovery data from disk.

           

          XTS performs some of this work for you. In fact it does everything that the WSAT standard requries a conforming implementation to do. So, it hides all the details of how you negotiate with the coordinator and how you handle receiving of PREPARE messages and sending of PREPARED responses etc. It also deals with logging recovery data and resuming communications if a crash happens part way through this process. What it cannot do just on its own is decide how you want to manage the web service data. It cannot know what to lock or how to lock it nor how to install or revert any changes you want to make. It simply provides a way for you to hand over a participant object when the web servcie is called and enlists inthe WSAT transaction on behalf of your participant object. The participant has to implement 3 methods, prepare, commit and rollback which get called when the coordinator notifies the XTS code of a change in the transaction status. It is up to the participant/web service to ensure that any data read during the transaction is locked for READ or WRITE access, handed over to XTS for saving in the recovery log at prepare and unlocked and updated at commit or unlocked and reverted at rollback.

           

          That's quite a complicated thing to implement but that is all the behaviour that the WSAT spec defines. However, if you just want to use an EJB to implement the web service then the txBridge package provides a participant which does most of  this work for you. It relies upon the transactional behaviour of EJBs to do the data management. You enable the txBridge by adding the txBridge server side header processor to your web service. When the web service is called with a WSAT CoordinationContext in the header the txBridge code removes it and creates a participant on behalf  of your web service which is enlisted in the WSAT transaction. It also creates a JTA transaction which is under the control of the participant. The participant callbacks don't talk to your web servcie but they do drive the JTA transaction your web service is using.

           

          The txBridge participant is just a wrapper round the JTA transaction. When the participant is told to prepare the JTA transaction is prepared and the details of the participant and the JTA transaction are saved in the recovery log. When the participant is told to commit its changes the JTA transaction is committed. If the participant is rolled back because, say, the client called rollback or because, say, another web service called by the client failed to prepare, then the JTA transaction is rolled back. So long as the web service only modifies EJB data then any changes it makes are locked, isolated from concurrent modifications by other transactions and guaranteed to be commited or rolled back after prepare even if a crash occurs i.e. the usual ACID properties. Thsi only works if your web service implementation is a pure EJB. If it wants to be able to modify its own shared state which is not accessed and updated via a transactional data management layer like an EJB then you will need to register your own participant and ensure that changes to this shared state provide the necessary ACID guarantees.

          • 2. Re: CoordinationContext
            canastasiou

            Thanks Andrew, you reply was very informative and clear. I will need some more information which I think you can provide if I give you a few more details of our implementation.

             

            As I said, our web service is deployed on JBoss 5.1.0GA. We installed XTS following the instructions inside jboss-5.1.0.GA\docs\examples\transactions. Some more code will enlighten you on how we implement the ws:

             

             

            package project.app.ejbc;
            
            
            import javax.ejb.Remote;
            import javax.jws.WebService;
            
            
            @Remote
            @WebService
            public interface ServiceRemote{
                 public String createTransfer(String username, String password, String requestXML) throws Exception;
            }
            

             

            Then we have:

             

             

            package project.app.ejb;
            
            .
            
            .
            
            .
            @Stateless
            @WebService
            @TransactionAttribute(value=TransactionAttributeType.SUPPORTS)
            @TransactionManagement(value=TransactionManagementType.CONTAINER)
            @EndpointConfig(configName = "Standard WSSecurity Endpoint")
            @Addressing(enabled=true, required=true)
            @SOAPBinding(style=Style.RPC,use=Use.LITERAL,parameterStyle=ParameterStyle.WRAPPED)
            public class ServiceBean implements ServiceRemote {
            
                    @WebMethod(action="createTransfer")
                      @TransactionAttribute(value=TransactionAttributeType.REQUIRED)
                      public String createTransfer(@WebParam(name="username")String username,@WebParam(name="password")String password, @WebParam(name="requestXML")String requestXML) throws 
                      .
                      .
                      .
                    }
            }
            

             

            Any communication with the DB (SELECT, INSERT etc) is done with Hibernate.

             

            We used to have a similar issue, an exception thrown by JBoss:

             

             

            ERROR [SOAPFaultHelperJAXWS] SOAP request exception
            javax.xml.ws.soap.SOAPFaultException: Unprocessed 'mustUnderstand' header element: {http://www.w3.org/2005/08/addressing}Action
                    at org.jboss.ws.core.jaxws.SOAPFaultHelperJAXWS.getSOAPFaultException(SOAPFaultHelperJAXWS.java:84)
                    at org.jboss.ws.core.jaxws.binding.SOAP11BindingJAXWS.throwFaultException(SOAP11BindingJAXWS.java:107)
                    at org.jboss.ws.core.CommonSOAP11Binding.verifyUnderstoodHeader(CommonSOAP11Binding.java:86)
                    at org.jboss.ws.core.CommonSOAPBinding.checkMustUnderstand(CommonSOAPBinding.java:962)
                    at org.jboss.ws.core.server.ServiceEndpointInvoker.invoke(ServiceEndpointInvoker.java:194)
                    at org.jboss.wsf.stack.jbws.RequestHandlerImpl.processRequest(RequestHandlerImpl.java:474)
                    at org.jboss.wsf.stack.jbws.RequestHandlerImpl.handleRequest(RequestHandlerImpl.java:295)
                    at org.jboss.wsf.stack.jbws.RequestHandlerImpl.doPost(RequestHandlerImpl.java:205)
                    at org.jboss.wsf.stack.jbws.RequestHandlerImpl.handleHttpRequest(RequestHandlerImpl.java:131)
                    at org.jboss.wsf.common.servlet.AbstractEndpointServlet.service(AbstractEndpointServlet.java:85)
                    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
                    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
                    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                    at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
                    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
                    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
                    at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
                    at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
                    at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
                    at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
                    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
                    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
                    at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
                    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
                    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
                    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
                    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)
                    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
                    at java.lang.Thread.run(Thread.java:595)
            
            

             

            Which was solved with the use of:

             

             

            @Addressing(enabled=true, required=true)
            
            

             

            That is why I thought another annotation would solve our problem but it seems that the solution is not as simple as I thought.

             

             

            Andrew Dinn wrote:

             

            That's quite a complicated thing to implement but that is all the behaviour that the WSAT spec defines. However, if you just want to use an EJB to implement the web service then the txBridge package provides a participant which does most of  this work for you. It relies upon the transactional behaviour of EJBs to do the data management. You enable the txBridge by adding the txBridge server side header processor to your web service. When the web service is called with a WSAT CoordinationContext in the header the txBridge code removes it and creates a participant on behalf  of your web service which is enlisted in the WSAT transaction. It also creates a JTA transaction which is under the control of the participant. The participant callbacks don't talk to your web servcie but they do drive the JTA transaction your web service is using.

             

            You propose the use of txBridge, by obtaining JBossTS 4.6.1.GA_CP07. I do not seem to be able to locate it anywhere. How can I obtain this version of JBossTS? From what you mention, txBridge is exactly what we need, since I understand it does most of the work on its own.

             

            I am sorry for asking questions that might seem obvious to you, but I am afraid that there are not enough examples on the internet for this, or at least I was not able to find them. Reading the Programmer's Guides also does not offer something apart from introducing the concept of ACID transactions and giving us an idea on how the whole thing works.

             

            I should note that I have comparatively little professional experience but I guess this is the way to learn. The tough way...

             

            Again, thank you for your help.

            • 3. CoordinationContext
              jhalliday

              > You propose the use of txBridge, by obtaining JBossTS 4.6.1.GA_CP07. I do not seem to be able to locate it anywhere. How can I obtain this version of JBossTS?

               

              The instructions are actually not quite right, since the JBossTS 4.6.1 line used by JBossAS 5.1 actually pre-dates the move of the txbridge code from its independent prototype repo into the main TS source tree. Your options are: use AS 6, which support a newer TS version with the full featured bridge, or stay on AS 5.x and use the obsolete prototype bridge that has no crash recovery.

               

              (for AS6) http://anonsvn.jboss.org/repos/labs/labs/jbosstm/tags/JBOSSTS_4_14_0_Final/txbridge/

              (for AS5) http://anonsvn.jboss.org/repos/labs/labs/jbosstm/workspace/jhalliday/txbridge/