Tutorial
Building cloud-native reactive Java messaging applications
Use Quarkus, Smallrye, and IBM MQ to build a minimal footprint reactive applicationWhen we develop applications for a cloud-native environment, our apps must exhibit some important characteristics. When we're paying for the resources we use, we want our applications to run as efficiently as possible, to be lightweight, with short start-up times. As a cloud-native developer, we need to make sure we're using the right tools for the job.
When we deploy applications to be run in the cloud, a common practice is to put them in custom containers and deploy them in Kubernetes by using a pipeline tool for continuous integration. In this environment, we need to make sure that our technology stack only contains what is needed to run our applications. Rather than shipping an entire JVM, when we run Java applications in the Cloud we can use the GraalVM JDK to build an optimised native binary that doesn't need a JVM to run.

You can use Quarkus with the cloud-native virtual machine technology called GraalVM, which is designed to create highly optimized images with just the runtime stack you need for your application. If you use GraalVM to build binaries from your Java apps, you don't need to package them into .jar files and run them in a container with a JVM installed.
Instead, GraalVM lets you ship your application combined with only the small fraction of the Java stack that your application uses, as an optimized, super-lightweight binary executable with a tiny footprint and lightning-fast start-up times.
Quarkus contains a reactive framework (Smallrye) which lets you create reactive applications. Reactive applications, as outlined in The Reactive Manifesto are responsive, resilient, elastic, and message-driven. Message-driven is where IBM MQ comes in by providing asynchronous, non-blocking communication between applications. By using Quarkus, developers can write reactive, cloud-native Java applications that satisfy these properties and that are easy to deploy and manage.
Building reactive Java apps with Quarkus and IBM MQ
If you want a tutorial that shows you how to create a Quarkus messaging app using the AMQP JMS QPid classes with IBM MQ, see this IBM Developer tutorial.
IBM MQ applications that use Quarkus communicate with MQ queue managers through AMQP, an open-source messaging protocol. The Quarkus application relies on two key open-source technologies to achieve reactive messaging – the Smallrye reactive messaging framework and the vert.x AMQP client, a reactive Java toolkit for AMQP messaging that Smallrye relies on. The Quarkus application can be run on a regular JVM or you can package the Quarkus application using a GraalVM JDK into a native-image executable that you can easily deploy as part of a cloud solution.
This figure should help you understand how the technology stack fits together inside your application:

Sample reactive messaging app
In this tutorial, we will run sample code that simulates a REST call to part of a reactive microservice architecture, where two applications will communicate using IBM MQ over AMQP. This sample application was adapted from this Quarkus.io sample for reactive messaging . The sample code has been adapted to work with MQ. The sample code can be found in this github repo .
The sample code we'll look at has two applications that communicate using the publish-subscribe messaging pattern with IBM MQ, working with a web page to generate random price quotes. It works as described in the following diagram:

The steps in this application are as follows (numbers in the previous figure):
- (0) When the system is run, the
amqp-quickstart-processorapplication subscribes to the topicquote-requestson the queue manager, using the publish-subscribe pattern. - (1) The user navigates to the site, which causes the
amqp-quickstart-producerapplication to subscribe to the topicquotes. - (2) The user clicks a Request Quote button.
- (3) This sends a POST request to the requesting application,
amqp-quickstart-producerand registers an event listener on the web page to receive the response. - (4) The producer requests a quote from the quote processing application,
amqp-quickstart-processor. It does this by sending a message to an MQ topic calledquote-requests. - (5) The quote processing application is subscribed to the
quote-requeststopic, so it gets sent the quote request. - (6) The quote processing application generates a quote and publishes it to the
quotestopic. - (7)
amqp-quickstart-produceris subscribed to thequotestopic, so it gets the quote message from theamqp-quickstart-processorapplication. - (8) The message is sent to the web page, which replaces the
pendingmessage with the actual quote.
It might sound a little over-engineered, but this system is the exact kind of architecture that's used by companies as they redesign their monolithic applications into microservices that run well in the cloud.
The files that are most interesting inside each application are QuotesResource.java, QuoteProcessor.java and the quotes.html files used in our demo. Important properties are also set in each application.properties file. The docker-compose.yml file is where the entire demo is defined and implemented when running the sample outside developer mode.
Prerequisites
- Java 11 or above
- Maven
- GraalVM, if you want to create an optimized native image
You can use sdkman to install each.
Steps
Step 1. Get the MQ image and enable AMQP
To get a queue manager set up with AMQP enabled, follow Step 1 in this IBM Developer tutorial on MQ and AMQP .
After you’ve done this step, in your terminal window, enter this command:
docker ps
You should see output like this, noting that there's a port mapping to port 5672, which is the port used by AMQP:

When you have the AMQP-enabled container, you're ready to get and use the sample applications.
Step 2. Get the sample code
First, navigate in your terminal to somewhere you want to download the code. Get the sample by entering these commands:
git clone https://github.com/ibm-messaging/mq_amqp_demo.git
cd mq_amqp_demo
By default, the application doesn't use username and password authentication and relies on a publish-subscribe messaging pattern. The application behavior can be easily modified in the application.properties for the producer and processor components, which we will talk about later.
Step 3. Run the sample in developer mode
Now you're ready to run the sample in developer mode, which will connect to your MQ container instance to do the messaging.
The application.properties file in each application is where the connection details for your application are specified. It's already been populated with default values for MQ running in a container. For example:
amqp-host=localhost
amqp-port=5672
To add basic authentication, the credentials of the app user can be set as follows:
amqp-username=app
amqp-password=passw0rd
Switching to queue-based point-to-point messaging
The AMQP Attach frame describes the address of the messaging resource, but it doesn’t describe its type, such as queue or topic.
By default, IBM MQ assumes the address is an AMQP topic. However, IBM MQ checks the capabilities field of the AMQP frame to determine the type of the AMQP address endpoint as is the convention used in the QPid client. For more information about IBM MQ ‘s AMQP support, see the IBM MQ documentation .
The capability can be set to topic, temporary queue, queue or shared, and for Quarkus 2.8.0.CR1 (or later), capabilities can be expressed as a property in the relevant application.properties file. To switch to queue-based messaging, these properties must be set for both the producer and processor application components.
Running the application in dev mode
Run these commands in two separate terminals:
mvn -f amqp-quickstart-processor quarkus:dev
mvn -f amqp-quickstart-producer quarkus:dev
You should see the message "AMQP Receiver listening address" in each terminal. For two side-by-side terminals, your output should look something like this:

In your browser, go to the address http://localhost:8080/quotes.html. You should see a web page with a button allowing you to request a quote.

When you click the Request Quote button, a request ID is generated and the message "pending" is displayed. This will shortly be replaced by a dollar amount for the quote as the amqp-quickstart-processor app generates a quote which is passed to the amqp-quickstart-producer app and it then the message (the quote) is updated on the page.
In developer mode, Quarkus lets you change lines of your application code without recompiling, which is a very useful feature.
Try this out by editing the QuoteProcessor.java file in the amqp-quickstart-processor application.

Line 28 contains the logic that generates the quote value for each quote request. The logic is pretty simple: return a random Int between 0 and 99. To raise the limit to 199, change line 28 to this:
return new Quote(quoteRequest, random.nextInt(200));
Refresh the http://localhost:8080/quotes.html page and you should be able to see that some your new quotes are for more that $99. (You'll get one request that stays pending, because the new subscription only happens when a user sends a POST request to the amqp-quickstart-producer application.)
Step 4. Run the sample in JVM mode in containers
Looks like everything is working in developer mode, but if we want to test that this code works outside developer mode, we need to build the applications with Maven.
Stop the applications running in developer mode with ctrl + c in each terminal window. You'll also need to stop the MQ container you created earlier as we'll create and set one up one with whole system in containers using docker compose.
Get the container ID for the running MQ container with podman ps and then run the following command to stop the container:
podman stop <container-id>
Now, you're ready to build the applications with these commands:
mvn -f amqp-quickstart-producer clean package -DskipTests
mvn -f amqp-quickstart-processor clean package -DskipTests
This will produce a .jar file for each application, such as:
amqp-quickstart-producer/target/amqp-quickstart-producer-1.0.0-SNAPSHOT.jar
You can start the demo by building the containers from the docker-compose.yml file by running this command:
podman compose up --build
After a little start-up time, you should see output like this:

Go to the web address again (http://localhost:8080/quotes.html), and refresh the page. You need to refresh to allow the amqp-quickstart-producer application to subscribe to the 'quotes' topic on the new broker.
Now, the demo should work as before, but this time, you're using a full Quarkus JVM stack that could realistically run in production (if you include an authorization framework).
Step 5. Run the sample in native-image mode using GraalVM
This is great progress, but we're still using the full Java VM. It's easy to transition into using GraalVM without changing our applications at all. Use the GraalVM documentation to install and set up GraalVM . Select the platform that you're running on, which will be Windows, Mac, or Linux (do not select the Docker container), for the purposes of this tutorial. You will also need to set your PATH and JAVA_HOME variables for the terminal you're running in. If you use sdkman to install and use GraalVM then this will be done for you.
Once you've installed GraalVM, check that you're using it by running this command:
java --version
You should see something like this list, where you can see that GraalVM is being used:

Now that you've got GraalVM it's time to build and run your applications in this hyper-optimized environment.
Build the applications with these Maven commands:
mvn -f amqp-quickstart-producer clean package -Pnative -DskipTests -Dquarkus.native.container-build=true
mvn -f amqp-quickstart-processor clean package -Pnative -DskipTests -Dquarkus.native.container-build=true
This will take longer than the other builds as the stack is being optimized while the build is taking place. You might need to increase the memory allocated to Podman too; I'd recommend at least 4GB.
The binaries will be in the application target directory, such as:
amqp-quickstart-producer/target/amqp-quickstart-producer-1.0.0-SNAPSHOT-runner
Next, set the QUARKUS-MODE environment variable to use native-image mode and run the native-image builds in containers with these commands:
export QUARKUS_MODE=native
podman compose up --build
If you go to http://localhost:8080/quotes.html and refresh the page, everything should work as before, but this time, your applications are optimized for a cloud-native deployment.
Run the following command to list the running containers:
podman ps
Output:

Note that the application containers are the native containers, such as: amqp-quickstart-producer:1.0-native.
Run the following command to see the respective size of the 4 containers that have been created.
podman image ls | grep quickstart
Output:

Summary
If you've followed this tutorial and got here, you've been able to:
- Enable AMQP in an MQ container
- Run a reactive Quarkus application with IBM MQ in developer mode, making changes and seeing them reflected in your application without rebuilding
- Run a Quarkus demo in JVM mode, deploying it in containers
- Build a native-image version of the demo and deploy it in containers running highly optimized Java stacks