Thursday, May 10, 2012

Java client to send/receive messages for ActiveMQ

ActiveMQ is a messagebroker supporting JMS 1.1 specification..Here i share a simple java client which can be used to send/browse  messages  in a destination which(ie: queue) is created in ActiveMQ server.
You might need ActiveMQ libraries in your classpath.

import java.util.Enumeration;
import javax.jms.Connection;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.QueueBrowser;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQDestination;

public class ActiveMQTest {
 private static ActiveMQDestination destination;

    public static void offer() throws Exception {

        ActiveMQConnectionFactory connectionFactory =
                                                      new ActiveMQConnectionFactory(
                                                                                    "vm://localhost");

        Connection connection = connectionFactory.createConnection();
        connection.start();
        Session sendSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        destination = (ActiveMQDestination) sendSession.createQueue("TEST.FOO");

        MessageProducer producer = sendSession.createProducer(destination);

        for (int i = 1; i < 5; i++) {
            TextMessage message = sendSession.createTextMessage(String.valueOf(i));
            // Send the messages
            producer.send(message);
            System.out.println("########Sent message : " + message.getText());
        }
        producer.close();
        sendSession.close();
        connection.close();
    }

    public static void peek() throws Exception {

        ActiveMQConnectionFactory connectionFactory =
                                                      new ActiveMQConnectionFactory(
                                                                                    "vm://localhost");

        Connection connection = connectionFactory.createConnection();
        connection.start();

        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        destination = (ActiveMQDestination) session.createQueue("TEST.FOO");
        QueueBrowser browser = session.createBrowser((Queue) destination);
        Enumeration enumeration = browser.getEnumeration();

        if (enumeration.hasMoreElements()) {
            Object msg = enumeration.nextElement();
            TextMessage m = (TextMessage) msg;
            System.out.println(" !!!!!!!!Browsed  msg " +m.getText());
        }

        browser.close();
        session.close();
        connection.close();

    }

    public static void poll() throws Exception {

        ActiveMQConnectionFactory connectionFactory =
                                                      new ActiveMQConnectionFactory(
                                                                                    "vm://localhost");
        Connection connection = connectionFactory.createConnection();
        connection.start();

        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        destination = (ActiveMQDestination) session.createQueue("TEST.FOO");
        MessageConsumer consumer = session.createConsumer(destination);
        TextMessage m = (TextMessage) consumer.receive(1000);
        if (m != null) {
            System.out.println("*********** Polled Messg" + m.getText());
        }
        consumer.close();
        session.close();
        connection.close();
    }

  
    public static void main(String args[]) {
        try {
            offer();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
             for (int i = 1; i < 5; i++) {
                peek();
                poll();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

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...