IBM Developer

Tutorial

Get started with request-response messaging apps

Build and run sample JMS applications using the request-response pattern

By Simone Jain

With request-response messaging, your applications can exchange messages asynchronously, which means that they can function independently and become more robust. By adding features such as message expiry and application timeout, you can also minimize the effect of downstream application failures.

In this tutorial, you'll configure and run sample JMS request and response applications, highlight the expected behavior, and see how they implement the best practices outlined in the other articles in this series.

Prerequisites

You must have the following software installed on your machine:

In this tutorial, you'll use samples from the mq-dev-patterns repository.

Steps

Step 1. Get the JMS applications

In this tutorial, you'll use the JmsRequest.java and JmsResponse.java applications in the mq-dev-patterns repository.

First, clone the repo using this command:

git clone https://github.com/ibm-messaging/mq-dev-patterns

Then, navigate to the JMS directory and follow the steps in the README to build the sample applications. If you already cloned this repository, make sure that your local copy is up to date by running git pull.

Step 2. Set up your queue manager

The requester and responder applications will be putting and getting messages to and from queues, so we need to set up a queue manager for them to connect to.

Follow the instructions found in this tutorial to set up a queue manager in a container.

Step 3. Configure env.json

After you set up your queue manager, provide its connection details to the applications through the env.json file. Navigate to the env.json file in the mq-dev-patterns directory and replace its contents with the following:

{
  "MQ_ENDPOINTS": [{
    "HOST": "localhost",
    "PORT": "1414",
    "CHANNEL": "DEV.APP.SVRCONN",
    "QMGR": "QM1",
    "APP_USER": "app",
    "APP_PASSWORD": "passw0rd",
    "QUEUE_NAME": "DEV.QUEUE.1",
    "BACKOUT_QUEUE": "DEV.QUEUE.2",
    "MODEL_QUEUE_NAME": "DEV.APP.MODEL.QUEUE",
    "RESPONDER_INACTIVITY_TIMEOUT": "600",
    "REQUEST_MESSAGE_EXPIRY": "600"
  }]
}

Other than the connection information for our queue manager, there are a few extra details to note:

  • APP_USER and APP_PASSWORD are set to the values that you used when you followed the tutorial from the previous step to set up the queue manager. If you changed those values, use the same values here.
  • RESPONDER_INACTIVITY_TIMEOUT specifies how long the responding application waits for a request before it times out and ends. In this example, the value is 10 minutes.
  • REQUEST_MESSAGE_EXPIRY specifies how long the message remains available before the queue manager deletes it if no application picks it up from the destination queue. In this example, the value is 10 minutes.
  • MODEL_QUEUE_NAME specifies the queue that the application uses as a template for the temporary reply-to queue, which it creates dynamically. Depending on your use case, you might want to use REPLY_QUEUE_NAME to define a static queue to receive replies, although using temporary dynamic queues is a best practice.
  • Because the request-response interaction happens in a transaction and uses JMS, BACKOUT_QUEUE specifies the queue where poison messages are backed out. For more information, see "An introduction to local transactions".

Step 4. Create the model queue

The easiest way to create the model queue is through the MQ Console. You can follow the instructions in this tutorial to set up and use the MQ Console.

Follow these steps to create the model queue:

From Manage > Queues, click the Create button.

MQ Console interface showing Manage Queues page with Create button highlighted

Select Model.

MQ Console queue type selection dialog with Model option displayed

Set the queue name to DEV.APP.MODEL.QUEUE, and then click Create. Note that you must prefix the queue with DEV. because the default developer security permissions allow the app user to access only queues with this prefix.

MQ Console create model queue form with DEV.APP.MODEL.QUEUE name entered

Your model queue is created and appears in the queue manager table.

MQ Console queue manager table displaying newly created DEV.APP.MODEL.QUEUE

Step 5. Run the Request app

The requesting application that you'll use is JmsRequest.java. In a separate terminal, navigate to the JMS directory and run the application by using one of the following commands.

If you used Maven to build the samples, run:

java -cp target/mq-dev-patterns-0.1.0.jar com.ibm.mq.samples.jms.JmsRequest

Otherwise, compile the app:

javac -cp ./com.ibm.mq.allclient-9.2.5.0.jar:./javax.jms-api-2.0.1.jar:./json-20230227.jar:. com/ibm/mq/samples/jms/JmsRequest.java

Then, run the app:

java -cp ./com.ibm.mq.allclient-9.2.5.0.jar:./javax.jms-api-2.0.1.jar:./json-20230227.jar:. com.ibm.mq.samples.jms.JmsRequest

After you run this application, output similar to the following is displayed in the terminal:

Terminal output showing JmsRequest application sending request and creating temporary reply queue

This output indicates that the application sent the request and created a temporary queue to receive the response. The application selects the response based on the specified JMSCorrelationID.

Take a look in the MQ Console:

MQ Console showing request message on DEV.QUEUE.1 and temporary reply queue created

You can see that the request message was put to DEV.QUEUE.1, and a temporary reply-to queue was created (AMQ.661D2A4C21A4DE01 in this example).

Step 6. Run the response app

The responding application that you'll use is JmsResponse.java. Navigate to the JMS directory and run the application by using 1 of the following commands.

If you used Maven to build the samples, run:

java -cp target/mq-dev-patterns-0.1.0.jar com.ibm.mq.samples.jms.JmsResponse

Otherwise, compile the app:

javac -cp ./com.ibm.mq.allclient-9.2.5.0.jar:./javax.jms-api-2.0.1.jar:./json-20230227.jar:. com/ibm/mq/samples/jms/JmsResponse.java

Then, run the app:

java -cp ./com.ibm.mq.allclient-9.2.5.0.jar:./javax.jms-api-2.0.1.jar:./json-20230227.jar:. com.ibm.mq.samples.jms.JmsResponse

After you run this application, the request application displays the following output and exits:

Terminal output showing JmsRequest application receiving response and exiting successfully

Take a look in the MQ Console again:

MQ Console showing DEV.QUEUE.1 empty after request consumed and temporary queue deleted

You can see that the request was consumed from DEV.QUEUE.1. The responder put the response message on the temporary queue, and the requester then consumed it and disconnected. Because of this sequence, the queue manager deleted the temporary queue.

Expiry and Timeout

The scenario above is an ideal one, so you did not observe message expiry or application timeout. You can recreate these scenarios, but before you do, edit your env.json file so that the wait time is 1 minute instead of 10 minutes.

{
  "MQ_ENDPOINTS": [{
    "HOST": "localhost",
    "PORT": "1414",
    "CHANNEL": "DEV.APP.SVRCONN",
    "QMGR": "QM1",
    "APP_USER": "app",
    "APP_PASSWORD": "passw0rd",
    "QUEUE_NAME": "DEV.QUEUE.1",
    "BACKOUT_QUEUE": "DEV.QUEUE.2",
    "MODEL_QUEUE_NAME": "DEV.APP.MODEL.QUEUE",
    "RESPONDER_INACTIVITY_TIMEOUT": "60",
    "REQUEST_MESSAGE_EXPIRY": "60"
  }]
}

Next, you need to recreate a scenario where the request message expires.

First, stop both the requesting and responding applications.

Then, run just the requesting application.

As before, the request is put on DEV.QUEUE.1, and the application creates a temporary queue.

MQ Console displaying request message on DEV.QUEUE.1 with temporary queue awaiting response

If you do not run JmsResponse.java, you see that the message is deleted from the queue after the time specified in REQUEST_MESSAGE_EXPIRY elapses and the application ends. In this example, the message expires after 1 minute.

MQ Console showing DEV.QUEUE.1 empty after request message expired and was deleted

To recreate a timeout scenario, first stop both the requesting and responding applications.

Then, run just the responding application.

If no request is available for the responder to process before the time specified in RESPONDER_INACTIVITY_TIMEOUT elapses, the responding application times out and ends. In this example, the timeout occurs after 1 minute:

Terminal output showing JmsResponse application timing out after inactivity period

Summary and next steps

In this tutorial, you set up and ran sample requesting and responding applications. You also reviewed the key features that applications need for a request-response exchange and when those features are useful.

To explore more messaging patterns and earn a digital credential, see the IBM MQ Developer Essentials learning path.