on Java-to-.NET interop via JMS and MQSeries

While looking around I found two articles, from SYS-CON's WebSphere Developer's Journal, covering J2EE and .NET interop via MQSeries.

part 1: https://sys-con.com/story/?storyid=43430&DE=1#RES

part 2: https://sys-con.com/story/?storyid=43452&DE=1#RES

These articles reference ma7p, the IBM supportpac, which is no longer available. ma7p has graduated into the MQSeries product. Upgrade to MQ V5.3 + CSD05 or later to get the MQ classes for .NET.

Interesting: the 2nd article documents a problem I ran into while trying to connect a Java/MQ application that uses the JMS api, with a .NET application that uses the MQ Classes for .NET. The JMS implementation essentially extracts function from the underlying MQ and embeds it into the API level. So, things like MessageId and CorrelationId, which are indispensable for a typical MQ app, are not transferrable between a JMS/Java app and a .NET app. JMS commandeers those MQ-isms and does not bubble them up into the application layer. In some cases there is a similarly named JMS thing, but it is not the same thing as the underlying MQ thing. In fact I could not find a way to set the MQ Message ID - the JMS doc I found said that the JMSMessageID on an outgoing JMS message will always be set by the JMS layer - the application is not able to set it. (not quite true, you can set it all you want, but as soon as you send the message, your MQ MessageId is over-written with a JMS-provided value). 

The net result was that I found myself reverse-engineering the JMS implementation of message-munging. At first it looked like it was just one or two methods, but the JMS-isms just kept coming and coming. The correlation ID needed to have a specific prefix. Strings had to conform to a JMS-specific encoding. If you try to encode a simple buffer with a couple of integers and a string, you get a big hairy XML envelope (with no namespaces! The dreaded RFH2 envelope) - the JMS message envelope. Which may be just what you DON'T want in a high-throughput messaging app. The JMS pitfalls and traps seemed to just keep going and going. Eventually I just punted and switched the Java app to use the "MQ Classes for Java", a package which defines, like the "MQ Classes for .NET", an IBM-only programming interface. When I use the MQ Classes for Java, I don't get the surprises I mentioned above.

Stop and think for a minute; This is a completely ridiculous situation. Imagine if you inserted rows into an Oracle database with a JDBC app, and then you could only read those rows with another JDBC app. Imagine if your LDAP repository, once you accessed it with JNDI, became a resource that could only be accessed by Java apps. Preposterous, right? Well that's what JMS does. You have to go to the high-fidelity MQ Classes for Java if you want to have a reasonable effort connecting Java to .NET apps. 

"Non-standard interface!" you point out. "Lock-in!" Yeah, you're right. But Interop trumps Neutrality. [Disclaimer, I never believed the "vendor neutrality" arguments anyway] The designers of JMS - either the IBM implementation of it, or the specification itself - have made decisions about message formats that specifically preclude any interop between a JMS (Java) app and a non-JMS app, without lots and lots of extra effort by the non-JMS side. The message formats are not published, so you either have to reverse-engineer them, and risk violating the JMS specification license, or ... you have to license and implement JMS. In either case, Vaya con dios, the future holds lots of work and lots of lawyers for you. Going with JMS, you may not get "Lock in" to a particular vendor of message middleware, but you do get "Lock out" - of anything non-Java.   

So I have some questions for you all:

  1. do you do interop between Java and .NET over MQ ? If so, do you use JMS? How do you resolve the issues I mentioned?
  2. anyone have any helper classes in C# or VB that unpacks the JMS envelope?
  3. what did you do about JMSMessageID?