JMS Transactions
In addition to the transaction mediator, WSO2 ESB also supports JMS transactions. The JMS transport shipped with WSO2 ESB supports both local and distributed JMS transactions. You can use local transactions to group messages received in a JMS queue. Local transactions are not supported for messages sent to a JMS queue.
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.
JMS Local Transaction Configuration
To start a local JMS transaction, define the following property in JMS Transport Listner/Sender in axis2.xml
:
<parameter name="transport.jms.SessionTransacted">true|false</parameter>
By default the session is not transacted and if you want to use JMS local transaction set the above parameter to true
. And you need to set the following property in Synpase fault handler to rollback the transaction in case of a failure.
<property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>
If you are using a JMS Inbound endpoint for the transaction, set the scope of the SET_ROLLBACK_ONLY
property to default
as follows:
<property name="SET_ROLLBACK_ONLY" scope="default" type="STRING" value="true"/>
JMS Distributed Transaction
The WSO2 ESB also has the support for distributed JMS transaction. You can use JMS Transport with more than one distributed resources( for example a JMS queue and a remote database server).
The Transaction Mediator can be used to mark a distributed transaction which involves a distribution transaction which span through multiple JMS resources.
Scenario
In the following scenario, a message will be read from a JMS queue and it will be processed by a back end service. While executing one sequence, ESB will receive a fault and this will cause the JMS transaction to rollback. In the successful scenario, the transaction will be committed and the request will be sent to the back end service. In the following configuration, there is a Class Mediator which will set a property called MESSAGE_COUNT
to the message context and it will demonstrate this behavior. Depending on the value of this variable the decision to either commit or rollback the transaction will be taken. You can download the binary ZIP of the mediator from here. Drop this mediator to $ESB_HOME/repository/components/lib
.
The source of the mediator looks as shown below.
public class MessageCounterMediator extends AbstractMediator { private static int MESSAGE_COUNT = 0; public boolean mediate(MessageContext synCtx) { MESSAGE_COUNT++; synCtx.setProperty("MESSAGE_COUNT", MESSAGE_COUNT); return true; } }
ESB configuration is given below.
<proxy name="StockQuoteProxy" transports="jms" startOnLoad="true"> <target> <inSequence> <class name="org.wso2.carbon.mediator.MessageCounterMediator"/> <switch source="get-property('MESSAGE_COUNT')"> <case regex="1"> <property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/> <log level="custom"> <property name="Transaction Action" value="Rollbacked"/> </log> </case> <default> <log level="custom"> <property name="Transaction Action" value="Committed"/> </log> <send> <endpoint name="endpoint_urn_uuid_677F3EF4BC0AE1AF5B32399295906279-2025938318"> <address uri="http://localhost:9000/services/SimpleStockQuoteService"/> </endpoint> </send> </default> </switch> <property name="OUT_ONLY" value="true"/> </inSequence> </target> <publishWSDL uri="file:repository/samples/resources/proxy/sample_proxy_1.wsdl"/> <parameter name="transport.jms.ContentType"> <rules> <jmsProperty>contentType</jmsProperty> <default>application/xml</default> </rules> </parameter> </proxy>
To start a local JMS transaction, define the following property in JMS transport Listner in axis2.xml
:
<parameter name="transport.jms.SessionTransacted">true</parameter>
By default, the session is not transacted and if you want to use JMS local transaction, set the above parameter to true. Also note the following property in the failure case which will roll back the local transaction.
<property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>
Running the Example
Note
You do not need to deploy the ESB on JBOSS to run this sample since this does not require any distributed transaction manager as in other cases.
1. Copy the JMS client JARs (activemq-core-5.2.0.jar, geronimo-j2ee-management_1.0_spec-1.0.jar, geronimo-jms_1.1_spec-1.1.1.jar) into the following location:
$ESB_HOME/repository/components/lib
.
2. Start the activemq server.
3. Deploy and start the SimpleStockQuoteService
service. Get the SimpleStockQuoteService
service attach with this article (SimpleStockQuoteService.aar) and place it in $ESB_HOME/samples/axis2Server/repository/services
.
4. Start WSO2 ESB with above configuration.
5. Run the JMS client with following command:
ant jmsclient -Djms_type=pox -Djms_dest=dynamicQueues/StockQuoteProxy -Djms_payload=MSFT
When you run the client, you can see two log lines saying that first time the traction was rolled back and in the second attempt the transaction was committed. And service will be served to the message received.
Distributed JMS Transaction
WSO2 ESB has the support for distributed JMS transaction. In this case, you can use the Transaction Mediator to manage multiple distributed resources. An ideal candidate for this category would be handling a JMS queue and a data base server using a single transaction. A sample configuration will be very similar to the distributed transaction example configuration given in the section on distributed transactions.