Every time I work with MQ and Spring JMS I want to poke my eyes out with a dull instrument. It’s always a pain in the neck. My most recent challenge was trying to get the JMSXUserID field to flow through to the application on the other side of MQ.

public class MyMessagePostProcessor implements MessagePostProcessor
{
private String userId;

@Override
public Message postProcessMessage(Message msg) throws JMSException
{
msg.setStringProperty(JmsConstants.JMS_IBM_MQMD_USERIDENTIFIER, userId);
msg.setStringProperty("JMSXUserID", userId);
return msg;
}
}


But when I checked the queue with HermesJMS I could see that the JMSXUserID had been overwritten somewhere, so I fired up WireShark and watched for the message and confirmed that the message that was going over the wire already had the JMSXUserID field overwritten. This was a good thing - the issue was in the IBM MQ JMS client code.

Everywhere I looked online told me that the JMSXUserID field is set by the JMS provider in the ‘send’ method, and that there was little or no possibility of controlling it. Then I found this reference on the IBM site that said:

You must set the Destination object property WMQ_MQMD_WRITE_ENABLED to true for the setting of MQMD properties to have any effect

It is necessary to set WMQ_MQMD_MESSAGE_CONTEXT before setting JMS_IBM_MQMD_UserIdentifier.

However, these are properties of the Destination, to which I did not currently have access because I was using Spring’s JmsTemplate + DynamicDestinationResolver to send the message. So I extended Spring’s DynamicDestinationResolver, set the two fields I needed to and Voila! The JMSXUserID passed through.

public class MqDestinationResolver extends DynamicDestinationResolver
{
@Override
public Destination resolveDestinationName(Session session, String destinationName, boolean pubSubDomain) throws JMSException
{
MQDestination mqDest = (MQDestination)super.resolveDestinationName(session,
destinationName, pubSubDomain);
mqDest.setBooleanProperty(WMQConstants.WMQ_MQMD_WRITE_ENABLED, true);
mqDest.setIntProperty(WMQConstants.WMQ_MQMD_MESSAGE_CONTEXT,
WMQConstants.WMQ_MDCTX_SET_IDENTITY_CONTEXT);
return dest;
}
}


I hope this helps.