Saturday, April 28, 2012

Configuring JMS Transaction Rollback in WSO2ESB

WSO2 ESB supports transactions in two ways..
  • Transaction mediator
  • JMS transport transaction

Here lets have a look on how we can use jms transport transaction to roll back the transactions in case of failures..
In my previous post, i explained how can we configure a proxy to listen to a particular queue..
Here , we'll  add two more additional parameters, to make it rollback the transaction when failures occur..

  1. Add a service level parameter to enable local JMS transaction...
 <parameter name="transport.jms.SessionTransacted">true</parameter>
You can define this parameter at your transport configuration, which is defined in the axis2 configuration..
Service level parameters will overwrite the transport level parameters..
 
    2. Add "SET_ROLLBACK_ONLY" property in the mediation flow(ie: @ your InSequence). When failure occurs , this property helps to rollback the local transaction.

    <property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>
Here is the final modified configuration...

<proxy name="ErrorProxy" transports="https http jms" startOnLoad="true" trace="disable">
    <target endpoint="ErrorQueueEndpoint" inSequence="ErrorInSequence" faultSequence="fault"/>
  <parameter name="transport.jms.ContentType">
      <rules>
        <jmsProperty>contentType</jmsProperty>
        <default>text/xml</default>
      </rules>
  </parameter>
  <parameter name="transport.jms.ConnectionFactory">myQueueConnectionFactory</parameter>
  <parameter name="transport.jms.DestinationType">queue</parameter>
  <parameter name="transport.jms.SessionTransacted">true</parameter>
  <parameter name="transport.jms.Destination">errorqueue</parameter>
</proxy>
<sequence name="ErrorInSequence">
   <property name="SET_ROLLBACK_ONLY" value="true" scope="axis2"/>
    <log level="custom">
        <property name="Picked message" value="************"/>
    </log>
   <description/>
</sequence>
<endpoint xmlns="http://ws.apache.org/ns/synapse" name="ErrorQueueEndpoint">
    <address uri="http://localhost:9000/services/SimpleStockQuoteService1">
     <timeout>
       <duration>30000</duration>
       <responseAction>fault</responseAction>
     </timeout>
    </address>
</endpoint>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="fault">
    <log level="full">
        <property name="FAULT SEQ" value="***"/>
        <property name="ERROR_CODE" expression="get-property('ERROR_CODE')"/>
        <property name="ERROR_MESSAGE" expression="get-property('ERROR_MESSAGE')"/>
    </log>
</sequence>
 If you down your endpoint(ie:ErrorQueueEndpoint); you will see that your message will remain the queue..
There is a detail article written by Rajika about the transactions support in WSO2ESB...

Monday, April 2, 2012

Avoiding long classpath issue in Ant

Recently i faced a hard time to fix the long classpath issue which occurred in windows, when we use Ant as our building tool.. I looked for various options in the net but none of them worked..

My initial build script was like this;
 <target name="init">
        <mkdir dir="${class.dir}"/>
        <mkdir dir="./../../work/temp/sampleClient"/>
        <path id="javac.classpath">
            <pathelement path="${class.dir}"/>
              <fileset dir="../../repository/components/plugins">        
                <include name="**/*.jar"/>
            </fileset>
            <fileset dir="../../lib">
                <include name="*.jar"/>
            </fileset>                
        </path>
</target>


<target name="compile" depends="init" description="Compile all Java"> 
        <javac srcdir="src" destdir="${class.dir}" includeantruntime="false" >         
            <classpath refid="javac.classpath"/>         
        </javac>     
</target>
According to following Ant guide[1], Manifestclasspath, which did the trick to solve the windows long classpath  issue



I corrected my script as follows using Manifestclasspath..Here the pathing.jar which contains a single manifest file where all classpaths are defined. In manifest file, to get references for the actual paths, we define another path which contains all the jars locations explicitly defined. Then we can refer the pathing.jar inside our path element, which should be pointed as "javac.classpath's" classpath reference.
Eg:
<path id="jar.classpath">
            <pathelement path="${class.dir}"/>
            <pathelement path="../../lib"/>         
            <fileset dir="../../repository/components/plugins">            
                <include name="**/*.jar"/>
            </fileset>
            <fileset dir="../../lib">
                <include name="*.jar"/>
            </fileset>        
  </path>

<target name="init">
        <mkdir dir="${class.dir}"/>
        <mkdir dir="./../../work/temp/sampleClient"/>
        <manifestclasspath property="tem.classpath" jarfile="pathing.jar">
            <classpath refid="jar.classpath"/>
        </manifestclasspath>      
        <jar destfile="pathing.jar" basedir="target\classes">
            <manifest>            
                <attribute name="Class-Path" value="${tem.classpath}"/>
            </manifest>
        </jar>
        <path id="javac.classpath">
            <pathelement path="${class.dir}"/>
            <pathelement path="pathing.jar"/>          
        </path>
 </target>

 <target name="compile" depends="init" description="Compile all Java">
        <javac srcdir="src" destdir="${class.dir}" includeantruntime="false">
            <classpath refid="javac.classpath"/>
        </javac>
  </target>

[1]http://ant.apache.org/manual/Tasks/manifestclasspath.html