Atomic Transaction basics

Think of a hypothetical web service that provides banking services. The service provides 2 operations: a credit operation and a debit operation. Now if the two operations are to be used to perform a monetary transfer between two accounts, it must be ensured that both operations succeed. Under these circumstances, the web services coordination framework can be used to ensure the atomicity of operations.

The sample code below shows how a non-J2EE client may use the Kandula implementation in this scenario.

import org.apache.kandula.coordinator.at.TransactionManagerImpl;

public class ...  {
    
    public ... foo(....) {
        Bank bank= new BankServiceLocator().getBank();
        TransactionManagerImpl tm =
            TransactionManagerImpl.getInstance();
        tm.begin();
        try {
            bank.credit(1001, 10);
            bank.debit(1002, 10);
        }catch (Exception e) {
            tm.rollback();
        }
        tm.commit();
    }
}

Though the web services coordination framework is platform independent, participant services unavoidably need to use platform-specific technologies to perform transactional work. For instance, if the banking service mentioned above is implemented in J2EE, its would use JTA. Hence in the context of coordinated activities, the underlying JTA runtime is required to coordinate with an external coordinator to decide if and when to make any work performed as part of such activities, persistent. In this scenario, Kandula interposes between the local JTA implementation and external coordinator to allow transactions to be propagated to and from J2EE to web services domain.

To illustrate the point further, consider how the same use case illustrated above would be implemented by a J2EE client.

public class ... implements SessionBean {
    private SessionContext ctx;

    public ... foo(....) {
        Bank bank= new BankServiceLocator().getBank();
        UserTransaction ut= ctx.getUserTransaction();
        ut.begin();
        try {
            bank.credit(1001, 10);
            bank.debit(1002, 10);
        }catch (Exception e) {
            ut.rollback();
        }
        ut.commit();
    }
}

Notice that the component uses JTA to ensure atomicity of operations. At runtime however, the transaction context of the calling thread is propagated to the remote service using the web services coordination framework.

How to download and build

  1. Checkout Kandula1 from the svn repository using an svn client at the following URL: https://svn.apache.org/repos/asf/webservices/kandula/branches/Kandula_1/. Let us call the directory to which you checked out Kandula1, KANDULA_HOME.

  2. Download and install Apache Tomcat. (5.0 or later required).

  3. Download and install Apache Axis (1.3 or later required). Do NOT deploy Kandula on a version of Axis different from the version on which it was built. Rebuild Kandula if this is required on the required version by modifying the build files. However, you may use different Axis versions on client/server ends.

  4. Download and install Apache Maven 1.x (2.0 not supported).

  5. Download and install Apache Ant (1.6.5 or later).

  6. Set the kandula.context property in %KANDULA_HOME%/src/conf/kandula.properties, to the context under which services are deployed in Axis. Normally this is: http://localhost:8080/axis/services/

  7. Build Kandula using Maven. Use the command maven in %KANDULA_HOME%. This will create the directory %KANDULA_HOME%/target. You will find the kandula-0.2-SNAPSHOT.jar along with all other required *.jar files in the directory %KANDULA_HOME%/target/lib.

  8. To build the sample applications, move to each of the sample directories in %KANDULA_HOME%/src/samples/ and use the command ant dist.

How to deploy

  1. Move all Apache Axis jars from %AXIS_DEPLOY%/WEB-INF/lib to %TOMCAT_HOME%/shared/lib.

  2. Move all geronimo-*.jar files, addressing-SNAPSHOT.jar and kandula-0.2-SNAPSHOT.jar to %TOMCAT_HOME%/shared/lib.

  3. Copy the *.jar file in the build directory of each sample application to %AXIS_DEPLOY%/WEB-INF/lib.

  4. Copy the server-config.wsdd file in %KANDULA_HOME%/src/conf/ to %AXIS_DEPLOY%/WEB-INF/.

  5. Copy the client-config.wsdd file in %KANDULA_HOME%/src/conf/ to %AXIS_DEPLOY%/WEB-INF/classes.

  6. Start Tomcat. To assure that Kandula has been properly deployed, first list all deployed services in Axis from the "Happy Axis" page and then verify that you can view the WSDL of each service.

How to run the sample applications

Sample applications reside in the directory %KANDULA_HOME%/src/samples. The Axis artifacts necessary to deploy all the samples are also included in %KANDULA_HOME%/src/conf/server-config.wsdd. Hence unless you deploy the samples along with Kandula, you need to remove those elements from the server-config.wsdd file copied to %AXIS_DEPLOY%/WEB-INF/ before you start Tomcat. Further, different samples use different handlers. You need to change your handler configuration as appropriate when you try out a particular sample application.

How to setup the TCP sniffer

The default configuration of Kandula assumes that you will use a TCP sniffer such as the "tcpmon" tool that comes with Apache Axis to monitor TCP traffic while running the sample applications. We also assume that Tomcat would be run on port 8080 and services in Axis are deployed under the URL: http://localhost:8080/axis/services/. Hence, to facilitate monitoring of traffic, all Stubs in Kandula forward messages that would otherwise be forwarded to port 8080 to port 8081.

Therefore, inorder to run the samples (or any other application that uses Kandula in the default setting) you MUST forward port 8081 (of your local machine) to port 8080.

You can change this behaviour by editing the WSDL files in %KANDULA_HOME%/src/schema/ and rebuilding Kandula thereafter.

Test-suite1

This sample application demostrates how to use Kandula to initiate and terminate transactions using the WS-AtomicTransaction protocol. It also demostrates the behaviour of Kandula under a number of failure scenarios. Note that we use pseudo XAResouces instead of actual applications such as Databases, Messaging etc. to simplify the testing process. Hence the application explicitly enlists all XAResources used in operations. This would not be the case with real applications however. The container would normally takecare of this for you, transparently.

The most important aspect of this sample application is that it demostrates how Kandula can be used to expose transactional resources in a J2EE environment via the web services transaction management framework. After the revision of code in December 2005, Kandula1 now supports ONLY the "Geronimo" Transaction Manager. The required jars are automatically downloaded by Maven during the build process.

To run the sample, do the following.

  1. First ensure that the transaction handler used in your %AXIS_DEPLOY%/WEB-INF/classes/client-config.wsdd is org.apache.kandula.geronimo.TxHandler.

  2. Next open up the JUnit test case provided in the src directory in your favourite IDE. This file contains a number of test cases. Each test case should be run on its own. If you run a number of test cases this would result in a whole lot of messages which would be rather difficult to interpret. Also note that some of the test scenarios are positive tests while some others are negative. A short description of the success criteria of most of the test cases can be found in the success-criteria.txt file in %KANDULA_HOME%/src/samples/test-suite1/.

  3. To run the test cases use the standard JUnit test harness of your IDE.

InteropIBM

The objective of this sample application is to test Kandula against IBM WS-AtomicTransaction implementation for interoperability. For details on interoperability test, please refer to the documentation available from: http://wsi.alphaworks.ibm.com:8080/interop/index.html . We suggest that you read through this specification before moving on since some of the terminology used in the following section is explained in the specification.

The sample allows you to exercies Kandula in both IA (Initiator Application) and PA (Participant Application) configurations. We have successfully tested Kandula in IA role against the IBM implementation in PA role for all scenarios except those that involve WS-Security. Testing under the opposite configuration is still under way. From the tests carried out thus far, Kandula in PA role interoperates with IBM successfully in all scenarios upto Section 5.0 of the test scenario specification.

To run this sample, you need to use org.apache.kandula.coordinator.at.TxHandler in your %AXIS_DEPLOY%/WEB-INF/classes/client-config.wsdd. Most importantly you MUST have an externally visible URL for your web container. If not, you may setup and HTTP tunnel. However, in this case you must set the kandula.context property to the externally visible URL. If neither option is available, you may still run the sample using Kandula in both IA and PA configurations simultaniously. The resulting message exchanges SHOULD still comply with the documented success criteria.

Further, in this particular scenario, the Kandula1 Stubs are pre-configured to forward any messages addressed to http://wsi.alphaworks.ibm.com:8080/ to http://localhost:8082/. This allows you to monitor all outgoing traffic. So before you run the sample forward the port 8082 of your local machine to http://wsi.alphaworks.ibm.com:8080/

To test Kandula in PA role follow the steps below.

  1. Deploy the sample and start Tomcat. Ensure that InteropService is listed (along with its operations) under deployed services in Axis and that you are able to view the WSDL.

  2. Open the page http://wsi.alphaworks.ibm.com:8080/wstx/interop.jsp in your web browser.

  3. Enter the URL of your "InteropService" as the participant destination. Here, if you want to monitor incoming traffic, change the port from 8080 to 8081 when entering the URL and forward port 8081 to 8080 as before.

  4. Select the test scenario you want to run. Do not select scenarios from Sections 5.0 or later since these have not been tested yet under this setting.

  5. Select run test.