This documentation is for WSO2 Enterprise Service Bus version 4.7.0 . View documentation for the latest release.
Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

In addition to the Transaction Mediator, WSO2 ESB also has support for JMS transactions. WSO2 ESB comes with a default JMS transport, which supports both local and distributed JMS transactions. In a JMS client, we use local transactions to group message sends and receives. The JMS API Session interface provides commit and rollback methods that you can use in a JMS client.

This section covers:

JMS Local Transaction

A local transaction represents a unit of work on a single connection to a data source managed by a resource manager. In JMS, we can use the JMS API to get a transacted session and call methods for commit or rollback for the relevant transaction objects. This is managed internal to a resource manager. There is no external transaction manager involved in the coordination of such transactions.

Let's demonstrate, through a sample scenario, how to handle Transaction using JMS in a situation where the back-end service is unreachable.

Sample Scenario

The sample scenario is as follows:

  1. A message will be read from a JMS queue and it will be processed by a back-end service.
  2. Failure scenarios: While executing one sequence, if a failure occurs, ESB will receive a fault and this will cause the JMS transaction to rollback.
  3. Successful scenario: The transaction will be committed and the request will be sent to the back-end service.

The scenario is depicted in the diagram below.

Let's see how to build and invoke this sample scenario in the ESB. Before proceeding, refer to the Prerequisites section in ESB Samples Setup.

Building the Sample Scenario

1. First, configure the JMS local transaction.To start a local JMS transaction, define the following property in JMS Transport Listener in <ESB HOME>/repository/conf/axis2/axis2.xml. By default the session is not transacted. In order to make it transacted, set the following parameter to true.  

<parameter name="transport.jms.SessionTransacted">true</parameter>

Once done, the axis.xml file should look as follows,

...
<transportReceiver name="jms" class="org.apache.axis2.transport.jms.JMSListener">
       <parameter name="myTopicConnectionFactory" locked="false">
           <parameter name="java.naming.factory.initial" locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
           <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</parameter>
           <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">TopicConnectionFactory</parameter>
        <parameter name="transport.jms.ConnectionFactoryType" locked="false">topic</parameter>
        <parameter name="transport.jms.SessionTransacted">true</parameter>
       </parameter>
 
       <parameter name="myQueueConnectionFactory" locked="false">
           <parameter name="java.naming.factory.initial" locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
           <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</parameter>
           <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">QueueConnectionFactory</parameter>
        <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>
        <parameter name="transport.jms.SessionTransacted">true</parameter>
       </parameter>
 
       <parameter name="default" locked="false">
           <parameter name="java.naming.factory.initial" locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
           <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</parameter>
           <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">QueueConnectionFactory</parameter>
        <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>...
        <parameter name="transport.jms.SessionTransacted">true</parameter>
       </parameter>
   </transportReceiver>

2) Set the synapse configuration. For example, in the following configuration, the message will be taken from the JMS queue and send to SimpleStockQuoteService running on the Axis2 back-end server. If it fails to achieve the task, the message will be rolledback.
 
The source of the ESB Configuration is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://ws.apache.org/ns/synapse">
  <proxy name="StockQuoteProxy" transports="jms" startOnLoad="true">
     <target>
        <inSequence>
           <property name="ClientApiNonBlocking" scope="axis2" action="remove"/>
           <property name="OUT_ONLY" value="true"/>
           <log level="custom">
              <property name="Transaction Action" value="Committed"/>
           </log>
           <send>
              <endpoint>
                 <address uri="http://localhost:9000/services/SimpleStockQuoteService"
                          format="pox"/>
              </endpoint>
           </send>
        </inSequence>
        <faultSequence>
           <property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>
           <log level="custom">
              <property name="Transaction Action" value="Rollbacked"/>
           </log>
        </faultSequence>
     </target>
     <parameter name="transport.jms.ContentType">
        <rules>
           <jmsProperty>contentType</jmsProperty>
           <default>application/xml</default>
        </rules>
     </parameter>
  </proxy>
  <sequence name="fault">
     <log level="full">
        <property name="MESSAGE" value="Executing default &#34;fault&#34; sequence"/>
        <property name="ERROR_CODE" expression="get-property('ERROR_CODE')"/>
        <property name="ERROR_MESSAGE" expression="get-property('ERROR_MESSAGE')"/>
     </log>
     <drop/>
  </sequence>
  <sequence name="main">
     <log/>
     <drop/>
  </sequence>
</definitions>

In case of handle failure, the property SET_ROLLBACK_ONLY has to be set to true in Synapse fault handler to rollback the transaction.For example,

<property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>

3.  Deploy the back-end service SimpleStockQuoteService and start the Axis2 server using the instructions given in section Starting Sample Back-End Servicese.
 
You now have a running ESB instance, ActiveMQ and a sample back-end service to simulate the sample scenario. Next, proceed to client JMS execution.
 

Executing the Sample Scenario

We have described below both the successful and failure scenarios.

Successful Scenario

4. Run the sample JMS Client by executing following ant command from <ESB_HOME>/samples/axis2Client directory. This will trigger a sample message to the JMS Server.
 

ant jmsclient -Djms_type=pox -Djms_dest=dynamicQueues/StockQuoteProxy -Djms_payload=MSFT

 If the message is mediated successfully, it should display an output on the Axis2 server's start-up console. For example,

5. Note, on the ESB's debug log, a message of type INFO that indicates that the transaction is committed. For example,

Failure Scenario

6. In order to simulate the failure scenario, stop the sample Axis2 Server and run the same code snippet given for JMS client in step 4 above.
 
7. Note that WSO2 ESB log shows a message as follows:

JMS Distributed Transaction

The WSO2 ESB also has support for distributed JMS transactions. You can use JMS Transport with more than one distributed resources (for example, a JMS queue and a remote database server). An external transaction manager coordinates the transaction. Designing and using JMS distributed transactions is more complex than using local JMS transactions.

The Transaction Mediator can be used to mark a distributed transaction, which involves a distribution transaction that spans through multiple JMS resources. The transaction manager is the primary component of the distributed transaction support infrastructure. However, the JDBC driver (the resource adapter) and the application server (in which you deploy the applications) should have the following two characteristics:

  • The driver should implement the JDBC 2.0 API (including the optional package interfaces XADataSource and XAConnection) or higher, and the JTA interface XAResource.
  • The application server should provide a Datasource class that is implemented to interact with the distributed transaction infrastructure and a connection pooling model for performance improvements.

When JMS transactions are in place, local transactions are managed by the JMS provider itself whereas the distributed JMS transactions are managed by the XAResource enabled transaction manager in the J2EE application server.

Note

Check if your application server provides a XAConnectionFactory when you look for the ConnectionFactory.

  • No labels