ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Enhancing Web Services Infrastructures with JMS
Pages: 1, 2, 3

JMSClientSendReceive Class

We'll start by looking at the JMSClientSendReceive class.



This class implements a JMS queue sender and receiver. If you're unfamiliar with JMS, take a look at this introductory article on JMS.

package org.open3.soap;

import java.util.*;

import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;

public class JMSClientSendReceive implements MessageListener {
    
  //contants for JMS  
  public final static String CTX_FACTORY = "org.open3.jndi.lite.LiteContextFactory";
  public static final String QCF_NAME = "QueueConnectionFactory";
  public final static String TO_WS_DEST_NAME = "toWS@open3soap";
  public final static String FROM_WS_DEST_NAME = "fromWS@open3soap";
  
 
  protected String  _configFile = "config/config.xml";
  protected String _configName = "standard";
  protected String _parser = "org.apache.crimson.parser.XMLReaderImpl";
  protected boolean _verbose = false; 
  protected QueueConnectionFactory _qcf = null;
  protected QueueConnection connection = null;
  protected Queue _queueToWS = null;
  protected Queue _queueFromWS = null;
  protected QueueSession sessionReceiver = null;
  protected QueueSession sessionSender = null;
  protected QueueReceiver receiver = null;
  protected QueueSender sender = null;
  
  //constants for xml document
  public static String XML_ORDER_OPEN_TAG = "<order>";
  public static String XML_ORDER_CLOSE_TAG = "</order>";
  public static String XML_WEIGHT_OPEN_TAG = "<shippingWeight>";
  public static String XML_WEIGHT_CLOSE_TAG = "</shippingWeight>";
  public static String XML_DISTANCE_OPEN_TAG = "<destinationDistance>";
  public static String XML_DISTANCE_CLOSE_TAG = "</destinationDistance>";
  public static String XML_COST_OPEN_TAG = "<shippingCost>";
  public static String XML_COST_CLOSE_TAG = "</shippingCost>";

  //Constructor
  public JMSClientSendReceive() {

  }
  
  public void init(String receiveFromQueue, String sendToQueue) {
        try {
            
            InitialContext initContext = null;
            
            //InitialContext through JNDI
            Properties props = new Properties();  
            props.put(Context.INITIAL_CONTEXT_FACTORY, CTX_FACTORY);
            props.put("org.open3.xstp.server.ConfigFile", _configFile);
            props.put("org.open3.jms.ConfigName", _configName);
            props.put("org.open3.xstp.server.SAXParser", _parser);

            initContext = new InitialContext(props);

            //get the Queue Connection factory
            _qcf = (QueueConnectionFactory)initContext.lookup(QCF_NAME);

            //get the queue destinations
            _queueToWS = (Queue)initContext.lookup(receiveFromQueue);
            _queueFromWS = (Queue)initContext.lookup(sendToQueue);

            connection = _qcf.createQueueConnection();

            //create a receiver and sender session 
            sessionReceiver = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
            sessionSender = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

            //create the receiver and sender
            receiver = sessionReceiver.createReceiver(_queueToWS);
            sender = sessionSender.createSender(_queueFromWS);

            //set to process onMessage events
            receiver.setMessageListener(this);

            //start delivery of incoming messages
            connection.start();

        }
        catch (Exception e) {
            System.out.println("JMSClientSendReceive.init Error: " + e.toString());
            e.printStackTrace();
        }
  }
  
  public void cleanUp() {
        //free up system resources
        try {
            sender.close();
            sessionReceiver.close();
            sessionSender.close();
            connection.close();
        } 
        catch(Exception e) {
            System.out.println("JMSClientSendReceive.cleanUp Error: " + e.toString());
        }
  }
  
  public void onMessage(javax.jms.Message msg) { }
  
  public boolean sendJMSMessage(String msgContent) {
      //sends a JMS TextMessage back to the JMS server
      boolean sendOK = true;
      
      System.out.println("ShippingClient: sending JMS message: " + msgContent);
      try {
        Message msg = sessionSender.createTextMessage(msgContent);
        sender.send(msg);
      }
      catch (Exception e) {
           System.out.println("ShippingClient.sendJMSMessage Error: " + e.toString());
           e.printStackTrace();
           sendOK = false;
      }
      return sendOK;   
  }
   
}

This class defines constants and variable fields for connecting to and using the JMS API.

public final static String CTX_FACTORY = "org.open3.jndi.lite.LiteContextFactory";
public static final String QCF_NAME = "QueueConnectionFactory";
public final static String TO_WS_DEST_NAME = "toWS@open3soap";
public final static String FROM_WS_DEST_NAME = "fromWS@open3soap";

These constants define the JNDI context factory and the names of the QueueConnection factory and queue destinations. All of the system's messages travel through two queues, toWS@open3soap and fromWS@open3soap. The toWS prefix refers to messages headed toward the Web service, and fromWS handles messages coming back from the Web service. The open3soap suffix is the namespace of the destination. We must configure the destinations in Open3.org JMS destinations.xml file. The destinations.xml file is under the config/ directory of the base directory. Add these two lines:

<destination type="queue" name="toWS" namespace="open3soap"/>
<destination type="queue" name="fromWS" namespace="open3soap"/>

The JMSClientSendReceive class also contains the elements for the XML document that forms the body of our messages. You wouldn't necessarily want to define your XML tags as String constants, but we've done so for simplicity:

public static String XML_ORDER_OPEN_TAG = "<order>";
public static String XML_ORDER_CLOSE_TAG = "</order>";
public static String XML_WEIGHT_OPEN_TAG = "<shippingWeight>";
public static String XML_WEIGHT_CLOSE_TAG = "</shippingWeight>";
public static String XML_DISTANCE_OPEN_TAG = "<destinationDistance>";
public static String XML_DISTANCE_CLOSE_TAG = "</destinationDistance>";
public static String XML_COST_OPEN_TAG = "<shippingCost>";
public static String XML_COST_CLOSE_TAG = "</shippingCost>";

The init() function connects the client to the server and sets up the sender and receiver sessions. In implementing the MessageListener interface, we utilize the event listener model for receiving messages. JMS specifies that only one thread may operate on a session at a time, and therefore we create separate sessions for the sender and receiver:

sessionReceiver = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
sessionSender = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

The AUTO_ACKNOWLEDGE mode is utilized. Messages are automatically acknowledged when received by the client.

This class also defines an empty onMessage() method that is overridden by classes that extend JMSClientSendReceive:

public void onMessage(javax.jms.Message msg) { }

The class implements a general sendJMSMessage method that takes a String parameter and utilizes this to build a JMS TextMessage. The system strictly utilizes JMS TextMessages to encapsulate the XML documents.

OrderApplication Class

Our next class is OrderApplication, which simulates an application for processing orders:

package org.open3.soap;

import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;

public class OrderApplication extends JMSClientSendReceive{

    /** Creates new OrderApplication */
    public OrderApplication() {
         super.init(FROM_WS_DEST_NAME, TO_WS_DEST_NAME);
        
        //create and send a message
        String msgOrder = XML_ORDER_OPEN_TAG + 
            XML_WEIGHT_OPEN_TAG + "45.50" + XML_WEIGHT_CLOSE_TAG +
            XML_DISTANCE_OPEN_TAG + "500" + XML_DISTANCE_CLOSE_TAG +
            XML_ORDER_CLOSE_TAG;
        
        boolean msgOK = sendJMSMessage(msgOrder);
    }

    public void onMessage(javax.jms.Message msg) {
        //a message has been received from the JMS server, this message
        //contains the 

        try{
            //get the xml data from the TextMessage
            String xmlData = ((TextMessage)msg).getText();

            String strShipCost = xmlData.substring(
                xmlData.indexOf(XML_COST_OPEN_TAG) + XML_COST_OPEN_TAG.length(),
                xmlData.indexOf(XML_COST_CLOSE_TAG));

           System.out.println("Shipping Cost=" + strShipCost);
        }
        catch (Exception e){
            System.out.println("OrderApplication.onMessage Error: " + e.toString());
        }
   }
    
    public static void main(String[] args) throws Exception {
        OrderApplication app = new OrderApplication();
    }
  
}

OrderApplication's constructor calls the parent's init() function to establish its JMS connections. Notice that the receiver is connected to FROM_WS_DEST_NAME, which is the queue for messages coming from the Web service, and the sender to TO_WS_DEST_NAME, which is the queue for messages going out to the Web service:

public OrderApplication() {
    super.init(FROM_WS_DEST_NAME, TO_WS_DEST_NAME);
        
    //create and send a message
    String msgOrder = XML_ORDER_OPEN_TAG + 
        XML_WEIGHT_OPEN_TAG + "45.50" + XML_WEIGHT_CLOSE_TAG +
        XML_DISTANCE_OPEN_TAG + "500" + XML_DISTANCE_CLOSE_TAG +
        XML_ORDER_CLOSE_TAG;
        
    boolean msgOK = sendJMSMessage(msgOrder);
}

The constructor also creates and sends an XML message to be delivered to the toWS@open3soap queue. The body of message is:

<order>
    <shippingWeight>45.50</shippingWeight>
    <destinationDistance>500</destinationDistance>
</order>

This document specifies two fields, shippingWeight and destinationDistance. These fields are utilized by the Web service to calculate a shipping cost for the order.

The onMessage method is called when a message has been returned from the Web service client. This message contains a document that appears as:

<order>
    <shippingCost>39.625</shippingCost>
</order>

The onMessage method extracts the shipping cost from the document and prints it.

Pages: 1, 2, 3

Next Pagearrow