DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Event Driven Architecture (EDA) - Optimizer or Complicator
  • Event-Driven Microservices: How Kafka and RabbitMQ Power Scalable Systems
  • Exploring Intercooler.js: Simplify AJAX With HTML Attributes
  • Streamlining Event Data in Event-Driven Ansible

Trending

  • The Evolution of Scalable and Resilient Container Infrastructure
  • Using Java Stream Gatherers To Improve Stateful Operations
  • Designing a Java Connector for Software Integrations
  • How To Build Resilient Microservices Using Circuit Breakers and Retries: A Developer’s Guide To Surviving

How To Use JMS ActiveMQ With Mule 4 - Part 5

In this blog, we will see how to use the Mulesoft JMS connector to perform the JMS guaranteed delivery.

By 
Anand Joshi user avatar
Anand Joshi
·
Updated Aug. 17, 21 · Tutorial
Likes (5)
Comment
Save
Tweet
Share
19.1K Views

Join the DZone community and get the full member experience.

Join For Free

This is the 5th Part of the JMS ActiveMQ with Mule4 Series, You can read previous parts here: Part 1, Part 2, Part 3, and Part 4. In this post, we will learn about the JMS guaranteed delivery.

Guaranteed/Persistent Delivery in JMS: 

We can make sure that there is no message loss while using the JMS for message transfer with mule API. There might be a possibility that a published message is not processed successfully due to any error/issue or app crash etc. so for such cases JMS can ensure that the unprocessed message is not lost and will be moved to a Dead Letter Queue and from there we can consume the message again.

Before moving ahead, let us know what is a Dead Letter Queue.

Dead Letter Queue is used to hold messages that can't be delivered to any receiver, or messages that couldn't be processed.

Now, let's first understand with a demo that why we need a persistent/Guaranteed delivery mechanism.

We have a mule flow JMS-demo-flow1 as shown in the below image and this flow gets triggered by an HTTP Requester, then we have a logger which will display the received message in logs, next we have the JMS Publish component which will publish the message into the JMS Queue and lastly we have a logger which will display a success message that the flow is completed.

In the below-given image, we can see that we have only done JMS connector Configuration and added the Destination Queue Name “sampleQueue1”, the rest of everything is the default.

The mule flow JMS-demo-flow1We have second flow named as jms-demo-flow2. This flow has a JMS on New Message Listener, which will pick up the newly available message from the Queue “sampleQueue1” then we have a logger which will display the received message and lastly we have a HTTP Requester. In HTTP Requester we are giving an incorrect url path purposely so that it will fail.

The JMS-demo-flow2

Now let's trigger the below message from the postman and see how our API behaves.

API behavior test

We can see that JMS-demo-flow1 starts as soon as we hit the mule endpoint from Postman. In the logs, we can see the message received from the postman and the correlation_ID.

Message received from the postman

We can see at the JMS console and confirm that the message is still in SampleQueue1 till now as shown in the below image:

Message in SampleQueue1

As soon as the message gets published, the On New Message Listener component of the JMS-demo-flow2 will pick the message. We can see the same message with the same correlation ID in the below image:

On New Message Listener of the JMS-demo-flow2

On processing further, as expected, we get a failure because we have configured an incorrect URL in the HTTP requestor.

Processing error

So the message sent from Postman is published successfully into SampleQueue1. But when this message is picked for processing we got an error in-between and processing is stopped. But we have lost the message. The message which we were processing is no more in SampleQueue1.   Below are the snips of the JMS showing the same:

The snips of the JMS

We can see there is no pending message in the queue.

The snips of the JMS

Below are the Mule Logs:

 INFO  2021-07-19 19:52:59,714 [[MuleRuntime].uber.03: [jms-demo].jms-demo-flow1.CPU_LITE @6c2b2dcc] [processor: jms-demo-flow1/processors/0; event: 8042abc0-e89b-11eb-9b4e-c8b29becab99] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: {

"Message": "This is a sample message"

}

INFO  2021-07-19 19:53:23,410 [[MuleRuntime].uber.03: [jms-demo].jms-demo-flow1.CPU_LITE @6c2b2dcc] [processor: jms-demo-flow1/processors/2; event: 8042abc0-e89b-11eb-9b4e-c8b29becab99] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: Message Published Successfully

INFO  2021-07-19 19:54:21,619 [[MuleRuntime].uber.04: [jms-demo].jms-demo-flow2.CPU_LITE @62f84f84] [processor: jms-demo-flow2/processors/0; event: 8042abc0-e89b-11eb-9b4e-c8b29becab99] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: {

"Message": "This is a sample message"

}

ERROR 2021-07-19 19:56:08,634 [[jms-demo].http.requester.requestConfig.08 SelectorRunner] [processor: jms-demo-flow2/processors/1; event: 8042abc0-e89b-11eb-9b4e-c8b29becab99] org.mule.extension.http.internal.request.HttpRequester: Error sending HTTP request to http://localhost:8081/first

ERROR 2021-07-19 19:56:42,458 [[jms-demo].http.requester.requestConfig.08 SelectorRunner] [processor: jms-demo-flow2/processors/1; event: 8042abc0-e89b-11eb-9b4e-c8b29becab99] org.mule.runtime.core.internal.exception.OnErrorPropagateHandler: 

********************************************************************************

Message               : HTTP GET on resource 'http://localhost:8081/first' failed: Connection refused: no further information.

Element               : jms-demo-flow2/processors/1 @ jms-demo:jms-guranteed-delivery.xml:22 (Request)

Element DSL           : <http:request method="GET" doc:name="Request" doc:id="f9cf1e9d-8d11-484e-be93-c516d88494ac" url="http://localhost:8081/first"></http:request>

Error type            : HTTP:CONNECTIVITY

FlowStack             : at jms-demo-flow2(jms-demo-flow2/processors/1 @ jms-demo:jms-guranteed-delivery.xml:22 (Request))

  (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)

To ensure that we don’t lose our JMS message in case of failure, we will make a small change in the configuration of publish and On New Message component of JMS. We will set Persistent to True.

Setting Persistent delivery to true

Similarly, we will set Persistent delivery to true in the JMS-demo-flow2  

Setting Persistent delivery to true in the JMS-demo-flow2


After doing the above changes we will trigger the same message from the postman. We can see that the flow is triggered and we have a correlation ID associated with it.

Triggering message from the postman

Once published we can see the same message in the SampleQueue1 in JMS.

Message in the SampleQueue1 in JMS

Now, as expected the message is picked by On New Message Listener and failed again.

Message failed

Logs: 

INFO  2021-07-19 21:55:47,966 [[MuleRuntime].uber.05: [jms-demo].jms-demo-flow1.CPU_LITE @4791f97d] [processor: jms-demo-flow1/processors/0; event: f53db3e0-e8ad-11eb-9326-c8b29becab99] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: {

"Message": "This is a sample message"

}

INFO  2021-07-19 21:57:38,340 [[MuleRuntime].uber.07: [jms-demo].jms-demo-flow2.CPU_LITE @2caa25da] [processor: jms-demo-flow2/processors/0; event: f53db3e0-e8ad-11eb-9326-c8b29becab99] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: {

"Message": "This is a sample message"

}

INFO  2021-07-19 21:57:40,665 [[MuleRuntime].uber.05: [jms-demo].jms-demo-flow1.CPU_LITE @4791f97d] [processor: jms-demo-flow1/processors/2; event: f53db3e0-e8ad-11eb-9326-c8b29becab99] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: Message Published Successfully

ERROR 2021-07-19 21:57:48,376 [[jms-demo].http.requester.requestConfig.08 SelectorRunner] [processor: jms-demo-flow2/processors/1; event: f53db3e0-e8ad-11eb-9326-c8b29becab99] org.mule.extension.http.internal.request.HttpRequester: Error sending HTTP request to http://localhost:8081/first

ERROR 2021-07-19 21:58:16,083 [[jms-demo].http.requester.requestConfig.08 SelectorRunner] [processor: jms-demo-flow2/processors/1; event: f53db3e0-e8ad-11eb-9326-c8b29becab99] org.mule.runtime.core.internal.exception.OnErrorPropagateHandler: 

********************************************************************************

Message               : HTTP GET on resource 'http://localhost:8081/first' failed: Connection refused: no further information.

Element               : jms-demo-flow2/processors/1 @ jms-demo:jms-guranteed-delivery.xml:23 (Request)

Element DSL           : <http:request method="GET" doc:name="Request" doc:id="f9cf1e9d-8d11-484e-be93-c516d88494ac" url="http://localhost:8081/first"></http:request>

Error type            : HTTP:CONNECTIVITY

FlowStack             : at jms-demo-flow2(jms-demo-flow2/processors/1 @ jms-demo:jms-guranteed-delivery.xml:23 (Request))

  (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)

********************************************************************************

Let's have a look at the JMS Console, here we can see that one more queue is created with the name ActiveMQ.DLQ and it has one message in it.

ActiveMQ.DLQ queue

We can see that the message which was failed while processing is now inside ActiveMQ.DLQ queue. We can confirm it is the same message by looking at either the message details or the Correlation_ID.

Failed message inside a DeadLetter Queue

In this way, we can use persistent delivery and keep all our failed messages inside a DeadLetter Queue, and from this queue, we can again trigger it or process it as per our requirement. This ensures guaranteed delivery because no message is lost.

Please note: In the above demo, the DeadLetter queue (ActiveMQ.DLQ) is a default DLQ queue for all the queues, which means if the message is failed from any queue it would be moved to the same queue ActiveMQ.DLQ.

We can create a dedicated Dead Letter Queue for each queue we have, to distinguish which failed messages belong to which queue and for this, we need to replace the destinationPolicy tag of the activemq.xml file which is present inside the conf folder in the ActiveMQ folder location.

XML
 
<destinationPolicy>
    <policyMap>
      <policyEntries>
        <!-- Set the following policy on all queues using the '>' wildcard -->
        <policyEntry queue=">">
             <deadLetterStrategy>
            <!--  Using the prefix 'DLQ.' for the destination name of  DLQ  -->
               <individualDeadLetterStrategy queuePrefix="DLQ." useQueueForQueueMessages="true"/>                                      
             </deadLetterStrategy>
        </policyEntry>
      </policyEntries>
    </policyMap>
  </destinationPolicy>

After making the changes in activemq.xml we need to start JMS again, and on hitting the same request from the postman, failed message is now moved to a dedicated DLQ with the name DLQ.sampleQueue1 as shown in the below image.

Dedicated DLQ - DLQ.sampleQueue1

So now we know how to implement Guaranteed delivery in the Mulesoft for JMS.

Event

Opinions expressed by DZone contributors are their own.

Related

  • Event Driven Architecture (EDA) - Optimizer or Complicator
  • Event-Driven Microservices: How Kafka and RabbitMQ Power Scalable Systems
  • Exploring Intercooler.js: Simplify AJAX With HTML Attributes
  • Streamlining Event Data in Event-Driven Ansible

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!