Wednesday, May 4, 2011

Using the Java Messaging Service with Enterprise JavaBeans



Lisiting 1
package jdj.article.jmsejb;

import javax.naming.*;
import javax.jms.*;          // Import the javax.jms package
import java.util.Hashtable;

 * JmsQueueManager.java
 *
 * An abstract base class that implements all the basic 
 * functionality for creating a JMS QueueReceiver or 
 * QueueSender. Includes all the necessary code for obtaining 
 * a JNDI naming Context, looking up the Queue and retrieving 
 * it, setting up the JMS Connection and Session,and creating 
 * the actual QueueReceiver and/or QueueSubscriber. 
 *
 * This is extended by the ReceiverStartup and the 
 * JMSEjbClient classes, but it could also be used in a "has 
 * a" relationship by creating an implementation class and 
 * then contained as an attribute of our classes through a 
 * reference.
 *
 * @author Scott Grant
 * @version 1.0 - 4/10/00
 *
public abstract class JmsQueueManager implements IJmsEjbConstants
{       
    protected QueueConnectionFactory queueFx;  // Our factory
    protected QueueConnection conn;        // Our connection
    protected Queue queue;                     // Our queue
    protected Queue tempQueue;        // Our temporary queue
    protected QueueSession session;           // Our session
    protected QueueReceiver receiver;         / Our receiver    
    protected QueueSender sender;              // Our sender
    
    protected String jndiFactory;
    protected String url;
    protected String jmsFactory;
    protected String queueName;
    protected String principal;
    protected String credential;
            
    protected Context ctx;  // our initial JNDI context

* Obtain an initial context from Weblogic through JNDI (this 
 * will be used to access the JMS factory and topic/queue 
 * information).

public JmsQueueManager(String jndiFactory, String url, 
                     String queueName, String jmsFactory,
                     String principal, String credential)
    {
        this.jndiFactory = jndiFactory;
        this.url = url;
        this.queueName = queueName;
        this.jmsFactory = jmsFactory;
        this.principal = principal;
        this.credential = credential;
    }
protected void finalize() throws Throwable
{
    closeJMS();
}
protected Context getInitialContext()
{
    // Try and create a new initial context using our
     // properties...
        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY, jndiFactory);
        env.put(Context.PROVIDER_URL, url);        
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.SECURITY_PRINCIPAL, principal);
        env.put(Context.SECURITY_CREDENTIALS, credential);       
        try
        {
            // Try and create a new initial context using 
            // our properties...
            Context context = new InitialContext(env);
            return context;
        }
        catch(NamingException e)
        {
            System.out.println("getInitialContext: Could not  
            obtain initial naming context");
            e.printStackTrace();
            return null;
        }
        catch(Exception e)
        {
            System.out.println("getInitialContext: Unknown   
        exception trying to obtain initial naming context");
            e.printStackTrace();
            return null;
        }
}
* Initialize JMS - create initial JMS resources,
* start connection, etc.

protected void initializeJMS(String type, MessageListener  
 listener, boolean transacted)
{
    try
    {
        if (ctx == null)
            ctx = getInitialContext();
            
        if (ctx != null)
        {
           
            // Get the default queue connection 
             // factory...Destinations (Queues and
            // Topics) and ConnectionFactory objects are 
             // administered objects - you retreive them 
             // from the Weblogic Application Server via JNDI.
            queueFx = (QueueConnectionFactory)   
             ctx.lookup(jmsFactory);

                // Get a QueueConnection from the QueueCon-
                // nectionFactory
                conn = queueFx.createQueueConnection();

                // Get a QueueSession - auto-acknowledge - 
                // and use the parameter to 
                // determine if it is transacted or not...
                session = conn.createQueueSession(transact-
                ed, Session.AUTO_ACKNOWLEDGE);

                // Get the Queue from JNDI...Queue is an 
                // administered object
                queue = (Queue) ctx.lookup(queueName); 

                
                if ((type.equals(RECEIVER) || 
                    type.equals(SENDER_RECEIVER)) && 
                    listener != null)
                {
                    // Create a Receiver for the Queue...
                    receiver = session.createReceiver(queue);
                
                    // Set the listener (this class)
                    receiver.setMessageListener(listener);
                }
                
                if (type.equals(SENDER) ||   
                type.equals(SENDER_RECEIVER)) 
                {
                    sender = session.createSender(queue);
                }
                // Start connection...
                conn.start();
        }
        else
        {
            System.out.println("initializeJMS: InitialCon-
             text was null");
            return;
        }
    }
    catch(NamingException e)
    {
        System.out.println("initializeJMS: NamingException 
         was thrown");
            e.printStackTrace();            
    }
    catch(JMSSecurityException e)
    {
        System.out.println("initializeJMS: JMSSecurityExcep-
         tion was thrown");
            e.printStackTrace();
    }
    catch(JMSException e)
    {
        System.out.println("initializeJMS: JMSException was 
         thrown");
            e.printStackTrace();
    }
    catch(Exception e)
    {
        System.out.println("initializeJMS: Unknown exception 
         trying to obtain initialize JMS");
            e.printStackTrace();
    }
}
* Close down JMS - stop the connection, etc.

protected void closeJMS()
{     
    if (conn != null)
        {
            try
            {
                conn.stop();            
                if (sender != null)
                    sender.close();
                    
                if (receiver != null)
                    receiver.close();
                                
                if (session != null)                    
                    session.close();                        
                                
                conn.close();                                
            }
            catch(JMSException e)
            {
                System.out.println("closeJMS: JMSException 
                thrown while trying to close connections");
                e.printStackTrace();
            }
            catch(Exception e)
            {
                System.out.println("closeJMS: An unknown 
      exception occurred while trying to close connections");
                e.printStackTrace();
            }          
        }                     
}
* sendMessage
*
* Send a JMS Message.

protected void sendMessage(Message msg)
{
    try
    {
        msg.setJMSDeliveryMode(DeliveryMode.PERSISTENT);
        sender.send(msg); // default behavior         
    }
    catch(JMSException e)
    {
        System.out.println("initializeJMS: JMSException try-
         ing to send message to queue");
    }
}
* createMapMessage
*
* Creates a MapMessage - delegates to 
* the session version of this method.
protected MapMessage createMapMessage()
{
    try
    {
        return session.createMapMessage(); // default behavior
    }
    catch(JMSException e)
    {
        System.out.println("createMapMessage: JMSException 
         trying to create MapMessage");
    }
    
    return null;
}
// You could implement all the additional "createXXXMes0
 // sage()" delegator methods here, if you wanted to flesh  
 // out this class...

}

Listing 2
package jdj.article.jmsejb;

import javax.naming.*;
import javax.jms.*;          // Import the javax.jms package
import javax.ejb.*;
import java.util.*;
import java.lang.reflect.*;
import java.rmi.RemoteException;

import weblogic.common.*;

 * JmsEjbReceiver.java
 *
 * Implements Weblogic Start-Up class that receives JMS
 * Messages on an incoming Queue using Weblogic's JMS 
 * implementation.
 *
 * @author Scott Grant
 * @version 1.0 - 4/10/00

public class ReceiverStartup extends JmsQueueManager
                               implements MessageListener, 
                                           T3StartupDef                              
{
    
    // Note: These parameters could be passed in the Hashtable 
    // arguments to the Weblogic Start-Up Class via the 
    // "weblogic.properties" file...I have hard coded them here...
    public static final String JNDI_FACTORY = 
    "weblogic.jndi.WLInitialContextFactory";
    public static final String URL = "t3://localhost:7001";    
    public static final String JMS_FACTORY = 
    "javax.jms.QueueConnectionFactory";
    public static final String QUEUE = 
    "jdj.article.jmsejb.ejbMessageQueue";    
    public static final String PRINCIPAL = "system";      
    public static final String CREDENTIAL = "password";
    
    private T3ServicesDef serv; // Part of Weblogic Start-Up 
    class support                        
  
    public ReceiverStartup()
    {
        super(JNDI_FACTORY, URL, QUEUE, JMS_FACTORY, PRINCI-
        PAL, CREDENTIAL);
    }
    
    // Weblogic Start-Up Class 
    
    public void setServices(T3ServicesDef s) 
    {
        serv = s;
    }

    * startup
    *
    * This is part of the Weblogic T3StartupDef
    * interface
    *
    public String startup(String name, Hashtable args) throws 
    Exception 
    {
        ctx = getInitialContext();        
        
        if (ctx != null)
            initializeJMS(RECEIVER, this, false);   // Not 
            using transactions
        else
            throw new NamingException("ReceiverStartup - 
            initializeJMS: Naming Exception was thrown");
        
                
        return "ReceiverStartup listening...";
    }
  
    // JMS Items                                 
    * Implements the onMessage method of the MessageListener 
    * interface. This is the call back method used by JMS to 
    * pass us messages on the queue our which we're 
    * registered with...
    
public void onMessage(Message msg)
{       
    System.out.println("ReceiverStartup: Received incoming 
     JMS message...");
    
        try 
        {
            String msgType = msg.getJMSType();                        
            if (msg instanceof MapMessage && 
            msgType.equals(JMSEJB_MESSAGE))
            {               
              MapMessage mapMsg = (MapMessage)msg;
              String homeName = mapMsg.getString("HomeName");
              String createName = mapMsg.getString("CreateName");
              int createParams = mapMsg.getInt("CreateParams");
              String methodName = mapMsg.getString("MethodName");
              int methodParams = mapMsg.getInt("MethodParams");
                
              System.out.println("homeName: " + homeName);
                
              if (ctx == null)
                 ctx = getInitialContext();
                    
              if (ctx != null)
                {
                   try
                   {                                                                        
                      // Get the class type and parameters 
                      // for the EJBHome create method...
                        System.out.println("Getting create 
                        class types...");
                        Class[] createTypes = get  ClassTypesFromMessage((MapMessage)msg, createParams, "CreateParam", "CreateParamType");
                        System.out.println("Getting create 
                        arguments and types...");
                        Object[] createArgs = getArgumentsFromMessage((MapMessage)msg, createParams, "CreateParam", "CreateParamType");
                        
                        // Get the class type and parame-
                        // ters for the EJBObject (stub) 
                        // method to invoke...
                        System.out.println("Getting method 
                        class types...");
                        Class[] methodTypes = getClassTypesFromMessage((MapMessage)msg, methodParams, "MethodParam", "MethodParamType");
                        System.out.println("Getting method  
                        arguments and types...");
                        Object[] methodArgs = getArgumentsFromMessage((MapMessage)msg, methodParams, "MethodParam", "MethodParamType");
                                                                                             
                        System.out.println("Looking up object class name...");
                        
                        // Find our home class through JNDI...
                        Object obj = ctx.lookup(homeName);
                        Class homeClass = obj.getClass();                                                
                                                              
                        // Find the create method...                                                                        
                        Method methodCreate = 
               homeClass.getMethod(createName, createTypes);
                        
                        System.out.println("Invoking create 
                        method...");
                        
                        // Invoke the create method...
                        Object ejb = 
                      methodCreate.invoke(obj, createArgs);                        
                                                                        
                        System.out.println("Invoking method 
                        " + methodName + "...");
                        
                        // Find the EJB method in the JMS 
                        // Message...
                        Method methodCall = ejb.get-
                 Class().getMethod(methodName, methodTypes);
                        
                        // Invoke the EJB method...
                        methodCall.invoke(ejb, methodArgs);                       
                           
                    }
                    catch(InvocationTargetException e)
                    {
                        System.out.println("ReceiverStart-
                 up: InvocationTargetException was thrown");
                    }
                    catch(NoSuchMethodException e)
                    {
                        System.out.println("ReceiverStart-
                    up: NoSuchMethodException was thrown");
                    }
                    catch(IllegalAccessException e)
                    {
                        System.out.println("ReceiverStart-
                   up: IllegalAccessException was thrown");
                    }
                    catch(Exception e)
                    {
                        System.out.println("ReceiverStart-
                            up: An exception was thrown");
                    }
                }
                else
                    System.out.println("ReceiverStartup: 
       onMessage: Failed to obtain initial naming context");
            }                             
        }
        catch (JMSException e) 
        {
            System.out.println("ReceiverStartup: onMessage: 
                              JMSException was thrown");
            e.printStackTrace();
        }
    }
    
    * getClassTypesFromMessage
    *
    * Returns an array of Class types from a MapMessage 
    * which contains a list of parameters for an EJB method call.

    public Class[] getClassTypesFromMessage(MapMessage msg, 
    int params, 
        String argName, String typeName) throws JMSException
    {
        Class[] types = new Class[0];
                
        if (params > 0)
        {
            types = new Class[params];
                            
            for (int i = 0; i < params; i++)
            {
                String type = msg.getString(typeName + i);                                
                if (type.equals("String"))
                {                    
                    types[i] = String.class;                    
                }
                else if (type.equals("int"))
                {                    
                    types[i] = int.class;                    
                }
                else if (type.equals("long"))
                {                    
                    types[i] = long.class;                    
                }
                else if (type.equals("float"))
                {                    
                    types[i] = float.class;                 
                }
                else if (type.equals("double"))
                {                    
                    types[i] = double.class;                    
                }
                else if (type.equals("short"))
                {                    
                    types[i] = short.class;                    
                }
                else if (type.equals("byte"))
                {                    
                    types[i] = byte.class;                    
                }
                else if (type.equals("object"))
                {
                    // Extract any type of object...
                    Object obj = msg.getObject(argName + i);
                    types[i] = obj.getClass();
                    System.out.println("Object instance: " 
                    + obj.getClass().getName());
                }
                else if (type.equals("message"))
                {                                        
                    types[i] = Message.class;               
                }                
                else
                    System.out.println("Unknown parameter   
                    type");
            }
        }
        
        return types;
    }
    
    * getArgumentsFromMessage
    *
    * Returns an array of Object's from a JMS MapMessage
    * that are extracted as parameters for an EJB method
    * call.

    public Object[] getArgumentsFromMessage(MapMessage msg, int params, 
         String argName, String argType) throws JMSException
    {
        Object[] args = new Object[0];
            
        if (params > 0)
        {            
            args = new Object[params];
            
            for (int i = 0; i < params; i++)
            {
                String type = msg.getString(argType + i);
                if (type.equals("String"))
                {
                    String temp = msg.getString(argName + i);                    
                    args[i] = temp;
                }
                else if (type.equals("int"))
                {
                    int temp = msg.getInt(argName + i);                    
                    args[i] = new Integer(temp);
                }
                else if (type.equals("long"))
                {
                    long temp = msg.getLong(argName + i);                    
                    args[i] = new Long(temp);
                }
                else if (type.equals("float"))
                {
                    float temp = msg.getFloat(argName + i);                    
                    args[i] = new Float(temp);
                }
                else if (type.equals("double"))
                {
                    double temp = msg.getDouble(argName + i); 
                    args[i] = new Double(temp);
                }
                else if (type.equals("short"))
                {
                    short temp = msg.getShort(argName + i);                     
                    args[i] = new Short(temp);
                }
                else if (type.equals("byte"))
                {
                    byte temp = msg.getByte(argName + i);                    
                    args[i] = new Float(temp);
                }
                else if (type.equals("object"))
                {
                    Object obj = msg.getObject(argName + i);
                    args[i] = obj;
                }
                else if (type.equals("message"))
                {                                        
                    args[i] = msg;
                }
                // You could add other types here...Object,etc...
                else
                    System.out.println("Unknown parameter type");
            }
        }
        
        return args;
    }
}

Listing 3
package jdj.article.jmsejb;
            
import javax.jms.*;
import javax.naming.*;
            
* JmsEjbClient
*
* This is our client class. It extends the base JmsQueueMan-
* ager to handle the creation of the JMS connection, session, 
* and QueueSender. 
*
* It creates two JMS MapMessages. The first is sent to the 
* EJB's "onMessage" method through simple delegation. The 
* second message is actually used to call a method on the EJB 
* asynchronously via a JMS message - both cases are handled 
* by the ReceiverStartup Weblogic startup class.
*
* @author Scott Grant
* @version 1.0 - 4/10/00
            
public class JmsEjbClient extends JmsQueueManager
{       
    public static final String JNDI_FACTORY = 
    "weblogic.jndi.WLInitialContextFactory";
    public static final String URL = "t3://localhost:7001";    
    public static final String JMS_FACTORY = 
    "javax.jms.QueueConnectionFactory";
    public static final String QUEUE = 
    "jdj.article.jmsejb.ejbMessageQueue";    
    public static final String PRINCIPAL = "system";      
    public static final String CREDENTIAL = "password";        
            
    public JmsEjbClient()
    {
        super(JNDI_FACTORY, URL, QUEUE, JMS_FACTORY, PRINCI
        PAL, CREDENTIAL);
    }
            
    public static void main(String[] args)
    {
        JmsEjbClient client = new JmsEjbClient();
        client.initializeJMS(SENDER, null, false);
            
        MapMessage msg = client.createMapMessage();       
        try
        {
            // Create a MapMessage and send it to the Queue
            msg.setJMSType(JMSEJB_MESSAGE);
            msg.setString("HomeName", 
            "jdj.article.jmsejb.JmsEjbExampleHome");
            msg.setString("CreateName", "create");            
            msg.setInt("CreateParams", 0);
            
            // We are sending this method to the "onMessage" 
            // method of the EJB, so we set one parameter 
            // which is of type "message". This is a special 
            // case and the ReceiverStartup will interpret
            // this as delegation - it will pass the actual 
            // JMS Message itself, on to this method (onMes-
            // sage) of the EJB as the parameter.
            msg.setString("MethodName", "onMessage");
            msg.setInt("MethodParams", 1); 
            msg.setString("MethodParamType0", "message");
            msg.setString("StringMessage", "This is my test 
       message string sent to the EJB onMessage method...");
            
            client.sendMessage(msg);
            
            // Now send a method invocation with Params...
            
            msg = client.createMapMessage();
            msg.setJMSType(JMSEJB_MESSAGE);
            msg.setString("HomeName", 
            "jdj.article.jmsejb.JmsEjbExampleHome");
            msg.setString("CreateName", "create");            
            msg.setInt("CreateParams", 0);
            
            // We are sending this message to ReceiverStart-
            // up as a method
            // invocation. So we set the method name, and 
            // the parameter types, and values. The 
            // ReceiverStartup class will use Java's reflec-
            // tion mechanism to find this method on the 
            // EJB, and invoke it, passing
            // in the parameters as we've specified them.  
            // This demonstrates using a Weblogic startup 
            // class as a delegator for asynchronous
            // method invocation on an EJB...
            msg.setString("MethodName", "testMethod");
            msg.setInt("MethodParams", 2); 
            msg.setString("MethodParamType0", "int");
            msg.setInt("MethodParam0", 1);
            msg.setString("MethodParamType1", "String");
            msg.setString("MethodParam1", "This is my test message string sent to the EJB testMethod as method parameter...");
            
            client.sendMessage(msg);            
        }
        catch(JMSException e)
        {
            System.out.println("JmsEjbClient: JMSException was thrown");
        }
    }
}

No comments:

Post a Comment