JMS - Java Message Service



JMS publish-subscribe 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

...
<JMSTopic JNDIName="dk.topsecurity.topic" Name="dk.topsecurity.topic" 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..
JMSTopicPublisher.java


package dk.topsecurity;

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

/**
 * The publish/subscribe (pub/sub) messaging model enables an application to 
 * send a message to multiple applications. Pub/sub messaging applications 
 * send and receive messages by subscribing to a topic. A topic publisher 
 * (producer) sends messages to a specific topic. A topic subscriber 
 * (consumer) retrieves messages from a specific topic.
 */
public class JMSTopicPublisher {

    public final static String TOPIC_NAME = "dk.topsecurity.topic";
    public final static String JMS_FACTORY = "weblogic.jms.ConnectionFactory";
//  public final static String JMS_FACTORY = "javax.jms.TopicConnectionFactory"

    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();
            TopicConnectionFactory factory =
                (TopicConnectionFactory) ctx.lookup(JMS_FACTORY); //get Topic Connection Factory by JNDI
            TopicConnection conn = factory.createTopicConnection(); //create a new Topic Connection
            TopicSession session = conn.createTopicSession(false,
                Session.AUTO_ACKNOWLEDGE); //create a non-transactional TopicSession
            Topic topic = null;
            try {
                topic = (Topic) ctx.lookup(TOPIC_NAME); //check if someone has already created the topic
            }
            catch (NameNotFoundException exc) {
                topic = session.createTopic(TOPIC_NAME);
                ctx.bind(TOPIC_NAME, topic); //if not, create a new topic and store it in JNDI directory
            }
            TopicPublisher sender = session.createPublisher(topic); //create a publisher to publish msg
            conn.start(); //tell Topic Connection you are ready to interact with the message service
            for (;;) {
		String messageTxt = "Hello from publisher at " + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new java.util.Date());
                TextMessage message = session.createTextMessage(messageTxt); //create simple text message
                sender.publish(message); //publish the 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..
JMSTopicReceiver.java


package dk.topsecurity;

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

/**
 * The publish/subscribe (pub/sub) messaging model enables an application to 
 * send a message to multiple applications. Pub/sub messaging applications 
 * send and receive messages by subscribing to a topic. A topic publisher 
 * (producer) sends messages to a specific topic. A topic subscriber 
 * (consumer) retrieves messages from a specific topic.
 */
public class JMSTopicReceiver {

    public final static String TOPIC_NAME = "dk.topsecurity.topic";
    public final static String JMS_FACTORY = "weblogic.jms.ConnectionFactory";
//  public final static String JMS_FACTORY = "javax.jms.TopicConnectionFactory"

    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();
            TopicConnectionFactory factory =
                (TopicConnectionFactory) ctx.lookup(JMS_FACTORY); //get Topic Connection Factory by JNDI
            TopicConnection conn = factory.createTopicConnection(); //create new Topic Connection
            TopicSession session = conn.createTopicSession(false,
                Session.AUTO_ACKNOWLEDGE); //create non-transactional Topic Session
            Topic topic = null;
            try {
                topic = (Topic) ctx.lookup(TOPIC_NAME); //check if someone has already created the topic
            }
            catch (NameNotFoundException exc) {
                topic = session.createTopic(TOPIC_NAME);
                ctx.bind(TOPIC_NAME, topic); //if not, create new topic and store it in JNDI directory
            }
            TopicSubscriber subscriber = session.createSubscriber(topic); //create subscriber to receive msg
            conn.start(); //tell the Topic Connection you are ready to interact with the message service
            for (;;) { //receive next message and echo message contents to console
                System.out.println(((TextMessage) subscriber.receive()).getText()); //echo message text to console
            }
        }
        catch (Exception exc) {
            exc.printStackTrace();
        }
    }
}


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


package dk.topsecurity;

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

/**
 * The publish/subscribe (pub/sub) messaging model enables an application to 
 * send a message to multiple applications. Pub/sub messaging applications 
 * send and receive messages by subscribing to a topic. A topic publisher 
 * (producer) sends messages to a specific topic. A topic subscriber 
 * (consumer) retrieves messages from a specific topic.
 */
public class JMSTopicListener implements MessageListener {

    public final static String TOPIC_NAME = "dk.topsecurity.topic";
    public final static String JMS_FACTORY = "weblogic.jms.ConnectionFactory";
//  public final static String JMS_FACTORY = "javax.jms.TopicConnectionFactory"

    JMSTopicListener() { }

    public void onMessage(Message message) {
        try { //assumes TextMessage
            System.out.println(((TextMessage) message).getText());
        }
        catch (Exception 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();
            TopicConnectionFactory factory =
                (TopicConnectionFactory) ctx.lookup(JMS_FACTORY);
            TopicConnection conn = factory.createTopicConnection();
            TopicSession session = conn.createTopicSession(false,
                Session.AUTO_ACKNOWLEDGE);
            Topic topic = null;
            try {
                topic = (Topic) ctx.lookup(TOPIC_NAME);
            }
            catch (NameNotFoundException exc) {
                topic = session.createTopic(TOPIC_NAME);
                ctx.bind(TOPIC_NAME, topic);
            }
            TopicSubscriber subscriber = session.createSubscriber(topic);
            conn.start();
            subscriber.setMessageListener(new JMSTopicListener());

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


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

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




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


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

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




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


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

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




It can look like this...



7 classes it says... ok... well... I compiled a couple of additonal helper classes also...

Getting two transmitters up and working (we could launch any number)...



Launching two receivers, we get plenty of messages...



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