Configuring JMS in IBM WAS Liberty
Want to bring simple JMS functionality to your project? Check out how you can use WAS Liberty JMS on a standalone server.
Join the DZone community and get the full member experience.Join For Free
Quite recently, we completed a project that needed simple JMS capabilities. A user would initiate an action on our website, get a prompt (e.g. USSD) on his/her mobile, respond to it, and feed this response to the web app. See the sketch below.
Using WAS Liberty's built-in JMS Messaging engine worked quite well, as the messages had a very short time to live and we did not need persistence. Also, WAS ND (traditional) allows you to communicate to a WAS Liberty JMS messaging engine quite easily.
In this article, I will show you how to set up a standalone JMS messaging engine server and configure another Liberty server and WAS ND to talk to it.
Create the JMS Messaging Engine server
I'm assuming you've already created or downloaded a WAS Liberty runtime with JEE 7 features. If not, you can have a look here. For more details on the embedded JMS messaging provider, have a look here.
Go to the Liberty runtime folder, e.g. /was/liberty/wlp/usr/servers.
Create a new folder "jms-messaging-engine-server" with the following server.xml inside:
<?xml version="1.0" encoding="UTF-8"?> <server description="Standalone Liberty JMS messaging server"> <!-- Enable features --> <!-- The wasJmsServer feature is required for the messaging engine The rest add some security that for now is out of scope for this example. --> <featureManager> <feature>federatedRegistry-1.0</feature> <feature>ldapRegistry-3.0</feature> <feature>appSecurity-2.0</feature> <feature>localConnector-1.0</feature> <feature>wasJmsServer-1.0</feature> </featureManager> <httpEndpoint host="rbester.pc" httpPort="10302" httpsPort="10502" id="defaultHttpEndpoint"> <tcpOptions soReuseAddr="true"/> </httpEndpoint> <!-- Expose the JMS endpoint --> <wasJmsEndpoint id="InboundJmsCommsEndpoint" host="rbester.pc" wasJmsPort="12302" wasJmsSSLPort="12502" /> <!-- Create a messaging engine with a non-persistent JMS Topic Space --> <messagingEngine> <topicSpace id="ExpressNonPersistent.Topic.Space" forceReliability="ExpressNonPersistent" maintainStrictOrder="False" maxMessageDepth="5000"> </topicSpace> </messagingEngine> <logging consoleLogLevel="AUDIT" copySystemStreams="True" maxFiles="10" logDirectory="/waslogs/jms-messaging-engine-server" traceSpecification="*=info"/> <!-- Your security settings goes here; I ommitted my settings for brevity --> <include location="security.xml" optional="false"/> </server>
As explained in the code snippet, a single Topic Space (slot where you create JMS Topics) is specified, to which we will connect in the next sections.
Setup for Liberty Consumer Server
Create a second Liberty server. Your application(s) that need to send and receive JMS messages are deployed on this server. You can set up a messaging engine on the same server as the one your apps are deployed to, but I found it nicer to do it on separate servers.
Create a folder for your server: /wlp/usr/servers/my-jms-consumer-server
Then, add a server.xml as in the example below:
<?xml version="1.0" encoding="UTF-8"?> <server description="JMS messaging consumer server"> <!-- Enable features --> <!-- Add features needed by your projects. Note the following features: wasJmsClient, mdb, jms. These are required to enable JMS usage and use JEE Message Beans. --> <featureManager> <feature>federatedRegistry-1.0</feature> <feature>ssl-1.0</feature> <feature>ldapRegistry-3.0</feature> <feature>appSecurity-2.0</feature> <feature>localConnector-1.0</feature> <feature>ejbLite-3.2</feature> <feature>jms-2.0</feature> <feature>mdb-3.2</feature> <feature>wasJmsClient-2.0</feature> </featureManager> <httpEndpoint host="rbester.pc" httpPort="10301" httpsPort="10501" id="defaultHttpEndpoint"> <tcpOptions soReuseAddr="true"/> </httpEndpoint> <applicationMonitor dropinsEnabled="false"/> <applicationMonitor updateTrigger="mbean"/> <!-- Security settings ommitted; include yours here --> <include location="security.xml" optional="false"/> <!-- Your application config goes here --> <include location="apps.xml" optional="false"/> <!-- Declare a topic connection factory resource to create a connection to the messaging engine --> <jmsTopicConnectionFactory jndiName="jms/TCF" connectionManagerRef="ConMgr1" clientID="jms-client"> <properties.wasJms remoteServerAddress="rbester.pc:12302:BootstrapBasicMessaging"/> </jmsTopicConnectionFactory> <connectionManager id="ConMgr1" maxPoolSize="10" minPoolSize="10" /> <!-- Declare a topic space resource to create a Publisher/Subscriber session to the TopicSpace --> <jmsTopic id="myJmsTopic" jndiName="jms/myJmsTopic"> <!-- This need to match a topic space, including the delivery mode, of that on the messaging engine --> <properties.wasJms topicName="HelloMessages" topicSpace="ExpressNonPersistent.Topic.Space" deliveryMode="NonPersistent" timeToLive="60000" priority="1" readAhead="AsConnection"/> </jmsTopic> <!-- Declare an activation specification for the message-driven beans that are deployed on Liberty. The message-driven beans use the activation specification to asynchronously consume messages that are published to the jmsTopic resource. The ID value must be given in the following format: application name/module name/bean name format, where application name is the name of the application that is deployed (if an EAR is used), module name is the name of the module in which the bean is packaged, and bean name is the ejb-name of the enterprise bean. Ensure that the destinationRef attribute is pointing to a valid jmsTopic resource ID. --> <jmsActivationSpec id="my-application/MyTopicSubscriber"> <properties.wasJms destinationRef="myJmsTopic" destinationType="javax.jms.Topic" remoteServerAddress="rbester.pc:12302:BootstrapBasicMessaging"/> </jmsActivationSpec> </server>
The settings above set up the topic connection factory to publish messages to, and (manually) subscribe to responses from, the topic. To use an MDB, you add the activation spec as indicated.
Connect to the Liberty JMS Topic via WAS ND
The configuration for the JMS Topic can be done as follows, in the case of IBM WAS 8.5.
Step 1: Set up/configure the Topic: Resources -> JMS -> Topics
Log into the Admin Console (for the deployment manager or standalone WAS server).
Go to Resources -> JMS -> Topics
Create a New topic and fill in the following settings:
|Provider||Default Messaging Provider|
|Bus name||(other, please specify) - defaultBus|
|Topic space||(other, please specify) - ExpressNonPersistent.Topic.Space|
|JMS delivery mode||Nonpersistent|
|Read ahead||Inherit from connection factory|
Step 2: Set up/configure Activation Spec if you intend on using MDBs: Resources -> JMS -> Activation specifications
To set up an MDB to listen to our topic, do the following on the WAS admin console.
Go to Resources -> JMS -> Activation specifications
Create a new Activation specification with the following settings.
|Provider||Default messaging provider|
|Destination JNDI name||jms/myJmsTopic|
|Bus name||(other, please specify) defaultBus|
|Target type||Messaging engine name|
The rest can be left default.
In this article, I gave a case study where built-in WAS Liberty JMS is used in a standalone server. I've also listed how to configure both another Liberty server as well as a WAS 8.5 (ND or standalone) server to connect to and use the messaging engine.
I've omitted things like configuring the app itself, creation of the MDB, and security settings to keep this article focused. Have a look at the Wiki for WAS Liberty for a lot of additional information.
Opinions expressed by DZone contributors are their own.
Apache Kafka vs. Message Queue: Trade-Offs, Integration, Migration
Build a Simple Chat Server With gRPC in .Net Core
Building A Log Analytics Solution 10 Times More Cost-Effective Than Elasticsearch