Java and .NET interop via MSMQ

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 ]

Enjoy. -Dino

Comments (34)

  1. Chris Bilson says:

    Another option is to use the HTTP handler MSMQ has. If you use a packet filter, you can see that the messages an MSMQ client sends to an MSMQ server over http are just soap messages with attachments for the body of the MSMQ message. I have considered doing this before for clients that I did not want to have to install the the MSMQ client stuff on, but still wanted to be able to send messages to a queue on a server.

  2. Brad says:


    This looks great — exactly what I needed! Would you mind posting the JNIMSMQ.dll?


  3. Dino says:

    ok, Brad, I updated the zip referenced in the post; it now includes the JNIMSMQ.dll. Having said that, remember that anyone should be able to build it themselves using the VC++ toolkit (free, if you use Windows) and the .NET SDK (also free).

  4. Dino says:

    Hey Chris, yes, I had seen Doron mention that, but he indicated there would be some additional protocol handling required, I think?

  5. Jeff T. says:

    The JNI approach would still only work for a java application running on a Windows platform, right? I am looking for a way to access a Windows MSMQ server from a linux client. It seems that there is no "ideal" way of accomplishing this. If MS would release a linux (or java) client, it would increase the popularity of MSMQ, IMHO.

    That said, does anyone know how this can currently be done?


  6. Dave says:

    Thanks for the great implementation. This works pretty cool if my message queue is on the same machine that I’m running the sample clients from. But I can’t get the Java version to work if the message queue is on another machine. I edited both the C# and the Java versions of "getQueueFullName" so they specify a remote queue name:

    return "FormatName:DIRECT=OS:remoteMachineName\private$\" + queueShortName;

    And the C# version still works, but the Java version always returns

    Queue open failure: Cannot open queue. (hr=MQ_ERROR_REMOTE_MACHINE_NOT_AVAILABLE)

    Am I doing something wrong? Or is this a limitation of the JNI implementation?

    Thanks in advance!


  7. cheeso says:

    > The JNI approach would still only work for a java application running on a Windows platform, right?

    Yes, the JNI approach used here involves Java code calling into a Windows-specific DLL. JNI is, in general, platform specific. You can do JNI on Linux, but you will lack the MSMQ DLL on Linux, so that won’t get you what you want.

  8. cheeso says:


    > Am I doing something wrong? Or is this a limitation of the JNI implementation?

    Yes, you are doing something wrong! Use the FormatName: prefix in the C# client, but not in the Java client.

    Also, for Java to work, you’ll have to apply the DIRECT=OS: prefix, in either the client code, or in the native layer, in the MsmqQueue.cpp module. But not in both ! To keep it parallel to the C# client, that prefix should be applied in the (and thus removed from the MsmqQueue.cpp module).

  9. cheeso says:

    I updated the example to support remote private queues. If you click the download link, you’ll get the update.


  10. azri says:

    I was checking the source code, and it would seem that the file JniMsmq.h is missing from the .zip file.

    Will/can it be fixed ?


  11. cheeso says:

    Azri, JniMsmq.h is a generated file, so it was not included in the zip.

    You can build JniMsmq.h with the makefile.

  12. Bjoernar says:

    The idea to use MSMQ and XML to have Java speak with Windows apps is a super idea, just what I was looking for. I have a small problem though, there seems to be a problem with character encodings. I’ve made some javascripts(WSH) that sends/receives text to a queue, but the Testclient and the javascripts don’t understand eachother. The text "ABC" looks like 41 00 42 00 43 00 from the javascript side and 41 42 43 from the java side. I suppose the double byte characters are some kind of Unicode (UTF-16LE??) While the 1 byte characters are ISO-8859-1 (Windows maybe??). What can be done to fix this?. Can the Strings be furnished at the Java layer to fix this or has the dll to be modified?

  13. In my original post on Java interop with MSMQ, I gave a sample implementation of a Queue class for…

  14. In my original post on Java interop with MSMQ, I gave a sample implementation of a Queue class for…

  15. In my original post on Java interop with MSMQ, I gave a sample implementation of a Queue class for…

  16. JavaOne2006 – Interop Session I went to a few sessions at JavaOne 2006. One was called Best Practices

  17. In my original post on Java interop with MSMQ , I gave a sample implementation of a Queue class for Java

  18. Jorge says:

    I want to read messages when they has been arrived to the queue.

    How can i set or fire a event which reads messages when they just arrived to the queue?


  19. cheeso says:

    There are a couple of ways to do what you want in MQ.  One is to poll the queue endlessly.  Another way is to use something called a "trigger monitor" in MQ.  This is a program that runs constantly, and upon arrival of a message on the desinated queue, the trigger monitor can start an application and send to that application relevant information from the queue message.

    The application itself can start up and dequeue from the queue, or do whatever it wants.

    You can read more about polling and the MQ Trigger Monitor Interface (TMI) in the MQ docs.

  20. Jorge says:

    hi, thanks for answer

    Sorry,  MQ is Message Queue?

    in the first option “One is to poll the queue endlessly” you’re talking about make a infinite loop or set a timer and check the queue?, what if there are two apps. reading the same queue, one in vb which has the notifyenabled to read the a message when it is arrived to that queue, and another one in java which have the loop what will happen if the the message is read by the vb app. first, the java app. never realize whether that message were arrived to the queue right?.

    In the second option, the app (in java), needs to know automatically when a message was arrived, so if i will create a trigger on the queue, what useful could be running another application which will has to connect to java too?

    so there’s no way to just add a ActionListener or something to catch the arriving of a message, like we can do it in vb?

    hope understand


  21. cheeso says:

    Wow, for some reason I understood you were asking about IBM MQSeries.  That’s what I meant when I wrote “MQ”.  So my prior answer is not what you wanted, I think.

    There are triggers as well in MSMQ.  MSMQ Triggers allows you to configure an app (.exe) to start when a message arrives on a message queue.  

    See here for an article:

    It may be that you don’t want to start an exe.  Maybe you want to just notify a thread inside your own Java applications.  Yes, this is also possible.

    To do it, though, you need to write your Java application to have multiple threads.   The first thread (T1) kicks off Thread #2  (T2).  T1 then calls wait() on a monitor object.  While T1 waits, T2 calls the Queue.receive() method specifying as a timeout some large number.  When the Queue.receive() returns, T2 can check to see if the timeout expired, or if the queue was actually successfully read.  In the latter case, T2 calls notify() on the monitor.  This awakens T1.  

    You may need to read up on Java threads ….  

  22. If you are facing  problems related crashing of dll.

    you can also use this dll.

  23. Dave says:

    Anyone used this method with multiple queues?

    I tried connecting to two queues.  Sending data to any of the two results in messages arriving at the second queue only even though the two queue instances show correct (differing) instance details when stepping the code.


  24. cheeso says:

    Dave, can you show me your application code?  There is a private member variable that holds the queue handle for each instance of the MsmqQueue class that you create.  Is it possible that somehow the instances are getting munged?

  25. Dave says:

    Thanks for responding.

    I’ve since changed my app to work around the problem (opening the queues as and when required) so the original code is not available but basically what it comes down to is something like:



    Queue qA, qB

    qA = new Queue("DIRECT=TCP:$qa",0x02);

    qB = new Queue("DIRECT=TCP:$qb",0x02);

    Message msgA = new Message("<Msg><Data>dataA</Data></Msg>","NoLabel",0,0);

    Message msgB = new Message("<Msg><Data>dataB</Data></Msg>","NoLabel",0,0);





    both messages end up in qB.  Stepping through the code at the two .send lines shows the queues with the correct labels etc.  Very strange.

    I was pressed for time and did not spend a lot of time on this so the sample above is my understanding of how the problem can be recreated.  Will try and test it myself later.

    Just ran into a more serious problem this morning though and hope you can shed some light please?  The app runs fine on my development machine.  Deployed to a production Windows Server 2003 box and now the messages no longer appear on the queue(s).  No exceptions are thrown when opening or sending but the messages simply vanish.  Other (.NET) apps are writing to queues on the same box with no problem.

    Your help is appreciated.

  26. Dave says:

    Managed to get it sending messages by changing the queue label from using "DIRECT:TCP…." to "DIRECT:OS…."

  27. Vaibhav says:


    has anyone enhanced MSMQ java code to support Transactional MSMQ Queue’s?

    I am not able to compile the dll.

  28. amit says:

    The code for JAVA MSMQ which working fine for me.

  29. archenroot says:

    Did anyone find working solution also for working with MSMQ server from app running on linux machine? I just installed Open ESB. One can download additional MSMQ binding component for JNI, but again only windows OS are supported for this time.

    Thanx for any related info.

  30. Alastors says:

    If anyone wants the 64 bits version of this I made visual studio 2010 projects for 32 and 64 bits with compiled dll included and submitted them to the codeplex issue tracker, the direct link is…/12272

  31. GuoXY says:

    thank you very very big much for Alastors!!!!!!!!!!!!!!!!!!