How to connect a Java app to MSMQ, the queuing system that is integrated into Windows? The question gets asked often. There are a number of third party bridges, COM bridges, or even JMS layers on top of MSMQ. But I haven't seen any simple or free mechanisms. It's possible, though.

MSMQ is exposed via at least 3 different programming interfaces: the C library interface; the COM interface, suitable for VB apps and other COM environments; and the System.Messaging namespace in the .NET base class library. Connecting Java to MSMQ means bridging from Java into one of those existing layers. The Java Native Interface is Java's way to integrate C/C++ libraries with Java applications. But JNI is not what you'd call "easy to use". It requires both Java and C/C++ skills, so not very accessible for most developers. But JNI is powerful, as this example shows.

The C api for MSMQ includes functions like MQOpenQueue(), MQCreateQueue, MQReceiveMessage() and so on. They provide all the low-level function an app needs, but it's an old-style library: not organized into classes. The interface is a typical C library: based on return codes (HRESULTS), no exception handling, lots of handles and pointers. All very un-OO. So what we'll do is build an object layer in Java on top of those library functions.

The main Java class is called Queue, and looks like this:

public class Queue

{

    public Queue(String queueName)

        throws  MessageQueueException ;

 

    public static Queue create(String queuePath, String queueLabel, boolean isTransactional)

        throws  MessageQueueException ;

 

    public static void delete(String queuePath)

        throws  MessageQueueException ;

 

    public void send(Message msg)

        throws  MessageQueueException ;

 

    public void send(String s) 

        throws  MessageQueueException ;

 

    public ionic.Msmq.Message receive(int timeout)

        throws  MessageQueueException ;

 

    public ionic.Msmq.Message receive()

        throws  MessageQueueException ;

 

    public ionic.Msmq.Message peek()

        throws  MessageQueueException ;

 

    public ionic.Msmq.Message peek(int timeout)

        throws  MessageQueueException ;

 

    public void close()

        throws  MessageQueueException ;

 

    public String getName();

    public String getLabel();

    public String getFormatName();

    public boolean isTransactional();

}

Instantiating a queue object implicitly opens the named backing queue. There's a static create() method , which also opens the newly created queue. This is roughly modelled on the System.Messaging.MessageQueue class from .NET. The basic programming model is similar, but of course this Queue class is much more basic.

The supporting Message class provides the abstraction for the message, including encapsulating the message body, label, and correlationId.

public class Message

{

    public void setMessage(String value) ;

    public String getMessage() ;

 

    public void setLabel(String value) ;

    public String getLabel() ;

 

    public void setCorrelationId(String value) ;

    public String getCorrelationId() ;

 

    public void setTransactionFlag(int value) ;

    public int getTransactionFlag() ;

 

    public int getStatus() ;

 

    public Message(String message, String label, String correlationId, int transactionFlag);

 

    public Message(String message, String label, String correlationId, int transactionFlag, int status) ;

}

How does it work?

Building a Java app that uses this JNI interface to MSMQ works like building any other Java application. Some caveats though: The Queue class depends on a set of native functions defined in a DLL. So won't work with a Java applet, since you need the DLL to be installed on the local machine. You need the directory for the DLL to be on your search path (either in the current working directory, or on the PATH environment variable. Also, It works only on Windows, but that shouldn't be much of a concern since we are talking about MSMQ here.

It should work with public or private MSMQ queues, although I tested it only with private queues. It should work with any sort of data, but the class I provide sends or receives only strings.

It's Not JMS

To head off any questions: As you can see above, this is not a JMS provider for MSMQ. It doesn't do transactions, it doesn't do pub/sub or the data-munging that JMS does that I commented on earlier. This is just a simple class that lets you access MSMQ from Java.

It's Limited

You can't do everything with this simple JNI library that you can do with the System.Messaging class library, or with the C api for MSMQ. You cannot enumerate queues, or interrogate properties of queues or messages. The send() and receive() methods work only with Strings. It's pretty basic.

Wait.... Really? only strings? This is a joke!

The strings that your apps exchange via MSMQ can be anything: plain old strings, XML documents, base64 encoded byte arrays of arbitrary binary data, encrypted blobs, digital signatures, or whatever you like. You could take the base Queue class and extend it to provide support for these more advanced scenarios. For example, you could integrate this class with a Java-to-XML data binding framework like Apache's XMLBeans or Sun's JAXB, in order to be able to ship XML documents across the queue in an interoperable fashion.

There is undoubtedly overhead associated to encoding all data as strings. But this is just a demo, an illustration. If you need something optimized for binary data, it shouldn't be hard for you to produce a send() method that handles it nicely.

Not a substitute for MQSeries.

All you MQ loyalists, don't get your knickers in a twist. I am not suggesting that the arrival of this JNI library for MSMQ means that MQSeries, or any other message queue system, is now irrelevant. All this example does is show one more way to interconnect Java-based and .NET apps, VB6 apps, or any other MSMQ-enabled system. MQ still works, too, but MSMQ may be a bit more "available" for typical developers, since it is included in Windows.

Get the original source
Get the latest source

[Update:  As of February 2008, The JNI library for MSMQ has been promoted to a CodePlex project.   Find it at www.codeplex.com/MsmqJava ]

Enjoy. -Dino