Published on

Working with IBM MQ Spring and Docker

Authors

In the past, I had to integrate a non-Spring Java application with IBM MQ queues. This at the time proved to be a pain as I needed a bunch of proprietary binaries (i.e. not available on Maven Central) and several JARs were needed but the version numbers between the different JARs ended up having to be completely different - resulting in a juggling act to get the right combination.

Fast forward a few years and in a Spring and docker environment it ended up being easy and simple to integrate a Spring app with IBM MQ queues. It involved:

  • Simply adding the correct Spring starter in Gradle/Maven
// ...
dependencies {
// ...
    implementation ("com.ibm.mq:mq-jms-spring-boot-starter:2.0.0")
// ...
}
  • Configure your application.properties with certain properties that IBM MQ expects:
ibm.mq.queueManager=MQ73
ibm.mq.channel=YOUR.CHANNEL.NAME
# your ip here. Default port is 1414 and is expected in brackets as below
ibm.mq.connName=1.2.3.4(1414)
ibm.mq.user=admin
ibm.mq.password=passw0rd
  • Set up your listeners on top of methods in services/components using the Spring @JmsListener annotation:
@Component
class MyServiceThatHandlesQueueMessages {

// ...
    @JmsListener(destination = "\${..boud.queue}")
    fun receiveMessage(message: Message) {
        // check if it is a text message
        if (message !is TextMessage) {
            logger.error("received unsupported message type")
            logger.debug("END :: receiveMessage")
            return
        }

        // is a textMessage so get the message and work with it
        val textMessage =  message.text
        // Note: if an exception is thrown the message will not be de-queued. Catch and handle the exception if you want it to dequeue


        // ... do what you need to with it now
    }

// ...
}
  • Setup senders (if needed) by simply wiring in a JmsTemplate where needed:
@Component
class SomeClassThatSendsMessagesToTheQueue {

// ...
    @Autowired
    private lateinit var jmsTemplate: JmsTemplate
// ...
    fun doSomethingThatNeedsAQueueMessageToBeSent() {
    // ... the queue is a string which is the name of the queue
    // the message is a string which you are putting on to the queue
    jmsTemplate.convertAndSend(queue, message)
    // ...
    }
// ...
}

Running the infrastructure for IBM MQ locally is straight forward as described in this tutorial. To make life easier I converted these various docker steps into the below docker-compose file:

version: "3.7"

services:
  activetmq:
    image: ibmcom/mq
    networks:
      - mq-demo-network
    volumes:
      - "qm1data:/mnt/mqm"
    ports:
      - "1414:1414"
      - "9443:9443"
    environment:
      - LICENSE=accept
      - MQ_QMGR_NAME=QM1

volumes:
  qm1data:

networks:
  mq-demo-network:

The official tutorials from IBM covering this are: