Jump start WebSphere MQ development on Linux

This article shows you how to get started installing and configuring WebSphere MQ on Linux and developing Java applications for the MQ environment, using sample applications for sending messages to and receiving messages from a queue.

Sami Salkosuo (sami.salkosuo@fi.ibm.com), Software Architect, EMC

Sami Salkosuo is a Software Architect with IBM Global Business Services in Helsinki. Has worked at IBM for eight years, and his main area of interest is programming in Java, Python, and PHP. His certifications include Sun Certified Java Programmer, IBM Certified Solution Developer for XML and Related Technologies, and IBM Certified Solution Designer for WebSphere MQ. You can contact Sami at sami.salkosuo@fi.ibm.com.



02 May 2007

Also available in Chinese

Introduction

The goal of this article is to make it easy for you to get started with IBM® WebSphere® MQ on Linux®. Because most Linux servers do not have graphical user interfaces, the article will show you how to install and configure WebSphere MQ on Linux using command-line tools. The article will show you how to create two sample Java™ applications u using the WebSphere MQ Java API: MQSend to send messages to a queue and MQGet to receive messages from a queue.

Prerequisites

  • WebSphere MQ V6 install packages.
  • One or two machines with Linux installed.This article used two machines with Suse Linux Enterprise Server V9, you can do everything on one machine.
  • Linux administration skills.
  • Experience in Java development is helpful but not necessary because pre-compiled Java sample applications are provided for you to download and use from the command line.

WebSphere MQ

WebSphere MQ provides a foundation for SOA by providing a connectivity layer and reliable integration for applications. Major WebSphere MQ features include:

Assured message delivery
Reliable queue-based messaging ensures that messages are not lost or duplicated.
Standards-based development
Using Java Message Service (JMS) API and Message Queue Interface (MQI).
End-to-end security
Secure Sockets Layer (SSL) for authentication, message integrity checking, and data encryption.
Web services support
Simple Object Access Protocol (SOAP) for Web services transport and reliability.
Asynchronous processing
Decoupling of applications in order to enable time-independent processing.
Multi-platform support
Support for over 80 platform configurations.

For more information about WebSphere MQ, see resources at the bottom of the article.

Installing WebSphere MQ

Installing WebSphere MQ is a breeze -- simply unpack the install packages to a directory (this article uses mq_install under the root home directory) You can install all of the RPM install packages but this article requires only. Here are the packages and directories included in WebSphere MQ V6:

IBMJava2-SDK-1.4.2-0.0.i386.rpm
MQSeriesClient-6.0.0-0.i386.rpm
MQSeriesConfig-6.0.0-0.i386.rpm
MQSeriesFTA-6.0.0-0.i386.rpm
MQSeriesIES30-6.0.0-0.i386.rpm
MQSeriesJava-6.0.0-0.i386.rpm
MQSeriesKeyMan-6.0.0-0.i386.rpm
MQSeriesMan-6.0.0-0.i386.rpm
MQSeriesMsg_Zh_CN-6.0.0-0.i386.rpm
MQSeriesMsg_Zh_TW-6.0.0-0.i386.rpm
MQSeriesMsg_de-6.0.0-0.i386.rpm
MQSeriesMsg_es-6.0.0-0.i386.rpm
MQSeriesMsg_fr-6.0.0-0.i386.rpm
MQSeriesMsg_it-6.0.0-0.i386.rpm
MQSeriesMsg_ja-6.0.0-0.i386.rpm
MQSeriesMsg_ko-6.0.0-0.i386.rpm
MQSeriesMsg_pt-6.0.0-0.i386.rpm
MQSeriesRuntime-6.0.0-0.i386.rpm
MQSeriesSDK-6.0.0-0.i386.rpm
MQSeriesSamples-6.0.0-0.i386.rpm
MQSeriesServer-6.0.0-0.i386.rpm
MQSeriesTXClient-6.0.0-0.i386.rpm
PreReqs
READMEs
copyright
gsk7bas-7.0-3.15.i386.rpm
lap
licenses

Here are the installation steps:

  1. Set up a Linux server. This article uses hostnames WMQ1 and WMQ2. IP address of WMQ1 is 192.168.28.71 and IP-address of WMQ2 is 192.168.28.72.
  2. Before installing WebSphere MQ, you must execute ./mqlicense.sh to read and accept the license.
  3. Install the required MQ packages and also the WebSphere MQ Java and IBM Java SDK packages, so that you can develop Java clients for WebSphere MQ:
    wmq1:~/mq_install # rpm -ivh IBMJava2-SDK-1.4.2-0.0.i386.rpm
    wmq1:~/mq_install # rpm -ivh MQSeriesRuntime-6.0.0-0.i386.rpm
    wmq1:~/mq_install # rpm -ivh MQSeriesServer-6.0.0-0.i386.rpm
    wmq1:~/mq_install # rpm -ivh MQSeriesJava-6.0.0-0.i386.rpm

WebSphere MQ is now installed, with a user and group called mqm that are used for configuration. By default, WebSphere MQ is installed in /opt/mqm and queues and other configuration information is located in the home directory of user mqm. The Java SDK is installed in /opt/IBMJava2-142 and the Java interpreter is located in /opt/IBMJava2-142/bin.

The next step is configuration. This article uses one queue manager with local and remote queues for both machines, which are used to test the sample applications.

Configuring WebSphere MQ

WebSphere MQ terms and definitions

Queue manager
System program that provides queueing services and API as well administrator functions to manage queues.
Queue
Named destination to which messages are sent.
Local queue
Queue that is local to a queue manager.
Remote queue
Queue that resides in other queue manager, possibly on other host.
Transmission queue
Temporary queue of messages that are destined to a remote queue.
Channel
Communication path from one queue manager to another.
Listener
Process that accepts network request from clients or other queue managers.
Command server
Verifies commands and sends valid commands to command processor that then executes the command.

Configuration consists of following steps:

  • Create queue manager.
  • Start queue manager.
  • Create queues and channels.
  • Start command server, listener, and channels.

These steps are required on both WebSphere MQ machines. The sections below show configuration only on WMQ1, but the same steps are required on WMQ2 also.

Create and start queue managers

Log in to WMQ1 using root and then change to user mqm by typing su - mqm. Create queue manager for the WMQ1 machine using the following command:

mqm@wmq1:~/ # crtmqm WMQ1QM

Start the queue manager using following command.

mqm@wmq1:~/ # strmqm WMQ1QM

Create queue and channels

Configure WebSphere MQ using command-line tools. A configuration script for WMQ1 is below. The script defines local queue, remote queue, transmission queue, sender channel, and receiver channel.Save the script as WMQ1QM.conf:

DEFINE QLOCAL ('WMQ1InputQ') +
		 REPLACE

DEFINE QLOCAL ('WMQ2QMXmitQ') +
		 DESCR('Transmission Queue to WMQ2QM') +
		 USAGE(XMITQ) +
		 TRIGGER +
		 TRIGTYPE(FIRST) +
		 TRIGDPTH(1) +
		 TRIGDATA('WMQ1QM.WMQ2QM') +
		 INITQ('SYSTEM.CHANNEL.INITQ') +
		 REPLACE

DEFINE QREMOTE ('WMQ1OutputQ') +
		 XMITQ('WMQ2QMXmitQ') +
		 RNAME('WMQ2InputQ') +
		 RQMNAME('WMQ2QM') +
		 REPLACE

DEFINE CHANNEL ('WMQ1QM.WMQ2QM') CHLTYPE(SDR) +
		 TRPTYPE(TCP) +
		 CONNAME('192.168.28.72(1414)') +
		 XMITQ('WMQ2QMXmitQ') +
		 REPLACE

DEFINE CHANNEL ('WMQ2QM.WMQ1QM') CHLTYPE(RCVR) +
		 TRPTYPE(TCP) +
		 REPLACE

DEFINE CHANNEL ('SYSTEM.ADMIN.SVRCONN') CHLTYPE(SVRCONN) +
		 TRPTYPE(TCP) +
		 DESCR(' ') +
		 HBINT(300) +
		 MAXMSGL(4194304) +
		 MCAUSER('MUSR_MQADMIN') +
		 RCVDATA(' ') +
		 RCVEXIT(' ') +
		 SCYDATA(' ') +
		 SCYEXIT(' ') +
		 SENDDATA(' ') +
		 SENDEXIT(' ') +
		 REPLACE

The configuration script above can be used as a template for other WebSphere MQ installations. Only the names in bold need to be changed to set up queues and channels in other WebSphere MQ installations. There are lots of entries in the configuration script -- for more information about them, see the WebSphere MQ Information Center.

Configure WebSphere MQ using the command below to create queues and channels:

mqm@wmq1:~/ # runmqsc WMQ1QM < WMQ1QM.conf > qcreate.log

The command runmqsc is used to issue WebSphere MQ commands. In this case, commands are read from the WMQ1QM.conf file and output is directed to qcreate.log. Open qcreate.log and verify that there were no syntax errors and all valid commands were processed.

Start services

The command server, listener, and channels need to be started and then everything is ready for developing and testing the sample applications:

mqm@wmq1:~/ # strmqcsv WMQ1QM &
mqm@wmq1:~/ # runmqlsr -m WMQ1QM -t TCP &

Verify that the queue managers and listeners are running on both machines, then start the channels:

mqm@wmq1:~/ # runmqchl -m WMQ1QM -c WMQ1QM.WMQ2QM &
mqm@wmq1:~/ # runmqchl -m WMQ1QM -c WMQ2QM.WMQ1QM &

WebSphere MQ is now installed, configured, and ready to tested. The next section will show the source code of two Java-based applications to send messages to and receive messages from the queue.

Sample applications

The queue defined in the previous section can be used by the sample Java applications for putting messages in the queue (MQSend) and getting messages out (MQGet). These applications support String messages and are intended for testing and for examples of how to use WebSphere MQ from Java applications. Applications could be used from scripts, which enables all kinds of applications. Both MQSend and MQGet extend from MQConnector class, which provides WebSphere MQ connectivity, initialises WebSphere MQ, opens and closes a queue, and sends messages to and receives messages from a queue.

MQConnector

MQConnector is a superclass for sending and getting. This class handles opening the connection and sending and getting messages. You configure it using a properties file that specifies the host address, queue manager name, and queue name:

queue.manager=WMQ1QM
queue.manager.host=192.168.28.71
queue.name=WMQ1OutputQ

Here is the MQConnector source code:

package mqconn;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

import com.ibm.mq.MQC;
import com.ibm.mq.MQEnvironment;
import com.ibm.mq.MQException;
import com.ibm.mq.MQGetMessageOptions;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;

public class MQConnector
{
  protected String qManager = ""; // define name of queue manager

  protected String qManagerHost = "";

  protected String queuName = ""; // define name of queue

  protected MQQueue mqQueue;

  protected MQQueueManager qMgr;

  public static boolean DEBUG = true;

  public MQConnector()
  {

  }

  public void initMq()
  {
    try
    {
      FileInputStream fis = new FileInputStream(new File("mqconnect.properties"));
      Properties props = new Properties();
      props.load(fis);
      fis.close();
      qManager = props.getProperty("queue.manager");
      qManagerHost = props.getProperty("queue.manager.host");
      queuName = props.getProperty("queue.name");

	  // Create a connection to the queue manager
      MQEnvironment.channel = "SYSTEM.DEF.SVRCONN";
      MQEnvironment.hostname = qManagerHost;
      debug("Connecting to QueueManager " + qManager + " on " + qManagerHost);
      qMgr = new MQQueueManager(qManager);
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
  }

  public void openQueue() throws MQException
  {
    // Set up the options on the queue we wish to open...
    // Note. All WebSphere MQ Options are prefixed with MQC in Java.
     int openOptions = MQC.MQOO_INPUT_AS_Q_DEF | MQC.MQOO_OUTPUT;
    // Now specify the queue that we wish to open,
    // and the open options...    
    debug("Opening queue: " + queuName);
    try
    {
      mqQueue = qMgr.accessQueue(queuName, openOptions);
    }
    catch(MQException mqe)
    {
      //check if MQ reason code 2045
      //means that opened queu is remote and it can not be opened as 
      //input queue
      //try to open as output only
      if(mqe.reasonCode==2045)
      {
        openOptions = MQC.MQOO_OUTPUT;
        mqQueue = qMgr.accessQueue(queuName, openOptions);
      }
    }
  }
    
  public void putMessageToQueue(String msg) throws MQException
  {
    try
    {
      debug("Sending message: " + msg);

      MQPutMessageOptions pmo = new MQPutMessageOptions(); 
      MQMessage mqMsg = new MQMessage();
      mqMsg.write(msg.getBytes());

      // put the message on the queue
      mqQueue.put(mqMsg, pmo);
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }

  public String getMessageFromQueue() throws MQException 
  {
    try
    {
      MQMessage mqMsg = new MQMessage();
      
      MQGetMessageOptions gmo = new MQGetMessageOptions();

      // Get a message from the queue
      mqQueue.get(mqMsg,gmo);  
       
      //Extract the message data
      int len=mqMsg.getDataLength();
      byte[] message = new byte[len];
      mqMsg.readFully(message,0,len);
      return new String(message);
    }
    catch(MQException mqe)
    {
      int reason=mqe.reasonCode;
      
      if(reason==2033)//no messages
      {
        return null;
      }
      else
      {
        throw mqe;
      }
    }    
    catch (IOException e)
    {
      e.printStackTrace();
      return null;
    }
  }
  
  
  public void closeQueue() throws MQException
  {
    debug("Closing queue and disconnecting QueueManager...");

    // Close the queue...
    mqQueue.close();
    // Disconnect from the queue manager
    qMgr.disconnect();

  }

  protected boolean hasArg(String arg, String[] args)
  {
    for(int i=0;i<args.length;i++)
    {
      if(args[i].equals(arg))
      {
        return true;
      }
    }
    return false;
  }
  
  public void debug(Object msg)
  {
    if (DEBUG)
    {
      System.out.println(msg);
    }
  }
    
}

This class provides WebSphere MQ functionality to other applications. You can also use MQConnector in your own applications as a super class of your own class, or as a utility class. The following methods provide messaging capability to Java applications:

initMQ()
Reads properties and creates queue manager object.
openQueue()
Opens queue that is specified in properties file.
closeQueue()
Closes opened queue.
disconnectMq()
Disconnects queue manager.
putMessageToQueue(String)
Puts a string message to specified queue.
getMessageFromQueue()
Reads string message from specified queue.

MQSend

MQSend (shown below) uses MQConnector class and is used as a command-line program to send messages to a queue. Messages are specified as command-line arguments, and you can use it to send the contents of a file as a message:

package mqconn;

import java.io.BufferedReader;
import java.io.FileReader;

import com.ibm.mq.MQException;

public class MQSend extends MQConnector
{

  public MQSend()
  {

  }

  public void send(String[] args) throws MQException
  {
    boolean argsAreFiles = hasArg("-f", args);
    initMq();
    openQueue();
    for (int i = 0; i < args.length; i++)
    {
      if (args[i].equals("-f"))
        continue;

      if (!argsAreFiles)
      {
        putMessageToQueue(args[i]);
      }
      else
      {
        try
        {
          // send file contents as message
          BufferedReader br = new BufferedReader(new FileReader(args[i]));

          StringBuffer msg = new StringBuffer();
          for (String line = br.readLine(); line != null; line = br.readLine())
          {
            msg.append(line);
            msg.append('\n');
          }

          br.close();
          putMessageToQueue(msg.toString());
        }
        catch (Exception e)
        {
          System.out.println("Error while processing file " + args[i] + ": "
              + e.toString());
        }
      }
      System.out.println("Message sent.");
    }

    closeQueue();
    disconnectMq();
  }

  public static void main(String[] args)
  {
    MQSend mqsend = new MQSend();
    MQConnector.DEBUG = false;
    try
    {
      if (args == null || args.length == 0)
      {
        System.out.println("Usage: " + mqsend.getClass().getName()
            + " [-f] <file name | message> [<file name | message> ...]");
        System.exit(0);
      }
      mqsend.send(args);
    }
    catch (Exception e)
    {
      System.out.println(e.toString());
      System.out.println("Usage: " + mqsend.getClass().getName()
          + " [-f] <file name | message> [<file name | message> ...]");
    }

  }

}

MQSend uses MQConnector to provide messaging and the actual MQSend program functionality is very simple. There are two modes of operation:

  • Send each command-line argument as a separate message.
  • Send file contents using the -f option. In this case, each command-line argument is a file name.

MQGet

MQGet class (shown below) is simple -- it retrieves one message from a specified queue and writes it to standard out. you can store the message in a file by using a redirect.

package mqconn;

import com.ibm.mq.MQException;

public class MQGet extends MQConnector
{
  public MQGet()
  {
    
  }
  
  public String getMessages(String[] args) throws MQException
  {
   String message=getMessageFromQueue();
   return message;
    
  }
  
  public static void main(String[] args)
  {
    MQGet mqget = new MQGet();
    MQConnector.DEBUG=false;
    try
    {
      mqget.initMq();
      mqget.openQueue();

      String msg=mqget.getMessages(args);
      if(msg!=null)
      {
        System.out.println(msg);      
      }
      
      mqget.closeQueue();
      mqget.disconnectMq();      
    }
    catch (Exception e)
    {
      e.printStackTrace();
      System.out.println("Usage: "+mqget.getClass().getName()+" ");
    }
  }
}

MQGet uses the queue manager and queue specified in the mqconnect.properties file. The next section presents some sample use cases that you can use for testing.

Sample use cases

Here are a few use cases on how to use MQSend and MQGet applications, using WMQ1 as sender and WMQ2 as receive.r

Preparations

Before using the samples, you need to do some preparation such as setting up properties and making a couple of helper scripts. Use the following properties for the MQSend application in WMQ1:

queue.manager=WMQ1QM
queue.manager.host=127.0.0.1
queue.name=WMQ1OutputQ

Use the following properties for the MQGet application in WMQ2:

queue.manager=WMQ2QM
queue.manager.host=127.0.0.1
queue.name=WMQ2InputQ

To save typing, here are two scripts for sending and receiving

/opt/IBMJava2-142/bin/java -cp .:com.ibm.mq.jar mqconn.MQSend "$@"
/opt/IBMJava2-142/bin/java -cp .:com.ibm.mq.jar mqconn.MQGet "$@"

Change the scripts into executables using chmod 755 mqsend and chmod 755 mqget. All classes and other files in this article are located in the /var/mqm/bin directory where /var/mqm is the home directory of mqm-user.

Commands

The first sample command sends message to a queue specified above. The sample listing provide the actual command and also the output of the command.

mqm@wmq1:~/bin> ./mqsend "This is test message"
MQJE001: Completion Code 2, Reason 2045
Message sent.

MQJE001 is expected. Reason 2045 means in this case that the queue to be opened cannot be opened as an input queue because the queue is remote. MQJE001 is printed to standard error by WebSphere MQ classes. If you don't want to see these error message, redirect standard error to /dev/null ./mqsend "This is test message" 2> /dev/null. To find out what the reason code means, use mqrc 2045.

On WMQ2, use the mqget command to receive the message:

mqm@wmq2:~/bin> ./mqget
This is test message

If you execute mqget again, you get the expected MQJE001 message. mqrc 2033 shows that 2033 means "MQRC_NO_MSG_AVAILABLE." Retrieving the message removes it from the queue. Here is how to send multiple messages:

mqm@wmq1:~/bin> ./mqsend "This is test message" This is another message
MQJE001: Completion Code 2, Reason 2045
Message sent.
Message sent.
Message sent.
Message sent.
Message sent.

Receiving messages is the same mqget command shown above. Here is how to receive multiple messages:

mqm@wmq2:~/bin> ./mqget
This is test message
mqm@wmq2:~/bin> ./mqget
This
mqm@wmq2:~/bin> ./mqget
is
mqm@wmq2:~/bin> ./mqget
another
mqm@wmq2:~/bin> ./mqget
message
mqm@wmq2:~/bin> ./mqget
MQJE001: Completion Code 2, Reason 2033

The next sample sends the contents of all Java files:

mqm@wmq1:~/bin> ls -1 mqconn/*.java | awk '{print "mqsend -f "$1""}' | sh 2> /dev/null
Message sent.
Message sent.
Message sent.

The next sample reads messages and saves them to a file:

mqm@wmq2:~/bin> ./mqget > msg1.txt

The output of the mqget command is directed to msg1.txt.

Conclusion

This article showed you how to get started using WebSphere MQ on Linux. Only a few installation and configuration steps are required to get WebSphere MQ running, and these steps provide a good starting point for learning more about WebSphere MQ. The sample applications showed how easy it is to get programmatic access to WebSphere MQ and its messaging capabilities. The sample applications are also a good starting point for developing custom applications.


Download

DescriptionNameSize
Sample codemqsamples.zip332 KB

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere, Linux
ArticleID=216821
ArticleTitle=Jump start WebSphere MQ development on Linux
publish-date=05022007