I am trying to publish messages on a IBM MQ Queue. Here is a my implementation -
@Bean("jmsTemplate")
public JmsTemplate createProducer(@Qualifier("jmsConnectionFactory") ConnectionFactory cf) {
JmsTemplate jmsTemplate = new JmsTemplate(cf);
jmsTemplate.setDefaultDestinationName("my-queue-name");
return jmsTemplate;
}
and then I am calling it in a scheduler to produce message every second -
@Autowired @Qualifier("jmsTemplate") JmsTemplate jmsTemplate;
@Scheduled(fixedDelayString = "1000")
public void runOnStart() {
String message = "sample message "+String.valueOf(System.currentTimeMillis());
jmsTemplate.convertAndSend(message);
LOGGER.info(message);
}
All works good. Then I shut off the internet and this piece of code started throwing error - saying queue connection not available. I connected my system back to internet and it started sending the messages again. Cool! It worked as I wanted.
I tried to repeat the same experiment using JMS2.0 with javaContext implementation. Here is my second implementation -
@Bean("jmsContext")
public JMSContext createProducer(@Qualifier("jmsConnectionFactory") ConnectionFactory cf) {
return cf.createContext();
}
@Bean("jmsProducer")
public JMSProducer createProducer(@Qualifier("jmsContext") JMSContext jmsContext) {
return jmsContext.createProducer();
}
Again, similar to last approach, I created a scheduler to publish messages like this -
@Autowired @Qualifier("jmsContext") JMSContext jmsContext;
@Autowired @Qualifier("jmsProducer") JMSProducer jmsProducer;
@Scheduled(fixedDelayString = "1000")
public void runOnStart() {
try {
Destination destination = this.jmsContext.createQueue("my-queue-name"));
String message = "sample message "+String.valueOf(System.currentTimeMillis());
this.jmsProducer.send(destination, message);
} catch (JMSException e) {
LOGGER.error("Error in sending message", e.getLinkedException());
}
}
Here also, I am able to send the messages. Very well till now. My issue comes in the following part. The scheduler was running, I disconnected my system from internet and the code throws error saying there is no connection. I reconnected my system back, but still my messages were not going to the broker(unlike the previous implementation). Isn't it supposed to connect back and send messages?
What have I missed in my 2nd implementation?
Note that: the Bean @Qualifier("jmsConnectionFactory") ConnectionFactory cf
is same for both implementation and it is like -
public static ConnectionFactory getMQConnectionFactory (
Map<String, String> queueDetails,
SSLContext sslContext) throws Exception {
MQConnectionFactory cf = new MQConnectionFactory();
cf.setHostName(queueDetails.get("hostname"));
cf.setPort(Integer.parseInt(queueDetails.get("port")));
cf.setQueueManager(queueDetails.get("queueManager"));
cf.setChannel(queueDetails.get("channel"));
cf.setTransportType(WMQConstants.WMQ_CM_CLIENT);
cf.setStringProperty(WMQConstants.USERID, queueDetails.get("username"));
cf.setSSLCipherSuite(queueDetails.get("sslCipherSuite"));
cf.setSSLSocketFactory(sslContext.getSocketFactory());
return cf;
}
The exception -
com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2009' ('MQRC_CONNECTION_BROKEN').
If you want the underlying MQ client code to reconnect on failure you will need to enable mq auto reconnect like this:
cf.setClientReconnectOptions(WMQConstants.WMQ_CLIENT_RECONNECT);
cf.setClientReconnectTimeout(1800); // how long in seconds to continue to attempt reconnection before failing