Java Messaging Service – Part 6 – JMS Listener
In this blog article, we will see the configuration points in a JMS listener. We will also see Listener processing at the end.
What is JMS Listener?
– JMS Listener is a data instance of category Integration resources.
– It provides information to route the JMS messages to the service JMS rule for processing.
– JMS listeners support JMS 1.0 features.
Business scenario: Let’s say a Banking organization XYZ uses different applications to process the loans. A java application maintains the loan status. Whenever the loan status changes to Inactive, the Java application needs to send the message to all the interested parties. Pega is used as the customer servicing application and it is one of the interested parties for the loan Status change. The Pega application needs to refresh the loan status in its data table.
The architecture team decided to use Java Messaging Service as the solution for the business scenario. So the source application publishes a single message and send to a JMS Topic that can be consumed by one or more subscribers.
The starting of this implementation is to define a JMS listener
How to create a new JMS listener rule?
Step 1: Records -> Integration resources -> JMS Listener -> Create new
Fill in a meaningful name.
Step 2: Configure all the configuration points in the JMS listener rule form.
What are the configuration points in the JMS listener rule form?
There are two main tabs.
- Listener properties
- JMS properties
Note the message at the top. JMS listener is available only when PRPC is deployed as a web application. For enterprise application, always go with JM MDB listener.
Instead of going field by field, We will see old style of explaining the configuration points for listeners 🙂
Let’s ask ourselves what are the basic details we need for configuring a JMS listener?
- What is the messaging model for our JMS messages?
- How do we connect to JMS provider, in current case it is ActiveMQ?
- At which destination should the JMS listener actively monitor?
- How do we respond to the received message?
- Do we have any filter on selected messages in the topic?
- Do we need parallel processing to improve the performance?
- What are the error handling scenarios?
- After receiving the message, how do we process it?
Let’s answer one by one.
1. What is the messaging model for our JMS messages?
In the introduction post, we already discussed about two messaging model/domains in JMS
- Point-to-point
- Publish and subscribe
Here in this tutorial, we need to use Publish/Subscribe model since the loan status change message will be consumed by more than one subscriber.
In the JMS properties tab – Messaging model, select Publish-and-Subscribe option.
2. How do we connect to JMS provider, in current case it is ActiveMQ?
I strongly recommend you to go through the below posts in setting up ActiveMQ in your location machine and install the activemq-all jar in your personal edition.
Verify that Connection factory resource is specified in the server.xml page
And the same resource is linked in the context.xml of the prweb/Meta-INF/Context.xml and referred in the web.xml file.
As we saw before Active MQ do not support the JNDI server, we need to use resource reference option to connect to ActiveMQ server.
Switch to JMS properties, Session block.
Use the resource reference option in Resource name resolution field.
In the connection factory, use the picklist to select the specified connection factory in the server.xml.
You can use factory username and password, if your connection factory is secured with a user credentials. In our case, it is not needed.
3. At which destination should the JMS listener actively monitor?
4. How do we respond to the received message?
I purposefully couples 3rd and 4th question because for both we need to do similar kind of action.
As per our current scenario, we need to use Topic as the destination, where the JMS Listener actively monitors.
We will also test sending a response message. For Response, I am going to use a Separate Topic.
Note: In these publish-and-subscribe model, it may not be a mandatory requirement from the source system to receive the response from the subscribers. The decision can always vary!
Step 1: Create two new topics LoanStatusReq, LoanStatusRes
I am using Hawtio to administer ActiveMQ. Launch http://localhost:8080/hawtio
Click on localhost – Create tab
Give the topic name and click Create Topic
You will see the newly created topic in the list.
Step 2: Declare the Topic names globally in the server.xml file
C:PRPCPersonalEditiontomcatconf
<Resource name=”jms/topic/LoanStatusReq” auth=”Container” type=”org.apache.activemq.command.ActiveMQTopic” factory=”org.apache.activemq.jndi.JNDIReferenceFactory” physicalName=”LoanStatusReq”/>
<Resource name=”jms/topic/LoanStatusRes” auth=”Container” type=”org.apache.activemq.command.ActiveMQTopic” factory=”org.apache.activemq.jndi.JNDIReferenceFactory” physicalName=”LoanStatusRes”/>
Step 3: Specify the resource link in the application context.xml file
C:PRPCPersonalEditiontomcatwebappsprwebMETA-INF
<ResourceLink global=”jms/topic/LoanStatusReq” name=”jms/topic/LoanStatusReq” type=”javax.jms.Topic”/>
<ResourceLink global=”jms/topic/LoanStatusRes” name=”jms/topic/LoanStatusRes” type=”javax.jms.Topic”/>
Step 4: Update the web.xml file – Resource ref
C:PRPCPersonalEditiontomcatwebappsprwebWEB-INF
Save all three files and restart the server.
Tip: Try to save the JMS listener before restarting server, else you may lose the changes and need to create again.
After restart, switch to the JMS properties tab in the listener form.
You see all three destinations defined in the deployment descriptor files are populated in the dropdown.
Select the LoanStatusReq destination.
For the response destination, you have three options.
Message – It uses the JMSReplyTo header value from the incoming message to determine the reply destination.
Listener – Using this option, you can manually specify the destination name.
No reply – Yes, it is NO.
I am using the Listener option to select the referenced resource for Loan status reply.
Next question
5. Do we have any filter on selected messages in the topic?
You can always filter the Topic messages to select and processes only the messages that are relevant to you.
By default, the JMS properties can be used as filter criteria. How to specify it?
It is pretty simple. You need to specify SQL like conditional expression in the message selector field.
For example, If Pega application is responsible only for home loans then the JMS listener can select only the messages that have JMS property Loan type = ‘Home’
Please go through the below link, you will understand very clearly ☺️
https://docs.oracle.com/cd/E19798-01/821-1841/bncer/index.html
Do we need parallel processing to improve the performance?
6. Do we need to perform some parallel processing to improve the performance?
Listener nodes
– In a real production environment, you may have multiple nodes in a cluster.
– In some projects, they may have some specific node for batch processing to improve performance. Other projects, they may have only one node.
You can decide on which node you need to run this listener. You can make the configurations in the properties tab.
Block startup – Always keep this unselected. If selected, the listener will be blocked. Listener will run again only when this is unchecked.
Startup option – you get 4 options
a) Run on all nodes – you know what it means. The listener runs on all nodes in the cluster
b) Node-based startup – Here you can specify to start the listener only on specific nodes, using node id.
You can specify multiple node id in the array
c) Host-based startup – Similar to node based startup, we can start the listener only on specific nodes, using hostnames.
Here you can specify hostnames. There may be some situations, where nodes can share the same host name, you can specify the count
d) Node classification –
What is node classification?
– This is a new concept introduced in Pega 7.3
– You can classify nodes based on its usage.
Imagine, your application has some long running batch. If the batch or agent runs on the same node, where the end users log in and work, then it MAY have some impact on the performance. Batches can eat up the system resources. Already there are some ways to make the batch or agent run on specific nodes.
With the node classification, you can distinguish the nodes based on their usage.
There are certain ways to configure node types. There are dedicated blog articles on Node classification which you can take a look at –
So with the node classification, you can map the agents and listeners to run on a specific node type.
Note: Try to use node classification option over node based and hosed based startup
By default, our personal edition comes with node classified as shown below. You can get this in the admin studio.
I am going to use the background processing option.
You have a button to reset the startup. You can use it, when you want to change the assigned nodes.
There is one more area to improve the performance
Multithreading
In the listener properties block, you have the option to specify concurrent threads.
Usually, the JMS listener uses Java thread for processing a file. Say, for example, you need to process more than 1 message at the same time, then you can go for multithreading.
Note: please make sure you will have sufficient JVM memory before going for multithreading.
7. What are the error-handling scenarios?
There are a few configurations in the file listener form.
a) Send error messages
Usually errors can be known error or unknown run-time error.
For example – Say the loan number does not exist in our system. So we can handle this may be by sending a valid response message. These are all kind of known exception scenarios. Say there is some error with the listener processing at run-time, and then your response mapping may not be set. In such case, you can always use this option to send back the exact error message.
Note: This works only when the JMSReplyTo header has a valid destination.
b) No Local messages –
You will find this in the JMS properties tab.
Think of a scenario, as Pega application when the loan status trigger occurs in our system, then we may need to act as publisher and publish the message in the same Topic destination, so that others can process the message
In such case, our listener don’t want to pick the same message we published right? These messages are called local messages (loop back) This is controlled by this option.
Note: Client ID check determines whether a message is local message or not
3. Durable Subscriber – This option is used for Publish-and-subscribe model.
To make sure that the published message is received by all the subscribers.
There are two types of subscribers. Durable and non-durable.
Say Pega application is non-durable subscriber. It means when a message is published and Pega server is down by that time then Pega application is not considered as a potential subscriber for the message. Once it is up, then it can receive all the new message, but not the missed one.
If it is a durable subscriber, then all messages are guaranteed to reach the subscriber.
The below link will give a better understanding.
https://activemq.apache.org/how-do-durable-queues-and-topics-work
From Hawtio, you can always create a durable subscriber for a client.
The client ID can be used in the listener rule form when the durable subscriber is selected.
Additional configurations
Acknowledgement –
Acknowledgement is used by the JMS provider to make sure that the messages are read by the consumer. Once the message is read, then JMS provider can mark the message as read. If acknowledgement is not received then JMS provider keeps the message in destination so that it can be picked up again.
These explicit acknowledgements, you can send as soon as you receive the message or you can also acknowledge after successful processing.
Wait Interval –
In the listener properties, you will see the option wait interval in seconds.
We can pass the action to stop the listener anytime. Let’s say from admin portal I want to stop the listener. When I command that action, it doesn’t get executed in seconds. Every running listener pauses to check if any such command is issued at a regular wait interval. Here by default it is 60 seconds.
Okay, the final question now ☺️
8. After receiving the message, how do we process it?
This is an obvious answer! – We have Service-JMS rule to do the Job. We will see all the configuration points in the next post. For now, I just created a template Service-JMS rule and added it.
One final interesting configuration is container-managed transactions.
In the introduction article, we sneak peek at Java Transaction API. This option is applicable only for the J2EE complaint application servers, where the transaction is managed effectively so that commit and rollback can happen at the right time.
This is a vast discussion topic, check it out yourself. The basic concept is commit will be issued only when the processing is successful across distributed systems, else we can roll back and do the processing again.
Check the link for more details – https://docs.oracle.com/javaee/6/tutorial/doc/bncgl.html
Save the JMS Listener rule.
Let’s test if the JMS listener works right on the destination topic LoanStatusReq.
Step 1: Make sure your listener is up and running from the admin portal.
You can always stop (wait for a few seconds) and then start the listener
Step 2: Open the tracer on the template service JMS rule you specified in the Listener form.
Make sure you enable services in tracer settings
Step 3: Publish a message from the Hawtio to the LoanStatusReq destination
Step 4: Verify if the listener picks the message.
The tracer should show you the service run.
Hawtio you will show you the dequeued count. It means the message is read.
All good for now.
As a summary in this post
– We created a new Topic destination in ActiveMQ
– We specified the JMS resources in the server deployment descriptor files
– We configured a JMS listener rule form to monitor the topic destination.
– Started the listener and tested the working.
In the next (final) article on the JMS series, we will see how to configure a Service JMS rule to process the message.