Payara Micro is a lightweight middleware platform for containerized Jakarta EE application deployments, but it still provides a lot of APIs and functionality for developers. On top of all Jakarta EE Web Profile APIs, Payara Micro also supports a additional Jakarta EE APIs, and it also provides the same MicroProfile, Payara, and JCache APIs as our complete application platform, Payara Server. In this article, we’ll show you how to make use of Jakarta Messaging (JMS) in Payara Micro to send and receive messages to and from a JMS broker.
{{cta(‘0c1037e0-adaf-4401-b888-05088602db6a’)}}
What is Jakarta Messaging (JMS)?
Jakarta Messaging (JMS), formerly known as Java Message Service, is supported by various message brokers. Payara Micro doesn’t contain a JMS broker on its own so we’ll need to connect to an external broker. We need to deploy a JMS resource adapter (RAR) for our target broker, and configure it to connect Payara Micro to the broker as a JMS client.
We’ll use a demo application that sends a message to a JMS broker and then listens to the same message and prints it into the log.
The simplest way to use a JMS broker with Payara Micro is to use OpenMQ as the JMS broker. OpenMQ is very well supported by the Payara Platform. It is even bundled with Payara Server which uses it as the default JMS broker. It’s very natural to use OpenMQ with Payara Micro if you’re already familiar with Payara Server.
We’ll need to do the following to execute the demo JMS application on Payara Micro using OpenMQ as a message broker:
Download, install and start OpenMQ broker
Add a new user to OpenMQ
Deploy OpenMQ resource adapter RAR to Payara Micro
Configure the resource adapter to connect to the OpenMQ broker
Connecting Payara Micro to ActiveMQ
While OpenMQ is the default message broker in Payara Server, there are other JMS message brokers that you can use with Payara Micro. For example, ActiveMQ is a popular open source message broker and it can be easily integrated with Payara Micro because it provides an official resource adapter RAR. However, this resource adapter only supports the JMS 1.1 API. Therefore Payara Micro supports sending messages to and receiving them from ActiveMQ only using the JMS 1.1 API. Using new features of JMS 2.0 will cause errors.
If you want to use ActiveMQ, you can follow the instructions for OpenMQ with a few differences. The biggest difference is that OpenMQ and ActiveMQ understand different non-standard properties in the connection definition and MDB configuration. We’ll first explain how to use OpenMQ with Payara Micro and then describe what to do differently for ActiveMQ at the end of this article.
To start using the JMS API to send messages, we need to define two resources via the Java EE Connector Architecture (JCA) API: a connection factory and a destination.
We’ll define a connection factory using the annotation @ConnectionFactoryDefinition placed on any EJB class, preferably on the class that will use it:
The queue has to be named with a JNDI identitier. It also has to specify the resource adapter and specify the type javax.jms.Queue in the interfaceName property.
We specified the Name property to bind this queue to the TestQ queue in the OpenMQ broker. We don’t need to create this queue in the OpenMQ broker. If it doesn’t exist, it will be created.
The className property has to specify the queue implementation. This is com.sun.messaging.Queue for OpenMQ. This class and the Name property that specifies the name of the queue in the broker are specific to OpenMQ. They may be different if we use another broker like ActiveMQ.
Finally, we’ll create a stateless EJB and inject the connection factory and the queue as the following fields:
@Override public void onMessage(Message message) { } }
The ReceiveMessage MDB is a class with the @MessageDriven annotation that implements the method onMessage from the MessageListener interface. This method is called for every incoming message.
The activation config properties are analogous to the properties in the connection factory and the queue which we use for sending messages. The property destinationType is analogous to the interfaceName in the queue definition, the property destination is analogous to the OpenMQ-specific Name property. All other properties are analogous to properties with a similar name.
Deploy OpenMQ Resource Adapter
OpenMQ resource adapter is distributed together with the OpenMQ broker. Therefore we’ll first download and install OpenMQ from its download page as a ZIP file and unpack it to a local directory. If you already have Payara Server installed, you can skip this step and use OpenMQ in the Payara Server installation which is located in the mq directory.
The resource adapter is located in the OpenMQ installation directory. It’s the file imqjmsra.rar in the lib directory. We’ll copy it to the project directory.
The resource adapter imqjmsra.rar is installed by deploying it to Payara Micro in the same way as an application archive (e.g. a .war) is deployed. The following shows an example:
java -jar payara-micro.jar imqjmsra.rar
The connector is subsequently available to all other applications deployed to Payara Micro.
The name of the deployed connector will be the name of the file without the .rar extension. In this case it will be imqjmsra. Our demo application already expects a connector with this name to use it for incoming and outgoing messages.
We can run our demo application demo.war by deploying it after the rar file:
java -jar payara-micro.jar imqjmsra.rar myapp.war
To simplify starting our application, we’ll bundler Payara Micro and the rar file together with the –outputUberJar option:
The created JAR file payara-micro-mq.jar is a custom Payara Micro launcher that already contains the deployed resource adapter.
We can now start our application using this launcher instead of the standard Payara Micro JAR file, without supplying the resource adapter:
java -jar payara-micro-mq.jar demo.war
Running OpenMQ
With our application and OpenMQ resource adapter ready to be deployed, it’s time to start the message broker. To start the the OpenMQ broker, go to the OpenMQ installation directory and execute the following command:
bin/imqbrokerd
To verify that your OpenMQ broker is up and running, you can start the GUI admin tool called imqadmin. Execute the following command from the OpenMQ installation directory:
bin/imqadmin
The OpenMQ Administration Console will open in a new desktop window:
Then connect to the LocalBroker broker with the default admin user admin and password password. After you connect, you’ll be able to see the number of services and destinations in the broker:
Create a New OpenMQ User
By default, OpenMQ allows anonymous connections using the guest user. Application running on Payara Micro will connect using this user if no user name and password is specified.
Our demo application connects to the OpenMQ broker using an openmq user. This user doesn’t exist in the default OpenMQ installation therefore we need to create it. The GUI Administration Console doesn’t support managing users so we’ll use the imqusermgr command line tool. The following command will create an openmq user with password password:
bin/imqusermgr add -u openmq -p password
Running the Demo Application
Once we have OpenMQ broker running and accessible with the user openmq, we’ll run it using our custom Payara Micro JAR payara-micro-mq.jar that bundles the OpenMQ resource adapter:
java -jar payara-micro-mq.jar demo.war
Payara Micro will first deploy the OpenMQ adapter. Then it will deploy our demo application which sends a message to the TestQ queue in the OpenMQ broker every 5 seconds. The OpenMQ broker immediately sends the message from the TestQ queue back to our application. The messages are dispatched to the MDB that listens to messages from the TestQ. The MDB then prints the message with its metadata to the console.
Externalizing Configuration
Until now, we hard-coded all the configuration for the resource adapter in the source code. Most applications need to be configured externally so that they can be adapted to the environment.
We’ll now improve our demo application so that all variable aspects of the resource adapter configuration can be configured externally when launching the application, e.g. by system properties or environment variables.
Payara Micro supports variable references in Jakarta EE resource annotations, including the annotations we used to define the connection factory, queue and MDB. We’ll take advantage of this and we’ll replace all non-constant values with variable references. We’ll use references to MicroProfile Configuration properties which has several benefits:
configuration can be provided in several forms, including environment variables, system properties, and other configuration sources provided by Payara Micro
default values can be supplied as properties hard-coded in the application
We’ll first create a file microprofile-config.properties. This file should end up in the META-INF directory in the classpath. In a WAR it should thus end up in WEB-INF/classes/META-INF. In our maven-based project, we’ll create the file in src/main/resources/META-INF directory.
We’ll write the following into the microprofile-config.properties file to define the default values which we want to allow to overwrite:
Then we’ll replace all the corresponding values above in the annotations for the connection factory, queue and MDB with the references to their corresponding MicroProfile properties. For example, we’ll replace “TestQ” with “${MPCONFIG=mq.queue.name} and “localhost:7676” with ${MPCONFIG=mq.addressList}. This is how our connection factory definition will look like:
The default ActiveMQ user is admin with password admin (for creating a new user please refer to the ActiveMQ documentation)
We need to use the ActiveMQ resource adapter (download from here)
We need to specify different non-standard properties for connection factory, queue and MDB
We need to use a different implementation class for the queue
We’ll need to change the code that sends the messages to use JMS 1.1 API
Since the name of the ActiveMQ resource adapter will be different, e.g. activemq-rar, we also need to change the resource adapter name in the connection factory, queue and MDB definitions. Here’s what they all would look like (differences from OpenMQ highlighted):
And here’s how we send the message using JMS 1.1 API:
try (Connection conn = factory.createConnection()){ Session sess = conn.createSession(true,Session.AUTO_ACKNOWLEDGE); sess.createProducer(queue) .send(sess.createTextMessage("This is a test at " + new Date())); }
Finally, we need to start ActiveMQ and Payara Micro with the ActiveMQ adapter and our application.
That’s it. By now, you should be able to connect Payara Micro to OpenMQ or ActiveMQ and build microservices that communicate asynchronously using JMS. You can also connect to other JMS brokers, you just need to use using a resource adapter for them and modify the JMS and MDB properties specific for that adapter.