Tutorial
Get started with request-response messaging apps
Build and run sample JMS applications using the request-response patternWith 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:
- Git
- Java
- Maven
- The latest version of the IBM MQ allclient
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_USERandAPP_PASSWORDare 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_TIMEOUTspecifies 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_EXPIRYspecifies 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_NAMEspecifies 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 useREPLY_QUEUE_NAMEto 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_QUEUEspecifies 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.

Select Model.

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.

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

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:

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:

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:

Take a look in the MQ Console again:

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.

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.

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:

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.