Links: Table of Contents | Single HTML | Single PDF

Chapter 18. Using Atomic Transactions

Table of Contents

18.1. Using Web Services Atomic Transactions
18.1.1. Overview of Web Services Atomic Transactions
18.1.2. Enabling Web Services Atomic Transactions on Web Service Endpoint
18.1.3. Enabling Web Services Atomic Transactions on Web Service Clients
18.1.4. System Level Configuration
18.1.5. Compatibility
18.2. About the basicWSTX Example
18.3. Building, Deploying and Running the basicWSTX Example

18.1. Using Web Services Atomic Transactions

This section describes how to use Web services atomic transactions to enable interoperability with other external transaction processing systems.

18.1.1. Overview of Web Services Atomic Transactions

Web services enable interoperability with other external transaction processing systems, such as WebLogic, Websphere, JBoss, Microsoft .NET, and so on, through the support of the following specifications:

  • Web Services Atomic Transaction (WS-AtomicTransaction) Versions 1.0, 1.1 and 1.2: http://docs.oasis-open.org/ws-tx/wstx-wsat-1.2-spec-cs-01/wstx-wsat-1.2-spec-cs-01.html

  • Web Services Coordination (WS-Coordination) Versions 1.0, 1.1 and 1.2: http://docs.oasis-open.org/ws-tx/wstx-wscoor-1.2-spec-cs-01/wstx-wscoor-1.2-spec-cs-01.html

These specifications define an extensible framework for coordinating distributed activities among a set of participants. The coordinator, shown in the following figure, is the central component, managing the transactional state (coordination context) and enabling Web services and clients to register as participants.

Figure 18.1. Web Services Atomic Transactions Framework

Web Services Atomic Transactions Framework

The following table describes the components of Web services atomic transactions, shown in the previous figure.

Table 18.1. Components of Web Services Atomic Transactions

Component

Description

Coordinator

Manages the transactional state (coordination context) and enables Web services and clients to register as participants.

Activation Service

Enables the application to activate a transaction and create a coordination context for an activity. Once created, the coordination context is passed with the transaction flow.

Registration Service

Enables an application to register as a participant.

Application Protocol X, Y

Supported coordination protocols, such as WS-AtomicTransaction.


The following figure shows two server instances interacting within the context of a Web services atomic transaction.

Figure 18.2. Atomic Transaction - Interaction between two Servers

Atomic Transaction - Interaction between two Servers

Please note the following:

  • Using the local JTA transaction manager, a transaction can be imported to or exported from the local JTA environment as a subordinate transaction, all within the context of a Web service request.

  • Creation and management of the coordination context is handled by the local JTA transaction manager.

  • All transaction integrity management and recovery processing is done by the local JTA transaction manager.

The following describes a sample end-to-end Web services atomic transaction interaction:

  1. Application A begins a transaction on the current thread of control using the JTA transaction manager on Server A.

  2. Application A calls a Web service method in Application B on Server B.

  3. Server A updates its transaction information and creates a SOAP header that contains the coordination context, and identifies the transaction and local coordinator.

  4. Server B receives the request for Application B, detects that the header contains a transaction coordination context and determines whether it has already registered as a participant in this transaction. If it has, that transaction is resumed and if not, a new transaction is started.

    Application B executes within the context of the imported transaction. All transactional resources with which the application interacts are enlisted with this imported transaction.

  5. Server B enlists itself as a participant in the WS-AtomicTransaction transaction by registering with the registration service indicated in the transaction coordination context.

  6. Server A resumes the transaction.

  7. Application A resumes processing and commits the transaction.

18.1.2. Enabling Web Services Atomic Transactions on Web Service Endpoint

To enable Web services atomic transactions on a Web service endpoint:

  • When starting from Java (bottom-up), add the @com.sun.xml.ws.api.tx.at.Transactional annotation to the Web service endpoint implementation class or method.

The following tables summarizes the configuration options that you can set when enabling Web services atomic transactions:

Table 18.2. Web Services Atomic Transactions Configuration Options

Attribute

Description

Version

Version of the Web services atomic transaction coordination context that is used for Web services and clients. For clients, it specifies the version used for outbound messages only. The value specified must be consistent across the entire transaction.

Valid values include WSAT10, WSAT11, WSAT12, and DEFAULT. The DEFAULT value for Web services is all three versions (driven by the inbound request); the DEFAULT value for Web service clients is WSAT12.

Flow type

Whether the Web services atomic transaction coordination context is passed with the transaction flow. See table for valid values.


The following table summarizes the valid values for flow type and their meaning on the Web service and client. The table also summarizes the valid value combinations when configuring web services atomic transactions for an EJB-style web service that uses the @TransactionAttribute annotation.

Table 18.3. Flow Types Values

Value

Web Service Client

Web Service

Valid EJB @TransactionAttribute Values

NEVER

JTA transaction: Do not export transaction coordination context.

No JTA transaction: Do not export transaction coordination context.

Transaction flow exists: Do not import transaction coordination context. If the CoordinationContext header contains mustunderstand="true", a SOAP fault is thrown.

No transaction flow: Do not import transaction coordination context.

NEVER, NOT_SUPPORTED, REQUIRED, REQUIRES_NEW, SUPPORTS

SUPPORTS (Default)

JTA transaction: Export transaction coordination context.

No JTA transaction: Do not export transaction coordination context.

Transaction flow exists: Import transaction context.

No transaction flow: Do not import transaction coordination context.

REQUIRED, SUPPORTS

MANDATORY

JTA transaction: Export transaction coordination context.

No JTA transaction: An exception is thrown.

Transaction flow exists: Import transaction context.

No transaction flow: Service-side exception is thrown.

MANDATORY, REQUIRED, SUPPORTS


18.1.2.1. Using the @Transactional Annotation in Your JWS File

To enable Web services atomic transactions, specify the @com.sun.xml.ws.api.tx.at.Transactional annotation on the Web service endpoint implementation class or method.

  • If you specify the @Transactional annotation at the Web service class level, the settings apply to all two-way methods defined by the service endpoint interface. You can override the flow type value at the method level; however, the version must be consistent across the entire transaction.

  • You cannot explicitly specify the @Transactional annotation on a Web method that is also annotated with @Oneway.

  • Web services atomic transactions cannot be used with the client-side asynchronous programming model.

The format for specifying the @Transactional annotation is as follows:

Example 18.1. @Transactional annotation format

@Transactional(
    version=Transactional.Version.[WSAT10|WSAT11|WSAT12|DEFAULT],
    value=Transactional.TransactionFowType.[MANDATORY|SUPPORTS|NEVER]
)

For more information about the version and flow type configuration options, see Table.

The following sections provide examples of using the @Transactional annotation at the Web service implementation class and method levels, and with the EJB @TransactionAttribute annotation.

18.1.2.1.1. Example: Using @Transactional Annotation on a Web Service Class

The following example shows how to add @Transactional annotation on a Web service class. As shown in the example, there is an active JTA transaction.

Example 18.2. @Transactional Annotation on a Web Service Class

package examples.webservices.jaxws.wsat.simple.service;
. . .
import javax.transaction.UserTransaction;
. . .
import javax.jws.WebService;
import com.sun.xml.ws.api.tx.at.Transactional;
import com.sun.xml.ws.api.tx.at.Transactional.Version;
import com.sun.xml.ws.api.tx.at.Transactional.TransactionFlowType;

/**
 * This JWS file forms the basis of a WS-Atomic Transaction Web Service 
 * with the
 * operations: createAccount, deleteAccount, transferMonet, listAccount
 *
 */
@WebService(serviceName = "WsatBankTransferService", 
        targetNamespace = "http://tempuri.org/",
        portName = "WSHttpBindingIService")
@Transactional(value = Transactional.TransactionFlowType.MANDATORY,
        version = com.sun.xml.ws.api.tx.at.Transactional.Version.WSAT10)
public class WsatBankTransferService {

    public String createAccount(String acctNo, String amount) throws java
            .lang.Exception {

        Context ctx = null;
        UserTransaction tx = null;
        try {
            ctx = new InitialContext();
            tx = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
            try {
                DataSource dataSource = (DataSource) ctx.lookup
                        ("examples-demoXA-2");

                String sql = "insert into wsat_acct_remote (acctno, " +
                        "amount) values (" + acctNo +
                        ", " + amount + ")";

                int insCount = dataSource.getConnection()
                        .prepareStatement(sql).executeUpdate();

                if (insCount != 1)
                    throw new java.lang.Exception("insert fail at remote" +
                            ".");

                return ":acctno=" + acctNo + " amount=" + amount + " " +
                        "creating. ";
            } catch (SQLException e) {
                System.out.println("**** Exception caught *****");
                e.printStackTrace();

                throw new SQLException("SQL Exception during " +
                        "createAccount() at remote.");
            }
        } catch (java.lang.Exception e) {
            System.out.println("**** Exception caught *****");
            e.printStackTrace();
            throw new java.lang.Exception(e);
        }
    }

    public String deleteAccount(String acctNo) throws java.lang.Exception {
        ...
    }

    public String transferMoney(String acctNo, String amount,
                                String direction)
            throws java.lang.Exception {
        ...
    }

    public String listAccount() throws java.lang.Exception {
        ...
    }
}

18.1.2.1.2. Example: Using @Transactional Annotation on a Web Service Method

The following example shows how to add @Transactional annotation on a Web service implementation method.

Example 18.3. @Transactional Annotation on a Web Service Method

package examples.webservices.jaxws.wsat.simple.service;
. . .
import javax.transaction.UserTransaction;
. . .
import javax.jws.WebService;
import com.sun.xml.ws.api.tx.at.Transactional;
import com.sun.xml.ws.api.tx.at.Transactional.Version;
import com.sun.xml.ws.api.tx.at.Transactional.TransactionFlowType;

/**
 * This JWS file forms the basis of a WS-Atomic Transaction Web Service 
 * with the
 * operations: createAccount, deleteAccount, transferMonet, listAccount
 *
 */
@WebService(serviceName = "WsatBankTransferService",
        targetNamespace = "http://tempuri.org/",
        portName = "WSHttpBindingIService")
public class WsatBankTransferService {

    @Transactional(value = Transactional.TransactionFlowType.MANDATORY,
            version = com.sun.xml.ws.api.tx.at.Transactional.Version
                    .WSAT10)
    public String createAccount(String acctNo, String amount) throws java
            .lang.Exception {
        
        Context ctx = null;
        UserTransaction tx = null;
        try {
            ctx = new InitialContext();
            tx = (UserTransaction) ctx.lookup("javax.transaction" + "" +
                    ".UserTransaction");
            try {
                DataSource dataSource = (DataSource) ctx.lookup
                        ("examples-demoXA-2");

                String sql = "insert into wsat_acct_remote (acctno, " +
                        "amount) values (" + acctNo +
                        ", " + amount + ")";

                int insCount = dataSource.getConnection()
                        .prepareStatement(sql).executeUpdate();
                
                if (insCount != 1)
                    throw new java.lang.Exception("insert fail at remote" +
                            ".");
                
                return ":acctno=" + acctNo + " amount=" + amount + " " +
                        "creating. ";
            } catch (SQLException e) {
                System.out.println("**** Exception caught *****");
                e.printStackTrace();
                
                throw new SQLException("SQL Exception during " + 
                        "createAccount() at remote.");
            }
        } catch (java.lang.Exception e) {
            System.out.println("**** Exception caught *****");
            e.printStackTrace();
            throw new java.lang.Exception(e);
        }
    }

    public String deleteAccount(String acctNo) throws java.lang.Exception {
        ...
    }

    public String transferMoney(String acctNo, String amount,
                                String direction)
            throws java.lang.Exception {
        ...
    }

    public String listAccount() throws java.lang.Exception {
        ...
    }
}

18.1.2.1.3. Example: Using the @Transactional and the EJB @TransactionAttribute Annotations Together

The following example illustrates how to use the @Transactional and EJB @TransactionAttribute annotations together. In this case, the flow type values must be compatible.

Example 18.4. @Transactional and the EJB @TransactionAttribute Used Together

package examples.webservices.jaxws.wsat.simple.service;
. . .
import javax.transaction.UserTransaction;
. . .
import javax.jws.WebService;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import com.sun.xml.ws.api.tx.at.Transactional;
import com.sun.xml.ws.api.tx.at.Transactional.Version;
import com.sun.xml.ws.api.tx.at.Transactional.TransactionFlowType;

/**
 * This JWS file forms the basis of a WS-Atomic Transaction Web Service 
 * with the
 * operations: createAccount, deleteAccount, transferMonet, listAccount
 *
 */
@WebService(serviceName = "WsatBankTransferService",
        targetNamespace = "http://tempuri.org/",
        portName = "WSHttpBindingIService")
@Transactional(value = Transactional.TransactionFlowType.MANDATORY,
        version = com.sun.xml.ws.api.tx.at.Transactional.Version.WSAT10)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class WsatBankTransferService {
. . .
}

18.1.2.2. Enabling Web Services Atomic Transactions Starting From WSDL

When enabled, Web services atomic transactions are advertised in the WSDL file using a policy assertion.

This table summarizes the WS-AtomicTransaction 1.2 policy assertions that correspond to a set of common Web services atomic transaction flow type and EJB Transaction attribute combinations.

Web Services Atomic Transaction Policy Assertion Values (WS-AtomicTransaction 1.2)

Table 18.4. Web Services Atomic Transaction Policy Assertion Values (WS-AtomicTransaction 1.2)

Atomic Transaction Flow Type

EJB @TransactionAttribute

WS-AtomicTransaction 1.2 Policy Assertion

MANDATORY

MANDATORY, REQUIRED, SUPPORTS

<wsat:ATAssertion/>

SUPPORTS

REQUIRED, SUPPORTS

<wsat:ATAssertion wsp:Optional="true"/>

NEVER

REQUIRED, REQUIRES_NEW, NEVER, SUPPORTS, NOT_SUPPORTED

No policy advertisement


18.1.3. Enabling Web Services Atomic Transactions on Web Service Clients

On a Web service client, enable Web services atomic transactions using one of the following methods:

  • Add the @com.sun.xml.ws.api.tx.at.Transactional annotation on the Web service reference injection point for a client.

  • Pass the com.sun.xml.ws.api.tx.at.TransactionalFeature as a parameter when creating the Web service proxy or dispatch.

  • At run-time, if the non-atomic transactional Web service client calls an atomic transaction-enabled Web service, then based on the flow type settings:

    • If the flow type is set to SUPPORTS or NEVER on the service-side, then the call is included as part of the transaction.

    • If the flow type is set to MANDATORY, then an exception is thrown.

18.1.3.1. Using @Transactional Annotation with the @WebServiceRef Annotation

To enable Web services atomic transactions, specify the @com.sun.xml.ws.api.tx.at.Transactional annotation on the Web service client at the Web service reference (@WebServiceRef) injection point.

See Using the @Transactional Annotation in Your JWS File for the description of @Transactional annotation format.

The following example illustrates how to annotate the Web service reference injection point. As shown in the example, the active JTA transaction becomes a part of the atomic transaction.

Example 18.5. Using @Transactional Annotation with the @WebServiceRef Annotation

package examples.webservices.jaxws.wsat.simple.client;
. . .
import javax.servlet.*;
import javax.servlet.http.*;
. . .
import java.net.URL;
import javax.xml.namespace.QName;

import javax.transaction.UserTransaction;
import javax.transaction.SystemException;

import javax.xml.ws.WebServiceRef;
import com.sun.xml.ws.api.tx.at.Transactional;
*/

/**
 * This example demonstrates using a WS-Atomic Transaction to create or
 * delete an account,
 * or transfer money via Web service as a single atomic transaction.
 */

public class WsatBankTransferServlet extends HttpServlet {
    ...
    String url = "http://localhost:7001";
    URL wsdlURL = new URL(url + 
            "/WsatBankTransferService/WsatBankTransferService");
    ...
    DataSource ds = null;
    UserTransaction utx = null;

    try {
        ctx = new InitialContext();
        utx = (UserTransaction) ctx.lookup("javax.transaction" +
                ".UserTransaction");
        utx.setTransactionTimeout(900);
    } catch (java.lang.Exception e) {
        e.printStackTrace();
    }

    WsatBankTransferService port = getWebService(wsdlURL);

    try {
        utx.begin();
        if (remoteAccountNo.length() > 0) {
            if (action.equals("create")) {
                result = port.createAccount(remoteAccountNo, 
                        amount);
            } else if (action.equals("delete")) {
                result = port.deleteAccount(remoteAccountNo);
            } else if (action.equals("transfer")) {
                result = port.transferMoney(remoteAccountNo, 
                        amount, direction);
            }
        }
        utx.commit();
        result = "The transaction is committed " + result;
    } catch (java.lang.Exception e) {
        try {
            e.printStackTrace();
            utx.rollback();
            result = "The transaction is rolled back. " + e
                    .getMessage();
        } catch (java.lang.Exception ex) {
            e.printStackTrace();
            result = "Exception is caught. Check stack trace.";
        }
    }
    request.setAttribute("result", result);

    ...
    @Transactional(value = Transactional.TransactionFlowType.MANDATORY,
            version = Transactional.Version.WSAT10)
    @WebServiceRef()
    WsatBankTransferService_Service service;

    private WsatBankTransferService getWebService() {
        return service.getWSHttpBindingIService();
    }

    public String createAccount(String acctNo, String amount) throws 
            java.lang.Exception {
        Context ctx = null;
        UserTransaction tx = null;
        try {
            ctx = new InitialContext();
            tx = (UserTransaction) ctx.lookup("javax.transaction" +
                    ".UserTransaction");
            try {
                DataSource dataSource = (DataSource) ctx.lookup
                        ("examples-dataSource-demoXAPool");
                
                String sql = "insert into wsat_acct_local (acctno, " +
                        "amount) values (
                " + acctNo + ", " + amount + ")";
                        
                int insCount = dataSource.getConnection()
                        .prepareStatement(sql).executeUpdate();
                
                if (insCount != 1)
                    throw new java.lang.Exception("insert fail at " +
                            "local.");
                
                return ":acctno=" + acctNo + " amount=" + amount + " " +
                        "creating.. ";
            } catch (SQLException e) {
                System.out.println("**** Exception caught *****");
                e.printStackTrace();
                
                throw new SQLException("SQL Exception during " +
                        "createAccount() at local.");
            }
        } catch (java.lang.Exception e) {
            System.out.println("**** Exception caught *****");
            e.printStackTrace();
            throw new java.lang.Exception(e);
        }
    }

    public String deleteAccount(String acctNo) throws java.lang.Exception {
        ...
    }

    public String transferMoney(String acctNo, String amount,
                                String direction)
            throws java.lang.Exception {
        ...
    }

    public String listAccount() throws java.lang.Exception {
        ...
    }
}

18.1.3.2. Passing the TransactionalFeature to the Client

To enable Web services atomic transactions on the client of the Web service, you can pass the com.sun.xml.ws.api.tx.at.TransactionalFeature as a parameter when creating the Web service proxy or dispatch, as illustrated in the following example.

Example 18.6. Passing the TransactionalFeature to the Client

package examples.webservices.jaxws.wsat.simple.client;
. . .
import javax.servlet.*;
import javax.servlet.http.*;
. . .
import java.net.URL;
import javax.xml.namespace.QName;

import javax.transaction.UserTransaction;
import javax.transaction.SystemException;

import com.sun.xml.ws.api.tx.at.TransactionalFeature;
import com.sun.xml.ws.api.tx.at.Transactional.Version;
import com.sun.xml.ws.api.tx.at.Transactional.TransactionFlowType;
*/

/**
 * This example demonstrates using a WS-Atomic Transaction to create 
 * or delete an account,
 * or transfer money via Web service as a single atomic transaction.
 */

public class WsatBankTransferServlet extends HttpServlet {
    ...
    String url = "http://localhost:7001";
    URL wsdlURL = new URL(url + 
            "/WsatBankTransferService/WsatBankTransferService");
    ...
    DataSource ds = null;
    UserTransaction utx = null;

    try {
        ctx = new InitialContext();
        utx = (UserTransaction) ctx.lookup("javax.transaction" +
                ".UserTransaction");
        utx.setTransactionTimeout(900);
    } catch (java.lang.Exception e) {
        e.printStackTrace();
    }

    WsatBankTransferService port = getWebService(wsdlURL);

    try {
        utx.begin();
        if (remoteAccountNo.length() > 0) {
            if (action.equals("create")) {
                result = port.createAccount(remoteAccountNo, 
                        amount);
            } else if (action.equals("delete")) {
                result = port.deleteAccount(remoteAccountNo);
            } else if (action.equals("transfer")) {
                result = port.transferMoney(remoteAccountNo, 
                        amount, direction);
            }
        }
        utx.commit();
        result = "The transaction is committed " + result;
    } catch (java.lang.Exception e) {
        try {
            e.printStackTrace();
            utx.rollback();
            result = "The transaction is rolled back.    " + e
                    .getMessage();
        } catch (java.lang.Exception ex) {
            e.printStackTrace();
            result = "Exception is caught. Check stack trace.";
        }
    }
    request.setAttribute("result", result);

    ...

    // 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);
    }

    public String createAccount(String acctNo, String amount) throws 
            java.lang.Exception {
        Context ctx = null;
        UserTransaction tx = null;
        try {
            ctx = new InitialContext();
            tx = (UserTransaction) ctx.lookup("javax.transaction" +
                    ".UserTransaction");
            try {
                DataSource dataSource = (DataSource) ctx.lookup
                        ("examples-dataSource-demoXAPool");
                
                String sql = "insert into wsat_acct_local (acctno, " +
                        "amount) values (
                " + acctNo + ", " + amount + ")";
                        
                int insCount = dataSource.getConnection()
                        .prepareStatement(sql).executeUpdate();
                
                if (insCount != 1)
                    throw new java.lang.Exception("insert fail at " +
                            "local.");
                
                return ":acctno=" + acctNo + " amount=" + amount + " " +
                        "creating.. ";
            } catch (SQLException e) {
                System.out.println("**** Exception caught *****");
                e.printStackTrace();
                
                throw new SQLException("SQL Exception during " +
                        "createAccount() at local.");
            }
        } catch (java.lang.Exception e) {
            System.out.println("**** Exception caught *****");
            e.printStackTrace();
            throw new java.lang.Exception(e);
        }
    }

    public String deleteAccount(String acctNo) throws java.lang.Exception {
        ...
    }

    public String transferMoney(String acctNo, String amount,
                                String direction)
            throws java.lang.Exception {
        ...
    }

    public String listAccount() throws java.lang.Exception {
        ...
    }
}

18.1.4. System Level Configuration

To specify SSL be used for WS-AT protocol exchanges set the wsat.ssl.enabled system property to true, i.e. start the server with -Dwsat.ssl.enabled=true. The default value is false.

To disabled WS-AT transaction logging and recovery set the wsat.recovery.enabled system property to false, i.e. start the server with -Dwsat.recovery.enabled=false. The default value is true.

The WS-C and WS-AT endpoints necessary for WS-AT are deployed only when the first web service is deployed to the container. Therefore, it is necessary to have at least one web service deployed to the target container for WS-AT to function properly even in the case where only clients are used in the Metro instance.

18.1.5. Compatibility

Compatibility between the Metro 2.1 and pre-2.1 (submission version) WS-AT implementions is not supported.

18.2. About the basicWSTX Example

The basicWSTX example shows the following on the client-side:

  1. Developers use existing Java Transaction APIs (JTA). Invocations of transacted web service operations flow transactional context from client to web service. Persistent resources updated with client-created transactions are all committed or rolled back as a single atomic transaction.

  2. After the client-side code commits or aborts the JTA transaction, the client confirms that all operations in the transaction succeeded or failed by using calls to verify methods on the transacted web service.

SampleServiceClient, a WSIT servlet that initiates the transaction, and msclient, a client that performs the same operations but runs on the Microsoft side, both interact with the following components running on the service-side:

  1. SimpleService, a web service implemented as a Java servlet with transacted operations. The Edit Web Service Attributes feature in the NetBeans IDE WSIT plug-in is used to configure Transaction Attributes of each web service operation.

  2. SimpleServiceASCMTEJB, a web service implemented as container-managed transaction enterprise bean (CMT EJB). No configuration is necessary for this case.

  3. LibraryFacadeWebServiceBean, a web service that uses the Java Persistence API (JPA) with two JDBC resources

  4. Managed Java EE resources participating in a distributed transaction having its transacted updates all committed or rolled back

    The servlet and CMT EJB transacted web service operations manipulate two JMS resources:

    • jms/ConnectionFactory, an XATransaction connection factory

    • jms/Queue, a JMS queue

    The LibraryFacadeWebServiceBean web service operations manipulate the JDBC resources:

    • connectionPool, an XATransaction JDBC connection pool

    • jdbc/javaProgrammingLibrary, a JDBC connection resource

This example shows how to use XATransaction -enabled JMS and JDBC. The first version of this example, showing WSIT-to-WSIT operations, has the SampleServiceClient client configured to run on one GlassFish instance and the service running on the other GlassFish instance. Either the Java client or the Java web service could be replaced by a semantically equivalent Microsoft implementation. The Java client is, in fact, replaced by a Microsoft WCF client in the more advanced version of the example.

With the SampleServiceClient client, the WS-Coordination/WS-AtomicTransaction protocol messages flow back and forth between the two GlassFish instances just as they do in the Microsoft-to-Sun transaction interoperability scenario with the msclient client.

The basicWSTX example was initially designed so it could be run in either one or in two GlassFish domains. If you run the example in one domain, only one coordinator is used; no WS-Coordination protocol messages will be exchanged. This chapter explains how to run the example in two domains so both protocols, WS-Coordination and WS-AtomicTransaction (WS-AT), are used, as shown in WS-Coordination and WS-AtomicTransaction Protocols in Two GlassFish Domains.

Figure 18.3. WS-Coordination and WS-AtomicTransaction Protocols in Two GlassFish Domains

WS-Coordination and WS-AtomicTransaction Protocols in Two GlassFish Domains

The example also provides the msclient client, which is the equivalent of the client servlet shown in Domain 2.

Components in the basicWSTX Example shows the components that make up the two domain example. Again, the msclient client would be equivalent to the client servlet in Domain 2 in this figure as well.

Figure 18.4. Components in the basicWSTX Example

Components in the basicWSTX Example

The service, which runs in domain1, is comprised of two components:

  • SimpleService, a web service that is implemented as a servlet with transacted operations

  • SimpleServiceASCMTEJB, a container-managed transaction enterprise bean (CMT EJB) web service

The SimpleService web service uses two JMS resources that are created in domain1:

  • jms/ConnectionFactory, an XATransaction connection factory

  • jms/Queue, a JMS queue

The LibraryFacadeWebServiceBean web service uses the Java Persistence API (JPA) with two JDBC resources that are created in domain1:

  • connectionPool, an XATransaction JDBC connection pool

  • jdbc/javaProgrammingLibrary, a JDBC connection resource

The client servlet, which runs in domain2, initiates the transaction.

18.3. Building, Deploying and Running the basicWSTX Example

Complete the following steps to configure your environment then build, deploy, and run the basicWSTX example.

To Build, Deploy, and Run the basicWSTX Example

  1. Download the wsittutorial.zip sample kit for this example.

  2. Ensure that properties that point to your local Application Server (or GlassFish) and WSIT Tutorial installations have been set.

    1. Copy file tut-install/wsittutorial/examples/bp-project/build.properties.sample to file tut-install/wsittutorial/examples/bp-project/build.properties.

    2. Set the javaee.home and wsit.tutorial.home properties in the file tut-install/wsittutorial/examples/bp-project/build.properties.

    3. Ensure that Application Server (or GlassFish) and at least Ant 1.6.5 have been installed and are on the path.

      Application Server (or GlassFish) includes Ant 1.6.5, which can be found in the as-install/lib/ant/bin directory.

  3. Set up your environment to run the basicWSTX example.

    To configure your environment to run the example:

    1. Change to the tut-install/wsittutorial/examples/wstx/basicWSTX/SampleService directory:

      cd tut-install/wsittutorial/examples/wstx/basicWSTX/SampleService
    2. Issue the following command to configure your environment to run the example:

      ant setup

    This step performs the following configuration tasks for you:

    • Starts domain1.

    • Creates the resources (jms/Queue and XATransaction jms/ConnectionFactory) used in the example.

    • Creates and sets up two Application Server (or GlassFish) domains.

      The domains can be created either on one machine or on two different machines. These steps show you how to do it on one machine. The first domain, domain1, is created as part of the Application Server (or GlassFish) installation.

    • Establishes trust between the two domains by installing each domain's s1as security certificate in the other domain's truststore.

  4. Use the NetBeans IDE to create a database connection.

    1. Start the NetBeans IDE.

    2. In the Services tab, right-click Databases and select New Connection.

      The New Database Connection dialog displays.

    3. Select Java DB (Network) as name

    4. Type localhost in the Host field.

    5. Type 1527 in the Port field.

    6. Type wstxSampleDB in the Database field.

    7. Type app in the User Name field.

    8. Type app in the Password field.

    9. Select the Remember password checkbox.

    10. Click OK.

  5. Register the Application Server (or GlassFish) server instances (domain1 and domain2) in the NetBeans IDE.

    1. If Sun Java System Application Server (domain1) is already registered, go to Step 5j. If it is not, go to Step 4b.

    2. In the Services tab, right-click Servers, and select Add Server.

      The Add Server Instance dialog appears.

    3. Choose the server (Sun Java System Application Server (or GlassFish V2) from the drop-down list and give it a descriptive name, such as Sun Java System Application Server - domain1 (Server), and then click Next.

      The Platform Location dialog displays.

    4. ClickBrowse, navigate to the location where the Application Server (or GlassFish server) is installed, then click Choose.

    5. Make sure that the Register Local Default Domain radio button has been selected.

    6. Use the drop-down list to select domain1, then click Next.

      The Domain Admin Login Info dialog displays.

    7. Type admin in the Admin Username field.

    8. Type adminadmin in the Admin Password field.

    9. Click Finish.

      The server instance you just registered is the one in which you will run the web service (SampleService).

    10. Right-click Servers and select Add Server.

      The Add Server Instance dialog appears.

    11. Choose the server (Sun Java System Application Server (or GlassFish V2) from the drop-down list and give it a descriptive name, such as Sun Java System Application Server - domain2 (Client), and then click Next.

      The Platform Location dialog displays.

    12. ClickBrowse, navigate to the location where the Application Server (or GlassFish server) is installed, then click Choose.

    13. Make sure that the Register Local Default Domain radio button has been selected.

    14. Use the drop-down list to select domain2, then click Next.

      The Domain Admin Login Info dialog displays.

    15. Type admin in the Admin Username field.

    16. Type adminadmin in the Admin Password field.

    17. Click Finish.

      The server instance you just registered is the one in which you will run the web service client (SampleServiceClient).

  6. Open the SampleService project and associate the SampleService web service with the appropriate instance (domain1) of the Application Server (or GlassFish server).

    1. Select File, then Open Project.

    2. Browse to the tut-install/wsittutorial/examples/wstx/basicWSTX/ directory and select the SampleService project.

    3. Select the Open as Main Project check box.

    4. Select the Open Required Projects check box.

    5. Click Open Project.

      The SampleService project and two required projects, SampleService-ejb and SampleService-war, are opened and are shown in the Projects tab.

    6. In the Projects tab, right-click SampleService, select Properties, then select the Run category.

    7. Use the Server drop-down list to point to the default domain, domain1, for the Application Server (or Glassfish) server instance you registered in Step 5.

    8. Click OK.

  7. Resolve references to or add the Toplink Essentials Library to the SampleService-ejb project.

    The SampleService-ejb project references the Toplink Essentials Library Module that is included with NetBeans IDE. To verify whether the reference to this library is resolved in your NetBeans IDE environment:

    1. Right click the SampleService-ejb project and select Properties.

    2. Select the Libraries category.

      You should see Toplink Essentials in the Compile-time Libraries pane of the Compile tab.

    3. If you do not see the library, click Add Library to display the Add Library dialog.

    4. Locate and select Toplink Essentials and then click Add Library.

      You should now see Toplink Essentials in the Compile-time Libraries pane of the Compile tab.

    5. Click OK.

    To verify that you have Toplink Essentials library in NetBeans IDE, select Tools and then Library Manager. You should see "Toplink Essentials" in the left pane. If you don't, you can create the library yourself using the two Toplink JAR files in the Application Server (or GlassFish) lib directory and then resolve the reference to the newly created library.

  8. Set the proper transaction attributes for each mapping (wsdl:binding /wsdl:operation) in the SimpleService-war web service.

    To set the transaction attributes for the SampleService-war web service:

    1. In the Projects tab, expand the SampleService-war node.

    2. Expand the Web Services node.

    3. Right-click Simple Service and select Edit Web Service Attributes.

    4. In the Quality of Service tab, expand the five operation nodes and then expand the method nodes under each operation node. Use the Transaction drop-down list to set the appropriate transaction attribute for each method:

      • Set init to Required.

      • Set publishRequired to Required.

      • Set publishSupports to Supported.

      • Set verify to Required.

      • Set getMessage to Required.

      If any other operations are displayed, ignore them.

    5. Click OK.

      Transaction attributes for SampleServiceASCMTEJB do not need to be set; EJB 3.0 transaction attributes are used.

    The transaction attribute settings for the SampleService-war are stored in the file SampleService\SampleService-war\web\WEB-INF\wsit-wstx.sample.service.Simple.xml.

  9. Deploy the SampleService web service.

    Right-click SampleService and select Undeploy and Deploy. NetBeans IDE will start domain1 and deploy the web service to that domain.

  10. Register the SampleServiceClient client with the appropriate instance (domain2) of the Application Server (or GlassFish) server.

    1. Select File, then Open Project.

    2. Browse to the tut-install/wsittutorial/examples/wstx/basicWSTX/ directory and select the SampleServiceClient project.

    3. Select the Open as Main Project check box.

    4. Select the Open Required Projects check box.

    5. Click Open Project.

      The SampleServiceClient project is opened and is displayed in the Projects tab.

    6. In the Projects tab, right-click SampleServiceClient, select Properties, then select the Run category.

    7. Use the Server drop-down list to point to domain2.

    8. Click OK.

  11. Create web service references for the client (three web service clients, a simpleServlet and two CMT EJB clients) and generate the WSDL for all.

    1. In the Projects tab, right-click SampleServiceClient, select New, then select Web Service Client.

      The New Web Service Client dialog displays.

    2. Click Browse next to the Project field.

      The Browse Web Services dialog displays.

    3. Expand SampleService-war, select Simple, then click OK.

    4. In the Package field, type wstx.sample.client, then click Finish.

    5. Right-click SampleServiceClient, select New, then select Web Service Client.

      The New Web Service Client dialog displays.

    6. Click Browse next to the Project field.

      The Browse Web Services dialog displays.

    7. Expand SampleService-ejb, select SimpleAsCMTEjb, then click OK.

    8. In the Package field, type wstx.sample.ejbclient, then click Finish.

    9. Right-click SampleServiceClient, select New, then select Web Service Client.

      The New Web Service Client dialog displays.

    10. Click Browse next to the Project field.

      The New Web Service Client dialog displays.

    11. Expand SampleService-ejb, select LibraryFacadeWebServiceBean, then click OK.

    12. In the Package field, type wstx.sample.library, then click Finish.

  12. If transaction attributes for the servlet (see Step 7) or CMT EJB web service have changed, those services must be deployed and client web service references refreshed to get new web service attributes.

    To refresh the client web service references for this example:

    1. In the Projects tab, open the SampleServiceClient, then open Web Service References.

    2. Right-click Simple and select Refresh Client to refresh the client node and regenerate the WSDL for the simpleServlet.

    3. Right-click SimpleAsCMTEjb to do the same for the CMT EJB client.

    4. Right-click LibraryFacadeWebServiceBean to do the same for the LibraryFacadeWebServiceBean client.

  13. Deploy and run the client.

    Right-click SampleServiceClient and select Run.

    NetBeans IDE will start domain2, deploy the servlet and EJB CMT clients to that domain, then display the results for both in a pop-up browser window, as shown in basicWSTX Results.

    Figure 18.5. basicWSTX Results

    basicWSTX Results