Friday, January 15, 2016

JMS tutorial - using Oracle WLS_Server as a JMS Provider

Hi folks , writing after a very long time , this is my first blog in 2016 .
Today I am going to share  how to run a sample program to send and receive messages to a JMS Queue .

So first lets brief you about JMS .

What Is Messaging?


Messaging is a method of communication between software components or applications.  A messaging client can send messages to, and receive messages from, any other client. Each client connects to a messaging agent that provides facilities for creating, sending, receiving, and reading messages.

What Is the JMS API?


The Java Message Service is a Java API that allows applications to create, send, receive, and read messages. Designed by Sun and several partner companies, the JMS API defines a common set of interfaces and associated semantics that allow programs written in the Java programming language to communicate with other messaging implementations.

For more details on JMS specification read here .

Pre requisites for this java exercise :


1. Install Oracle Weblogic Server 12.1.3 is preferred since this exercise has been done with WLS 12.1.3.
2. Create a domain on the WLS and a managed_server to deploy applications , target the JMS modules .
3. Your admin server , managed server should be up and running .

Configuration 


1. Create a JMS Server :

A JMS server acts as a management container for resources within JMS modules. Some of its responsibilities include the maintenance of persistence and state of messages and subscribers. A JMS server is required in order to create a JMS module.    




-> Services > Messaging > JMS Servers
Select New
Name  : testJMSServer
Persistent Store: (none)  -> Next
Target : managed_server-1 [The managed Server created and configured in your Oracle WLS_Server]
Finish





-------------------------------------------------------------------------------------------------------------------------


The JMS server should now be visible in the list with Health OK.    


2. Create a JMS Module

A JMS module is a definition which contains JMS resources such as queues and topics. A JMS module is required in order to create a JMS queue.    

-> Services > Messaging > JMS Modules -> New         
Name: testJMSModule  ->  Leave the other options empty  -> Next 
-> Targets: managed_server- 1  (or choose the same one as the JMS server)     
-> Leave “Would you like to add resources to this JMS system module” unchecked and  press Finish
 
3. Create a Connection Factory       
 
A connection factory is a resource that enables JMS clients to create connections to JMS destinations.    
 
-> Services > Messaging > JMS Modules
-> select testJMSModule and click New
-> Select Connection factory -> Next
-> Name: testConnectionFactory , JNDI Name : jms/testcf
-> Leave the other values at default
->  Advanced Targeting -> Subdeployments -> Click Create a new Sub deployment
A subdeployment is a mechanism by which JMS resources are grouped and targeted to a server instance or a cluster . 
Subdeployment Name : testJMSSubdeployment -> OK 
On Tagets -> check managed_server-1 and testJMSServer or the corresponding names you have used in this exercise.
 
 
4. Create a JMS Queue      
 
A JMS queue (as opposed to a JMS topic) is a point-to-point destination type. A message is written to a specific queue or received from a specific queue.
 
-> Services > Messaging > JMS Modules
-> select testJMSModule and click New
-> Select Queue -> Next
-> Name: testQueue , JNDI Name : jms/testq
-> Template : None 
->  Subdeployments -> testJMSSubdeployment -> OK 
On Tagets -> check testJMSServer.
Finish
 
You should see the following resources under testJMSModule under Services -> Messaging ->  JMS Modules
 

 
The JMS queue is now complete and can be accessed using the JNDI names
jms/testcf
jms/testq
 

If you hit  exception  :
 
java.lang.ClassCastException: weblogic.management.configuration.ServerMBeanImpl cannot be cast to weblogic.management.configuration.JMSServerMBean

Workaround :

- create jms queue without subdeployment specified and save
- edit queue and then set subdeployment then save
 
Now we have finished all the configuration and our JMSModule on the WLS_SERVER is ready to accept messages from a client and to send back to another client .

5. Let's come to coding part .

I am showing the simplest way possible to do this exercise hence I will be creating a Java Project TestJMS , create a package named   jms.test  in a src directory , create a folder in this project called lib  .

Now under your Oracle_Home which would look like this C:\OracleHome may be different for you ; this is the root directory from where you go and run your weblogic scripts etc.

-> Under OracleHome -> wlsserver -> modules -> copy all jars(*.jar) and paste in under the lib , also OracleHome -> wlsserver -> server -> lib -> copy all jars(*.jar) and paste in under the lib  .

Create three class files under this package MyListener.java , MyReceiver.java and MySender.java

The following is the source code and I am explaining the code in the comments section in the code itself , have a look .

/**
 * This example shows how to establish a connection and send messages to the JMS
 * queue. The classes in this package operate on the same JMS queue. Run the
 * classes together to see the messages being sent and received.
 * @author Anmol Deep
 */

MySender.java

package jms.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Hashtable;
import java.util.Properties;

import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

 
/**
 * The class is used to send messages to the queue.
 */
public class MySender {
 // Defines the JNDI context factory.
 public final static String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";

 // Defines the Connection Factory's JNDI name
 public final static String JMS_FACTORY = "jms/testcf";

 // Defines the queue's JNDI name
 public final static String QUEUE = "jms/testq";

 private QueueConnectionFactory qconFactory;
 private QueueConnection qcon;
 private QueueSession qsession;
 private QueueSender qsender;
 private Queue queue;
 private TextMessage msg;


 public void init(Context ctx, String queueName) throws NamingException,
   JMSException {

         // Create the QueueConnectioFactory by lookup JNDI name
         qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);

         // Create the Queue Connection
         qcon = qconFactory.createQueueConnection();

         // Create the QueueSession
         qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

         // Create the Queue object by lookup JNDI name
         queue = (Queue) ctx.lookup(queueName);

         // Create the QueueSender object
         qsender = qsession.createSender(queue);

         // Create the TextMessage Object
         msg = qsession.createTextMessage();

         // Start the Queue Connection
         qcon.start();
 }

 
 /**
  * Sends a message to a JMS queue.
  *
  * @param message
  *            message to be sent
  * @exception JMSException
  *                if JMS fails to send message due to internal error
  */
 public void send(String message) throws JMSException {
      msg.setText(message);
      qsender.send(msg);
 }

 
 /**
  * Closes JMS objects.
  *
  * @exception JMSException
  *                if JMS fails to close objects due to internal error
  */
 public void close() throws JMSException {
      qsender.close();
      qsession.close();
      qcon.close();
 }

 
 /**
  * main() method.
  *
  * @exception Exception
  *                if operation fails
  */
 public static void main(String[] args) throws Exception {
      Properties parm = new Properties();
      parm.setProperty(Context.INITIAL_CONTEXT_FACTORY,
        "weblogic.jndi.WLInitialContextFactory");

      // weblogic managed server URL
      parm.setProperty(Context.PROVIDER_URL, "t3://localhost:7002");
      parm.setProperty("java.naming.security.principal", "weblogicUserName");
      parm.setProperty("java.naming.security.credentials", "weblogicPassword");

  
      Context ctx = new InitialContext(parm);
      ctx.lookup(QUEUE);
      MySender qs = new MySender();
      qs.init(ctx, QUEUE);
      readAndSend(qs);
      qs.close();
 }

 private static void readAndSend(MySender mySender) throws IOException,
   JMSException {
      BufferedReader msgStream = new BufferedReader(new InputStreamReader(
        System.in));
      String text= null;
      boolean quitting = false;
      do {
      System.out.print("Enter message (\"quit\" to quit): \n");
      text= msgStream.readLine();
      if (text!= null && text.trim().length() != 0) {
       mySender.send(text);
       System.out.println("JMS Message Sent: " + text+ "\n");
       quitting= text.equalsIgnoreCase("quit");
      }
     } while (!quitting);
    }
  }


A MessageListener object is used to receive asynchronously delivered messages. 

For more info.  read  this

MyListener.java

package jms.test;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
public class MyListener implements MessageListener {

public void onMessage(Message m) {
      try{
          TextMessage textMessage=(TextMessage)m;
          System.out.println("Following Message Receieved :"+textMessage.getText());
      }catch(JMSException e){

          System.out.println(e);
          e.printStackTrace();}
     }
}


 
MyReceiver.java

package jms.test;
import java.util.Properties;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;

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

           Properties parm = new Properties();
           parm.setProperty(Context.INITIAL_CONTEXT_FACTORY,
             "weblogic.jndi.WLInitialContextFactory");
           parm.setProperty(Context.PROVIDER_URL, "t3://localhost:7002");
           parm.setProperty("java.naming.security.principal", "weblogicUserName");
           parm.setProperty("java.naming.security.credentials", "weblogicPassword");

           Context ctx = new InitialContext(parm);
 
           QueueConnectionFactory qconF= (QueueConnectionFactory) ctx
                 .lookup("jms/testcf");
           QueueConnection qCon = qconF.createQueueConnection();
           qCon.start();

           QueueSession qSess = qCon.createQueueSession(false,
     Session.AUTO_ACKNOWLEDGE);

     Queue queue = (Queue) ctx.lookup("jms/testq");
   

   QueueReceiver qReceiver = qSess.createReceiver(queue);
   // create listener object
   MyListener listener = new MyListener();

   // register the listener object with receiver
   qReceiver.setMessageListener(listener);

   System.out.println("Receiver is ready, waiting for messages.");
   System.out.println("press Ctrl+c to shutdown...");
   while (true) {
    Thread.sleep(1000);
   }
  } catch (Exception e) {
   e.printStackTrace();
   System.out.println(e);
  }
 }

}
Run the MySender class
Run the MyReciever class
On Weblogic  Under JMSModules - > testJMSModule - > testQueue ->  Monitoring tab ->  Show Messages

Sample Output :

MySender

Enter message ("quit" to quit):
This is a sample program to Send messages to a JMS Queue
JMS Message Sent: This is a sample program to Send messages to a JMS Queue

Enter message ("quit" to quit):

This is the second Message Sent 

JMS Message Sent: This is the second Message Sent

 

Enter message ("quit" to quit):

quit
JMS Message Sent: quit

MyReceiver


Receiver is ready, waiting for messages.
press Ctrl+c to shutdown...
Following Message Receieved :This is a sample program to Send messages to a JMS Queue
Following Message Receieved :This is the second Message Sent
Following Message Receieved :"quit"
Following Message Receieved :quit

End of Exercise
Happy Coding .

No comments:

Post a Comment