/* * Copyright (c) 1998-2000, Fiorano Software, Inc. * All Rights Reserved * * JMS-EJB Integration Sample * * FileName : Subscriber.java * * Implements an asynchronous listener to listen * for messages published on the queue - "primaryQueue". * * Receives JMS Messages that were published on the Queue, * demarshalls the content of the JMS Message to lookup and * invoke appropriate methods on the EJB with appropriate * parameters using reflection. * * * USAGE:: * java -Djava.naming.factory.initial=AppServer'sInitialContext Subscriber * * Questions/comments/suggestions? * Please visit: http://www.fiorano.com * or e-mail: support@fiorano.com * * @since 4.4, May 2000 */ import javax.jms.*; import javax.ejb.*; import javax.naming.*; import javax.rmi.*; import java.lang.reflect.*; import java.util.*; import fiorano.jms.rtl.FioranoInitialContext; /** * This class can be run as a stand-alone JMS Application * The JVM should have a reference of hte appropriate Server * interfaces (Home/Remote Interfaces of all EJB's that need to be * invoked) in its CLASSPATH. * * Alternatively, this class can also be made as a startup * class, so that the AppServer is responsible for starting * and stopping this class within the AppServer's JVM instance. * * The main disadvantage of making this class as a startup class * is the non-proprietary nature of the support for the startup * classes by the various AppServer vendors. * */ class Subscriber implements MessageListener,ExceptionListener { // String identifying the message type private static final String FIORANO_EJB_MESSAGE = "FIORANO_EJB_MESSAGE"; // AppServer's InitialContext private InitialContext m_appServerContext; public static void main (String args[]) { Subscriber subscriber = new Subscriber (); try { // 1. Create the InitialContext Object used for looking up // JMS administered objects on the FioranoMQ // located on the default host. FioranoInitialContext ic = new FioranoInitialContext (); ic.bind (); // 1.1 Lookup Connection Factory and Queue names // QueueConnectionFactory qcf = (QueueConnectionFactory) ic.lookup ("primaryQCF"); Queue queue = (Queue)ic.lookup("primaryQueue"); // 1.2 Dispose the InitialContext resources // ic.dispose(); // 2. create and start a queue connection System.out.println("Creating queue connection"); QueueConnection queueConnection = qcf.createQueueConnection(); // Register an Exception Listner queueConnection.setExceptionListener (subscriber); queueConnection.start (); // 3. create queue session on the connection just created System.out.println("Creating queue session: not transacted, auto ack"); QueueSession queueSession = queueConnection.createQueueSession(false,1); // 4. create subscriber System.out.println("Creating queue, subscriber"); QueueReceiver queueReceiver = queueSession.createReceiver(queue); // 5. install an asynchronous listener/callback on the subscriber object // just created System.out.println ("Ready to subscribe for messages :"); queueReceiver.setMessageListener (new Subscriber ()); } catch (Exception e) { e.printStackTrace (); } } /** * Message listener which receives messages aysynchronously * for the bound subscriber. * * Read the message properties, and lookup the appropriate * EJB. Invoke appropriate method on the EJB. * * @param Message, received JMS Message */ public void onMessage (Message msg) { try { String msgType = msg.getJMSType(); // Check whether the received messages is // an EJB invocation message. if (msgType.equals(FIORANO_EJB_MESSAGE)) { // Get the contents of the message to invoke apppropriate EJB String beanName = msg.getStringProperty(JMSConstants.EJB_NAME); String constName = msg.getStringProperty(JMSConstants.CONST); int nConstArgs = msg.getIntProperty(JMSConstants.CONST_N_ARGS); String methodName = msg.getStringProperty(JMSConstants.METHOD_NAME); int nMethodArgs = msg.getIntProperty(JMSConstants.METHOD_N_ARGS); // Get Appserver's InitialContext to lookup appropriate Bean references if (m_appServerContext == null) { // Please make sure to set appropriate System // property. // In case of WebLogic AppServer, set property // java.naming.factory.initial=weblogic.jndi.T3InitialContextFactory //Properties prop = System.getProperties (); //prop.put ("java.naming.factory.initial", "weblogic.jndi.T3InitialContextFactory"); System.setProperties (prop); try { m_appServerContext = new InitialContext(); } catch (NamingException err) { System.out.println ("Unable to initialize AppServer's InitialContext. Please ensure" + "to set System property java.naming.factory.initial"); err.printStackTrace (); } } if (m_appServerContext != null) { try { // Get the constructor types and args to create appropriate EJB Class[] constTypes = getClassTypesFromMessage(msg, nConstArgs, JMSConstants.CONST, JMSConstants.CONST_TYPE); Object[] constArgs = getArgumentsFromMessage(msg, nConstArgs, JMSConstants.CONST,JMSConstants.CONST_TYPE ); // Get the class type and parameters for the EJBObject (stub) method to invoke... Class[] methodTypes = getClassTypesFromMessage(msg, nMethodArgs, JMSConstants.METHOD_NAME, JMSConstants.METHOD_TYPE); Object[] methodArgs = getArgumentsFromMessage(msg, nMethodArgs, JMSConstants.METHOD_NAME, JMSConstants.METHOD_TYPE); // Find our home class through JNDI... Object obj = m_appServerContext.lookup(beanName); Class beanClass = obj.getClass(); // Find the create method... Method methodCreate = beanClass.getMethod(constName, constTypes); // Invoke the create method... Object ejb = methodCreate.invoke(obj, constArgs); System.out.println("Received Event. Invoking EJB::Method()" + methodName); // Find the EJB method in the JMS Message... Method methodCall = ejb.getClass().getMethod(methodName, methodTypes); // Invoke the EJB method... methodCall.invoke(ejb, methodArgs); } catch(InvocationTargetException e) { System.out.println("ReceiverStartup: InvocationTargetException was thrown"); } catch(NoSuchMethodException e) { System.out.println("ReceiverStartup: NoSuchMethodException was thrown"); } catch(IllegalAccessException e) { System.out.println("ReceiverStartup: IllegalAccessException was thrown"); } catch(Exception e) { System.out.println("ReceiverStartup: An exception was thrown"); } } else System.out.println("JMSSubscription:: Startup Failure"); } } catch (JMSException e) { e.printStackTrace(); } } /** * Get Class Type from Message * * @param message * @param no of args * @param argument Name * @param type name */ private Class[] getClassTypesFromMessage (Message 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.getStringProperty(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.getObjectProperty(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; } /** * Get Arguments Type from Message * * @param message * @param no of args * @param argument Name * @param type name * * @exception JMSException if the operation fails */ private Object[] getArgumentsFromMessage(Message 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.getStringProperty(argType + i); System.out.println ("Arg Type" + argType + " Value" + type); if (type.equals("String")) { String temp = msg.getStringProperty(argName + i); args[i] = temp; } else if (type.equals("int")) { int temp = msg.getIntProperty(argName + i); args[i] = new Integer(temp); } else if (type.equals("long")) { long temp = msg.getLongProperty(argName + i); args[i] = new Long(temp); } else if (type.equals("float")) { float temp = msg.getFloatProperty(argName + i); args[i] = new Float(temp); } else if (type.equals("double")) { double temp = msg.getDoubleProperty(argName + i); args[i] = new Double(temp); } else if (type.equals("short")) { short temp = msg.getShortProperty(argName + i); args[i] = new Short(temp); } else if (type.equals("byte")) { byte temp = msg.getByteProperty(argName + i); args[i] = new Float(temp); } else if (type.equals("object")) { Object obj = msg.getObjectProperty(argName + i); args[i] = obj; } else if (type.equals("Message")) { args[i] = (javax.jms.Message)msg; } // You could add other types here...Object,etc... else System.out.println("Unknown parameter type"); } } return args; } /** * If a JMS provider detects a serious problem with a * Connection this method is invoked passing it a JMSException * describing the problem. * * @param JMSException e */ public void onException (JMSException e) { //Report the Error and take necessary Error handling measures String error = e.getErrorCode (); System.out.println (error); } }