I have a weird problem with Websphere MQ and JMS. There is a PL1 application that puts messages into a queue which are read by my java application (running in tomcat). The problem is that as soon as the PL1 application puts a message in the queue, the java application can't read anything from that queue anymore - as if there weren't any messages in the queue. The MQ Browser on the other hand shows that the messages are indeed there. The queue administrator also tells me that he can't see any errors on the queue by the time I try to fetch the messages.
I've tried to read the messages from the java tomcat application with a listener and also with a custom class reading the messages via the JMS QueueBrowser. Neither way works. For the QueueBrowser for example I even don't get an exception while calling the QueueBrowser.getEnumeration Method.
The funny thing is when the queue is emptied again and a local java test application (and not the PL1 application) puts messages in the queue they can be read by the java tomcat application. As soon as the PL1 application adds a message again all the messages aren't visable anymore for the java tomat application => even those that have been added by the local java test application and worked before.
One important thing to say: The PL1 application is setting message properties on the message handle via MQSETMP:
Use the MQSETMP call to set or modify a property of a message handle.
Syntax
MQSETMP (Hconn, Hmsg, SetPropOpts, Name, PropDesc, Type, ValueLength, Value, Compcode, Reason)
https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_8.0.0/com.ibm.mq.ref.dev.doc/q101910_.htm).
I suppose that that's somehow the reasons for the issues. If the setting "PROPCTL" of the queue is set to "NONE" (instead of "COMPAT") the java application can read the messages from PL1 but the message properties aren't visible. We want to use those message properties though that's why this is not an option for us. We also tried the other possible options for PROPCTL which also didn't work.
Is there anything I can do maybe from the java client side? Are there any possible settings for Websphere MQ classes for java that I can try out?
Websphere MQ-Version: 8
Websphere MQ classes for java version (com.ibm.mq.allclient): 9.0.4.0
Edit
This is a minimal example of the java client fetching the messages via QueueBrowser:
package jmsminimal;
import java.util.Date;
import java.util.Enumeration;
import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Queue;
import javax.jms.QueueBrowser;
import javax.jms.Session;
import javax.jms.TextMessage;
import com.ibm.mq.jms.JMSC;
import com.ibm.mq.jms.MQQueueConnectionFactory;
public class JMSTest {
public static void main(String[] args) throws JMSException {
String hostname = "hostname";
String channel = "channelname";
int port = 1414;
String queueMgr = "queuemgrname";
String queueName = "queuename";
String username = "username";
String password = "";
MQQueueConnectionFactory mqQueueConnectionFactory = new MQQueueConnectionFactory();
mqQueueConnectionFactory.setHostName(hostname);
mqQueueConnectionFactory.setChannel(channel);
mqQueueConnectionFactory.setPort(port);
mqQueueConnectionFactory.setQueueManager(queueMgr);
mqQueueConnectionFactory.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP);
Connection connection = mqQueueConnectionFactory.createConnection(username, password);
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(queueName);
QueueBrowser browser = session.createBrowser(queue);
connection.start();
Enumeration entriesEnum = browser.getEnumeration();
while (entriesEnum.hasMoreElements()) {
Message message = (Message) entriesEnum.nextElement();
TextMessage textMessage = (TextMessage) message;
System.out.println("*********************************************************");
System.out.println("JMSMessageID: " + textMessage.getJMSMessageID());
System.out.println("JMSCorrelationID: " + textMessage.getJMSCorrelationID());
System.out.println("JMSTimestamp: " + new Date(textMessage.getJMSTimestamp()).toString());
System.out.println("\nProperties:");
Enumeration propertiesEnum = textMessage.getPropertyNames();
while (propertiesEnum.hasMoreElements()) {
String propertyKey = (String) propertiesEnum.nextElement();
String propertyValue = textMessage.getObjectProperty(propertyKey).toString();
System.out.println(propertyKey + "=" + propertyValue);
}
System.out.println("\nText: \n" + textMessage.getText());
System.out.println("*********************************************************\n");
}
connection.close();
session.close();
}
}
Here the pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.jms</groupId>
<artifactId>jmsminimal</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>com.ibm.mq</groupId>
<artifactId>com.ibm.mq.allclient</artifactId>
<version>9.0.4.0</version>
</dependency>
</dependencies>
</project>
As said earlier - this example works only when there are no messages in the queue which are sent by PL1 and contain message properties in the MQHRF2 format. Otherwise the enumeration is empty.
/opt/mqm/samp/bin/amqsbcg SYSTEM.DEFAULT.LOCAL.QUEUE TESTQM 1
(the1
at the end tells it to format and print the properties). To generate a message with properties use the sampleamqsstm SYSTEM.DEFAULT.LOCAL.QUEUE TESTQM
, this uses the CMQSETMP
function. It will ask for name value pairs for the properties once done press enter for blank property and it will ask for a message text. This lets you know if it is a java specific problem. – JoshMc