{"id":60956,"date":"2024-03-29T22:03:12","date_gmt":"2024-03-29T16:33:12","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=60956"},"modified":"2024-03-29T22:03:12","modified_gmt":"2024-03-29T16:33:12","slug":"managing-dead-letter-queuesdlq-in-rabbitmq-with-java-spring-boot","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/managing-dead-letter-queuesdlq-in-rabbitmq-with-java-spring-boot\/","title":{"rendered":"Managing Dead Letter Queues(DLQ) in RabbitMQ with Java Spring Boot"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p><span style=\"font-weight: 400;\">Rabbit MQ is an open source message broker mainly used as a middle-ware(or broker) to communicate among the micro-services. Micro-service which produces or sends a message to the broker is termed as \u201cProducer\u201d whereas the service which receives the message is known as \u201cConsumer\u201d.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">One can imagine the flow of communication as: <\/span><b>Producer \u2014&gt; Message Broker \u2014&gt; Consumer.<\/b><b><br \/>\n<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Message Broker comprises two key parts:<\/span><span style=\"font-weight: 400;\"><br \/>\n<\/span><span style=\"font-weight: 400;\">1) Exchange<\/span><span style=\"font-weight: 400;\"><br \/>\n<\/span><span style=\"font-weight: 400;\">2) Queue<\/span><span style=\"font-weight: 400;\"><br \/>\n<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Messages by the producer are sent to the exchange first and then it is routed to the queue with the help of a routing key. This phenomenon is known as <\/span><b>\u201cBinding\u201d<\/b><span style=\"font-weight: 400;\">. And, then the consumer consumes the message from the queue.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Sometimes, consumers fail to consume and acknowledge the message from the queue due to various factors, such as invalid format, processing failure or routing failure. In such cases, Dead Letter Queues (DLQ) are employed to capture these messages, allowing for analysis, troubleshooting, and potential reprocessing without disrupting the normal flow of messages.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"> For each queue, we can have a separate dead letter queue and exchange. It helps in maintaining system integrity, identifying issues and facilitating proper error handling and resolution in distributed systems:<\/span><span style=\"font-weight: 400;\"><br \/>\n<\/span><i><\/i><\/p>\n<p><strong><i>1) <\/i><i>Error Handling and Retry Mechanism: <\/i><\/strong><span style=\"font-weight: 400;\">This ensures the system does not lose critical messages due to processing failure.<\/span><span style=\"font-weight: 400;\"><br \/>\n<\/span><\/p>\n<p><strong>2) <i>Visibility and Debugging: <\/i><\/strong><span style=\"font-weight: 400;\">It allows the developer or admin to easily identify and inspect messages that failed to be processed.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><br \/>\n<\/span><strong>3) <\/strong><i><span style=\"font-weight: 400;\"><strong>Reprocessing and Recovery:<\/strong> <\/span><\/i><span style=\"font-weight: 400;\">Messages in the DQ can be manually or automatically reprocessed, allowing the system to recover from processing failure and data consistency.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><br \/>\n<\/span><strong>4) <\/strong><i><span style=\"font-weight: 400;\"><strong>Auditing and Compliance:<\/strong> <\/span><\/i><span style=\"font-weight: 400;\">Storing failed messages provides the records of all the messages that are accounted for, thus contributing to overall integrity and transparency of the system.<\/span><span style=\"font-weight: 400;\"><br \/>\n<\/span><\/p>\n<p><span style=\"font-weight: 400;\">We can create Dead Letter Exchanges and Queues over the RabbitMQ UI Management and also through the code in Java with Spring Boot using \u201c<\/span><b>Spring for Rabbit MQ<\/b><span style=\"font-weight: 400;\">\u201d dependency. Below is the Maven dependency code of RabbitMQ:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">dependencies {<\/span><span style=\"font-weight: 400;\">\r\n<\/span> <span style=\"font-weight: 400;\">implementation 'org.springframework.boot:spring-boot-starter-amqp'<\/span><span style=\"font-weight: 400;\">\r\n<\/span> <span style=\"font-weight: 400;\">testImplementation 'org.springframework.amqp:spring-rabbit-test'<\/span><span style=\"font-weight: 400;\">\r\n<\/span><span style=\"font-weight: 400;\">}<\/span><span style=\"font-weight: 400;\">\u00a0\u00a0<\/span><\/pre>\n<p><span style=\"font-weight: 400;\">Below is DLQ configuration implementation in java with spring boot:<\/span><span style=\"font-weight: 400;\"><br \/>\n<\/span><strong>1) Define a bean of Dead Letter Exchange(dlx)<br \/>\n2) Define a bean of Dead Letter Queue(dlq)<br \/>\n3) Bind the dlx and dlq<br \/>\n4) Associate the above dlx to the queue you are using .<\/strong><\/p>\n<p>a) Parameter variables of queue, exchange and routing keys: We define the instance variable and assign the values using \u201c@Value\u201d annotation by the help of key-value pair defined in application properties file.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-60976 size-full\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-10-40-05-1.png\" alt=\"\" width=\"447\" height=\"219\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-10-40-05-1.png 447w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-10-40-05-1-300x147.png 300w\" sizes=\"(max-width: 447px) 100vw, 447px\" \/><br \/>\n<span style=\"font-weight: 400;\"><br \/>\nb) Values to the above fields assigned in the application properties file in key-value format.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-60978 size-full\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-29-06.png\" alt=\"\" width=\"588\" height=\"184\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-29-06.png 588w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-29-06-300x94.png 300w\" sizes=\"(max-width: 588px) 100vw, 588px\" \/><br \/>\n<\/span><span style=\"font-weight: 400;\"><br \/>\nc) Configuration of dead letter exchange and queue in configuration file.<\/p>\n<p><\/span><span style=\"font-weight: 400;\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-60982 size-full\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-36-56.png\" alt=\"\" width=\"672\" height=\"183\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-36-56.png 672w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-36-56-300x82.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-36-56-624x170.png 624w\" sizes=\"(max-width: 672px) 100vw, 672px\" \/><br \/>\n<\/span><\/p>\n<p><span style=\"font-weight: 400;\">d) The above code creates the bean for the queue for which we are setting up the DLQ. With the help of \u201cwith Argument\u201d method we can specify the exchange name and its routing key to establish the connection between the main Queue and dead letter exchange.<br \/>\n<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-60983 size-full\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-38-11.png\" alt=\"\" width=\"680\" height=\"128\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-38-11.png 680w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-38-11-300x56.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-38-11-624x117.png 624w\" sizes=\"(max-width: 680px) 100vw, 680px\" \/><br \/>\n<span style=\"font-weight: 400;\"><br \/>\ne) The code creates the dead letter queue and its bean.<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-60984 size-full\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-39-19.png\" alt=\"\" width=\"680\" height=\"128\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-39-19.png 680w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-39-19-300x56.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-39-19-624x117.png 624w\" sizes=\"(max-width: 680px) 100vw, 680px\" \/><br \/>\n<span style=\"font-weight: 400;\"><br \/>\nf) Next, create the dead letter exchange and its bean.<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-60985 size-full\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-40-07.png\" alt=\"\" width=\"679\" height=\"170\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-40-07.png 679w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-40-07-300x75.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-40-07-624x156.png 624w\" sizes=\"(max-width: 679px) 100vw, 679px\" \/><br \/>\n<span style=\"font-weight: 400;\">g) Finally, bind the dead letter exchange and dead letter queue with the routing key.<\/span><span style=\"font-weight: 400;\"><br \/>\n<\/span><span style=\"font-weight: 400;\"><br \/>\n<\/span><span style=\"font-weight: 400;\">And, remember to use the below library for different classes, interface and annotations of rabbitmq used in the config class:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">import org.springframework.amqp.core.Binding;\r\n<\/span><span style=\"font-weight: 400;\">import org.springframework.amqp.core.BindingBuilder;\r\n<\/span><span style=\"font-weight: 400;\">import org.springframework.amqp.core.Queue;\r\n<\/span><span style=\"font-weight: 400;\">import org.springframework.amqp.core.QueueBuilder;\r\n<\/span><span style=\"font-weight: 400;\">import org.springframework.amqp.core.TopicExchange;\r\n<\/span><span style=\"font-weight: 400;\">import org.springframework.beans.factory.annotation.Value;\r\n<\/span><span style=\"font-weight: 400;\">import org.springframework.context.annotation.Bean;\r\n<\/span><span style=\"font-weight: 400;\">import org.springframework.context.annotation.Configuration;<\/span><\/pre>\n<p><span style=\"font-weight: 400;\"><br \/>\n<\/span><span style=\"font-weight: 400;\">Failed messages will be routed to the dead letter queue. Additionally, one can also specify the expiration time while sending the message and set the TTL(time-to-live) while creating the bean of the queue, thus after that expiration time if the message is not consumed, it will be routed to the dead letter queue. You could use the help of below code to implement it.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">1)While sending message:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">rabbitTemplate.convertAndSend(MAIN_QUEUE, message, messagePostProcessor -&gt; {<\/span><span style=\"font-weight: 400;\">\r\n<\/span><span style=\"font-weight: 400;\">messagePostProcessor.getMessageProperties().setExpiration(\u201c60000\u201d); \/\/ TTL in milliseconds (e.g., 60 seconds)<\/span><span style=\"font-weight: 400;\">\r\n<\/span><span style=\"font-weight: 400;\">return messagePostProcessor;<\/span><span style=\"font-weight: 400;\">\r\n<\/span><span style=\"font-weight: 400;\">});<\/span><\/pre>\n<p><span style=\"font-weight: 400;\">2) While creating bean of the queue:<\/span><span style=\"font-weight: 400;\"><br \/>\n<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">@Bean<\/span><span style=\"font-weight: 400;\">\r\n<\/span><span style=\"font-weight: 400;\">public Queue mainQueue() {<\/span><span style=\"font-weight: 400;\">\r\n<\/span><span style=\"font-weight: 400;\">return QueueBuilder.durable(MAIN_QUEUE)<\/span><span style=\"font-weight: 400;\">\r\n<\/span><span style=\"font-weight: 400;\">.ttl(60000) \/\/ TTL in milliseconds (e.g., 60 seconds)<\/span><span style=\"font-weight: 400;\">\r\n<\/span><span style=\"font-weight: 400;\">.build();<\/span><span style=\"font-weight: 400;\">\r\n<\/span><span style=\"font-weight: 400;\">}<\/span><span style=\"font-weight: 400;\">\r\n<\/span><\/pre>\n<p><span style=\"font-weight: 400;\">At the consumer level, one needs to handle the failed processing messages. One of the ways can be as below:<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-60973 size-full\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-02-45.png\" alt=\"\" width=\"945\" height=\"319\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-02-45.png 945w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-02-45-300x101.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-02-45-768x259.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-from-2024-03-27-17-02-45-624x211.png 624w\" sizes=\"(max-width: 945px) 100vw, 945px\" \/><span style=\"font-weight: 400;\"><br \/>\n<\/span><span style=\"font-weight: 400;\"><br \/>\nI hope you enjoyed the article on Dead Letter Queue in Rabbit MQ.<br \/>\n<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Thank you! ?<\/span><\/p>\n<p><code><\/code><\/p>\n<div class=\"ap-custom-wrapper\"><\/div><!--ap-custom-wrapper-->","protected":false},"excerpt":{"rendered":"<p>Introduction Rabbit MQ is an open source message broker mainly used as a middle-ware(or broker) to communicate among the micro-services. Micro-service which produces or sends a message to the broker is termed as \u201cProducer\u201d whereas the service which receives the message is known as \u201cConsumer\u201d. One can imagine the flow of communication as: Producer \u2014&gt; [&hellip;]<\/p>\n","protected":false},"author":1679,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":866},"categories":[446,1994,1],"tags":[5732,1077,5750],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/60956"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1679"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=60956"}],"version-history":[{"count":5,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/60956\/revisions"}],"predecessor-version":[{"id":61075,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/60956\/revisions\/61075"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=60956"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=60956"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=60956"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}