JMS - Java Message Service



JMS point-to-point in the Weblogic way..

Add to config.xml :


What you need to add to config.xml in your Weblogic installation to get rolling..
config.xml

...
<JMSQueue JNDIName="weblogic.jms.inqueue" Name="dk.topsecurity.queue" StoreEnabled="default"/> ...



Furthermore you need a "jndi.properties" in your local directory to tell the applications which setup to use when contacting JMS service :


The jndi.properties, which ties everything together - eliminating the need to gardcode everything in the application - or set bunch of stuff through commandline parameters...
jndi.properties

java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory
java.naming.provider.url=t3://localhost:7001


The transmitter, which keeps pounding the queue..
JMSQueueSender.java


package dk.topsecurity;

import javax.jms.*;
import javax.naming.*;
import java.util.*;
import java.text.SimpleDateFormat;

/**
 * The point-to-point (PTP) messaging model enables one application to send a 
 * message to another. PTP messaging applications send and receive messages 
 * using named queues. A queue sender (producer) sends a message to a specific 
 * queue. A queue receiver (consumer) receives messages from a specific queue.
 */
public class JMSQueueSender {

    public final static String QUEUE_NAME = "dk.topsecurity.queue";
    public final static String JMS_FACTORY = "weblogic.jms.ConnectionFactory";
//  public final static String JMS_FACTORY = "javax.jms.QueueConnectionFactory"
    public final static String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";


    public static void main(String[] args) {
        try {

//requires definition of in java.naming.factory.initial,java.naming.provider.url in jndi.properties
            Context ctx = new InitialContext();

            QueueConnectionFactory factory =
                (QueueConnectionFactory) ctx.lookup(JMS_FACTORY); //get Queue Connection Factory via JNDI
            QueueConnection conn = factory.createQueueConnection(); //create new Queue Connection

// Create a Queue Session, ask JMS to acknowledge the messages
// The session is non-transactional - you don't send messages
// as part of a transaction.

            QueueSession session = conn.createQueueSession(false,
                Session.AUTO_ACKNOWLEDGE);

            Queue queue = null;
            try {
                queue = (Queue) ctx.lookup(QUEUE_NAME); //check if someone has already created the queue
            }
            catch (NameNotFoundException exc) {
                queue = session.createQueue(QUEUE_NAME); //if not, create a new Queue and store it in the JNDI directory
                ctx.bind(QUEUE_NAME, queue);
            }
            QueueSender sender = session.createSender(queue); //create a QueueSender (so you can send messages)
            conn.start(); //tell Queue Connection you are ready to interact with the message service
            for (;;) {
		String messageTxt = "Hello from sender at " + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new java.util.Date());
                TextMessage message = session.createTextMessage(messageTxt); //create simple text message
                sender.send(message); //send message
                try { Thread.sleep(5000); } catch (Exception ignore) {} //5 secs pause before another message
            }
        }
        catch (Exception exc) {
            exc.printStackTrace();
        }
    }
}



Two ways to to receive messages: call the receive method, which waits for messages - or create a listener object, which receives messages when they becomes available...


Simple... calling receive method, which blocks call until message available..
JMSQueueReceiver.java



package dk.topsecurity;

import javax.jms.*;
import javax.naming.*;

/**
 * The point-to-point (PTP) messaging model enables one application to send a 
 * message to another. PTP messaging applications send and receive messages 
 * using named queues. A queue sender (producer) sends a message to a specific 
 * queue. A queue receiver (consumer) receives messages from a specific queue.
 */
public class JMSQueueReceiver {

    public final static String QUEUE_NAME = "dk.topsecurity.queue";
    public final static String JMS_FACTORY = "weblogic.jms.ConnectionFactory";
//  public final static String JMS_FACTORY = "javax.jms.QueueConnectionFactory"

    public static void main(String[] args)
    {
        try {
//requires definition of in java.naming.factory.initial,java.naming.provider.url in jndi.properties
            Context ctx = new InitialContext();
            QueueConnectionFactory factory =
                (QueueConnectionFactory) ctx.lookup(JMS_FACTORY); //locate the Queue Connection Factory via JNDI
            QueueConnection conn = factory.createQueueConnection(); //create a new Queue Connection

// Create a Queue Session, ask JMS to acknowledge the messages
// This program receives messages, so it doesn't really care.
// The session is non-transactional

            QueueSession session = conn.createQueueSession(false,
                Session.AUTO_ACKNOWLEDGE);
            Queue queue = null;
            try {
                queue = (Queue) ctx.lookup(QUEUE_NAME); //check if someone has already created the queue
            }
            catch (NameNotFoundException exc) {
                queue = session.createQueue("HelloQueue"); //if not, create a new Queue and store it in the JNDI directory
                ctx.bind(QUEUE_NAME, queue);
            }
            QueueReceiver receiver = session.createReceiver(queue); //create a QueueReceiver to receive messages
            conn.start(); //tell the Queue Connection you are ready to interact with the message service
            for (;;) { //receive next message and echo message contents to console
                System.out.println(((TextMessage) receiver.receive()).getText());
            }
        }
        catch (Exception exc)
        {
            exc.printStackTrace();
        }
    }
}


"Service-on-demand"... setting up listener object to handle available messages..
JMSQueueListener.java



package dk.topsecurity;

import javax.jms.*;
import javax.naming.*;

/**
 * The point-to-point (PTP) messaging model enables one application to send a 
 * message to another. PTP messaging applications send and receive messages 
 * using named queues. A queue sender (producer) sends a message to a specific 
 * queue. A queue receiver (consumer) receives messages from a specific queue.
 */
public class JMSQueueListener implements MessageListener {

    public final static String QUEUE_NAME = "dk.topsecurity.queue";
    public final static String JMS_FACTORY = "weblogic.jms.ConnectionFactory";
//  public final static String JMS_FACTORY = "javax.jms.QueueConnectionFactory"

    JMSQueueListener() { }

/** 
 * Required by implemented MessageListener and called by the QueueReceiver 
 *  to handle the next message in the queue 
 */
    public void onMessage(Message message) {
        try {  //text message assumed
            System.out.println(((TextMessage) message).getText());       //echo to console
        }
        catch (JMSException exc) {
            exc.printStackTrace();
        }
    }

    public static void main(String[] args) {
        try {
//requires definition of in java.naming.factory.initial,java.naming.provider.url in jndi.properties
            Context ctx = new InitialContext(); 
            QueueConnectionFactory factory =
                (QueueConnectionFactory) ctx.lookup(JMS_FACTORY); //look up Queue Connection Factory by JNDI
            QueueConnection conn = factory.createQueueConnection(); //make new Queue Connection
            QueueSession session = conn.createQueueSession(false,
                Session.AUTO_ACKNOWLEDGE); //make non-transactional Queue Session
            Queue queue = null;
            try {
                queue = (Queue) ctx.lookup(QUEUE_NAME); //check if someone has already created the queue
            }
            catch (NameNotFoundException exc) {
                queue = session.createQueue(QUEUE_NAME); 
                ctx.bind(QUEUE_NAME, queue); //if not, create new Queue and put in JNDI directory
            }
            QueueReceiver receiver = session.createReceiver(queue); //create QueueReceiver to receive messages
            conn.start(); //tell Queue Connection, ready to interact with the message service
            receiver.setMessageListener(new JMSQueueListener()); // tell receiver to call your listener object on message arrival..

            System.out.println("Awaiting message from queue "+QUEUE_NAME);

//keep listener thread alive by pausing main process with a non-cpu consuming loop 
            Thread.sleep(999999999);
        }
        catch (Exception exc) {
            exc.printStackTrace();
        }
    }
}



That's the source code to keep the data flowing - but we need to setup a framework to handle everything...


We ned to compile everything.. use ANT here.. create a .jar file to include in the classpath.. remember to set wl_home to your weblogic installation directory of choice..
build.xml


<project name="TopsecurityJMS" default="all" basedir=".">

  <target name="init">
        <!-- set global properties for this build -->
        <property environment="env"/>
        <property name="wl_home" value="C:/weblogicplatform/weblogic81"/>
        <property name="source" value="./src/dk/topsecurity"/>
        <property name="destination" value="./classes"/>

        <property name="project_name"   value="TopsecurityJMS"/>
        <property name="jmsjar"         value="${project_name}.jar"/>
  </target>
  
  <target name="all" depends="makejar"/>

  <target name="clean" depends="init">
    <delete file="*.class"/>
  </target>

  <target name="compile" depends="clean">
    <mkdir dir="${destination}" />
    <javac srcdir="${source}" classpath="${wl_home}\server\lib\weblogic.jar" includes="*.java" destdir="${destination}"/>
  </target>

  <!-- create .jar -->
  <target name="makejar" depends="compile">
            <jar jarfile="${jmsjar}"
                    basedir="${destination}"
                    includes="dk/**">
              <fileset dir="${destination}">
                <include name="dk/**"/>
              </fileset>
            </jar>
  </target>
</project>




Using Windows platform (not by preferred choice).. we need command scripts to run the lot.. First let's start pounding the queue.. remember to set wl_home to your weblogic installation directory of choice..
queueSendTest.cmd


set BEA_HOME=C:\weblogicplatform
set WL_HOME=C:\weblogicplatform\weblogic81

java -classpath .;TopsecurityJMS.jar;%WL_HOME%\server\lib\weblogic.jar dk/topsecurity/JMSQueueSender




And another command line script to sweep up the transmitted messages (receiver)...


Using Windows platform (not by preferred choice).. let's receive messages from the queue... remember to set wl_home to your weblogic installation directory of choice..
queueReceiveTest.cmd


set BEA_HOME=C:\weblogicplatform
set WL_HOME=C:\weblogicplatform\weblogic81

java -classpath .;TopsecurityJMS.jar;%WL_HOME%\server\lib\weblogic.jar dk/topsecurity/JMSQueueReceiver




Or another way to grab the messages (listener)...


Using Windows platform (yeah.. not by preferred choice).. let's have an object listen for messages from the queue... remember to set wl_home to your weblogic installation directory of choice..
queueListenTest.cmd


set BEA_HOME=C:\weblogicplatform
set WL_HOME=C:\weblogicplatform\weblogic81

java -classpath .;TopsecurityJMS.jar;%WL_HOME%\server\lib\weblogic.jar dk/topsecurity/JMSQueueListener





Compiling... we get something like this...



7 classes it says... ok, you pulled the curtain on me.. :) I compiled a couple of additonal helper classes also...

Getting the transmitter up working...



Yeah, I was a bit slow to get the receiver up and running, so I got plenty of messages...



Stopping the receiver - restarting the transmitter - and starting the lister (instead of the receiver) gives... basicly same image...