Recent Blog Entries

Thursday, 12 August 2010

Web Service Transactions Part 1: WS-AtomicTransaction with EJB-based Webservices and WLS 11gR1

To make it clear at first: I am not a fan of web service transactions. They contradict the principle of loose coupling in a SOA. But it is like with XA and 2PC – there are situations where you want to use them or where it is almost mandatory.

In SOA there have been concepts like compensation in BPEL to avoid atomic transactions spanning several SOAP calls (before they were possible and available technically) but some business requirements do not allow to commit at first and undo later on.

Also, Oracle SOA Suite optimizes local calls, so transactions were possible over multiple service invocations if they are on the same application server instance (see optSoapShortcut property in 10g)

To allow web services with SOAP using transactions like in EJB-based distributed applications the following standards have been published by OASIS (http://www.oasis-open.org/specs/):

  • WS-AtomicTransaction v1.2
  • WS-BusinessActivity v1.2
  • WS-Coordination v1.2

    The latest version 1.2 was published in February 2009 and WS-Coordination and WS-AtomicTransaction support started in Weblogic Server 11gR1 (10.3.3) and Oracle Soa Suite 11g PS2 (11.1.1.3). WS-BusinessActivity is for long running business transactions and therefore not covered here.

    With WS-AtomicTransaction (abbreviated WS-AT) it is possible to call another web service (callee) from a web service (caller) within the same transaction. The transaction context is passed to the other web service via soap in a CoordinationContext structure in the SOAP header. Some other components work together as outlined here to let the second web service participate in the transaction.

    Let’s have a look at how you can setup a transaction spanning 2 or more web services.

    The first scenario we will look at is when you have implemented 2 web service based on JAX-WS EJBs in Weblogic and you want to call the one from the other.

    A good startup example for WS-AtomicTransaction is included in the Weblogic Server 11gR1 installation when you select custom install and include the "Server Samples” for installation. Then you can move to %WLS_HOME%\wlserver_10.3\samples\server\examples\src\examples\webservices\jaxws\wsat.

    After setting the examples environment, compiling and deploying with ant you will see the Bank application:

    ws-at-sample

    You can enter for example local account number 100 and remote account number 100 with initial amounts of 100 USD.Then try to transfer 20 USD from local to remote account. This is done in one atomic transaction.

    The application consists of one servlet which makes modifications on the local account and then calls the web service for the remote  located at

    http://host:port/WsatBankTransferService/WsatBankTransferService

    The wsdl is available at

    http://host:port/WsatBankTransferService/WsatBankTransferService?WSDL

    To be able to see the SOAP request to the web service I have put TcpMon  inbetween: change the following lines in WsatBankTransferServlet.java to map the TcpMon port (i.e. 8081):

    public void doPost(HttpServletRequest request,HttpServletResponse response)

               throws ServletException, IOException {

        // define remote Webservice server
        String url = "
    http://localhost:8081";
        URL wsdlURL = new URL(url + "/WsatBankTransferService/WsatBankTransferService");

    The SOAP request looks like follows – the WS-AT specific parts are contained in the CoordinationContext structure:

    <?xml version='1.0' encoding='UTF-8'?>
    <S:Envelope xmlns:S="
    http://schemas.xmlsoap.org/soap/envelope/">
      <S:Header>
        <To xmlns="
    http://www.w3.org/2005/08/addressing">http://localhost:8081/WsatBankTransferService/WsatBankTransferService</To>
        <Action xmlns="
    http://www.w3.org/2005/08/addressing">http://tempuri.org/WsatBankTransferService/createAccountRequest</Action>
        <ReplyTo xmlns="
    http://www.w3.org/2005/08/addressing">
          <Address>
    http://www.w3.org/2005/08/addressing/anonymous</Address>
        </ReplyTo>
        <FaultTo xmlns="
    http://www.w3.org/2005/08/addressing">
          <Address>
    http://www.w3.org/2005/08/addressing/anonymous</Address>
        </FaultTo>
        <MessageID xmlns="
    http://www.w3.org/2005/08/addressing">uuid:a64a702b-0ce6-40fc-9b12-71a494c41520</MessageID>
        <CoordinationContext xmlns:ns3="
    http://schemas.xmlsoap.org/soap/envelope/"
                             xmlns:ns2="http://schemas.xmlsoap.org/ws/2004/08/addressing"
                             xmlns="http://schemas.xmlsoap.org/ws/2004/10/wscoor"
                             ns3:mustUnderstand="1">
          <Identifier>urn:uuid:BEA1-0070D4A7F05CBD76B51F</Identifier>
          <Expires>900000</Expires>
          <CoordinationType>
    http://schemas.xmlsoap.org/ws/2004/10/wsat</CoordinationType>
          <RegistrationService>
            <ns2:Address>
    http://192.168.56.110:7001/wls-wsat/RegistrationPortTypeRPC</ns2:Address>
            <ns2:ReferenceParameters>
              <wls-wsat:txId xmlns:wls-wsat="
    http://weblogic.wsee.wstx.wsat/ws/2008/10/wsat">BEA1-0070D4A7F05CBD76B51F</wls-wsat:txId>
              <wls-wsat:routing xmlns:wls-wsat="
    http://weblogic.wsee.wstx.wsat/ws/2008/10/wsat">examplesServer</wls-wsat:routing>
            </ns2:ReferenceParameters>
          </RegistrationService>
        </CoordinationContext>

      </S:Header>
      <S:Body>
        <ns2:createAccount xmlns:ns2="
    http://tempuri.org/">
          <arg0>222</arg0>
          <arg1>0</arg1>
        </ns2:createAccount>
      </S:Body>
    </S:Envelope>

    More details regarding the implementation:

    The WsatBankTransferService bean contains the following annotations to enable WS-AT:

    @WebService(serviceName = "WsatBankTransferService", targetNamespace = "http://tempuri.org/", portName = "WSHttpBindingIService")
    @Transactional(value=Transactional.TransactionFlowType.MANDATORY,
               version=weblogic.wsee.wstx.wsat.Transactional.Version.WSAT10)

    Each method of the webservice looks up the JTA user transaction (if available):

    ctx = new InitialContext();
    tx = (UserTransaction)ctx.lookup("javax.transaction.UserTransaction");

    The servlet passes the TransactionalFeature to the web service as documented in

    Oracle® Fusion Middleware Programming Advanced Features of JAX-WS Web Services for Oracle WebLogic Server – Chapter 3: Using Web Services Atomic Transactions

    // Passing the TransactionalFeature to the Client
    private WsatBankTransferService getWebService(URL wsdlURL) {
      TransactionalFeature feature = new TransactionalFeature();
      feature.setFlowType(TransactionFlowType.MANDATORY);
            feature.setVersion(Version.WSAT10);
            WsatBankTransferService_Service service =
                    new WsatBankTransferService_Service(wsdlURL,
                        new QName("
    http://tempuri.org/", "WsatBankTransferService"));
      return service.getWSHttpBindingIService(new javax.xml.ws.soap.AddressingFeature(), feature);

    In the next parts we will call the WsatBankTransferService from a SOA Composite and we will span atomic transactions over multiple SOA composites.

  • No comments:

    Post a Comment