Configuring message redelivery on JBoss – WildFly

In this tutorial we will discuss about the effect of using PERSISTENT or NON_PERSISTENT message delivery on JBoss EAP 6/7 or WildFly.

By default, if you are sending a JMS message without any parameter, the PERSISTENT mode will be used:

public void sendMessage() {

	try {

	    MessageProducer producer = session.createProducer(queue);
	    TextMessage message = session.createTextMessage("my message");

	} catch (Exception exc) {


The PERSISTENT delivery mode, the default, instructs the JMS provider to take extra care to ensure that a message is not lost in transit in case of a JMS provider failure. A message sent to a Queue with this delivery mode is logged to stable storage when it is sent.

Let’s see what’s the impact of PERSISTENT mode in practice:

1) If the server crashes before the message is delivered to Consumers (e.g an MDB Consumer is not available), then the message will be counted in the “message-count” and eventually delivered when the Queue Consumer returns.

standalone@localhost:9999 /] /subsystem=messaging/hornetq-server=default/jms-queue=exampleQueue:read-resource(include-runtime=true)
    "outcome" => "success",
    "result" => {
        "consumer-count" => 0,
        "dead-letter-address" => "jms.queue.DLQ",
        "delivering-count" => 0,
        "durable" => true,
        "entries" => ["java:jboss/jms/queue/exampleQueue"],
        "expiry-address" => "jms.queue.ExpiryQueue",
        "message-count" => 1L,
        "messages-added" => 1L,
        "paused" => false,
        "queue-address" => "jms.queue.exampleQueue",
        "scheduled-count" => 0L,
        "selector" => undefined,
        "temporary" => false

2) If a failure happens within the MDB onMessage method, the server will re-attempt delivery, provided that the Exception raised was a RuntimeException (or an Exception derived from it).

Under CMT, if a RuntimeException (or an Exception derived from it) is thrown by the MDB in the onMessage method, the container rolls back the transaction and the message is redelivered. At this point the specific settings of JBoss/WildFly take place

By default EAP 6/7 and WildFly will redelivery the message based on the redelivery-delay timeout for the number of attempts specified by max-delivery-attempts. The default setting of redelivery-delay is 0 which means that an attempt to redeliver the message will be done immediately. If the number of max-delivery-attempts is reached, then the message is sent to the DLQ, as seen by the following log:

14:52:56,292 WARN  [org.hornetq.core.server] (Thread-25 (HornetQ-server-HornetQServerImpl::serverUUID=45d7c2e9-d3d9-11e5-8615-87a971596f0b-1717247)) HQ222149: Message Reference[221]:RELIABLE:ServerMessage[messageID=221,userID=5a4848c8-d3eb-11e5-bdd6-f549e06540f0,priority=4, bodySize=1500,expiration=0, durable=true, address=jms.queue.exampleQueue,properties=TypedProperties[__HQ_CID=b85c5e80-d3e9-11e5-bdd6-f549e06540f0]]@1665726767 has reached maximum delivery attempts, sending it to Dead Letter Address jms.queue.DLQ from jms.queue.exampleQueue

Messages sent with NON-PERSISTENT mode

A JMS message can be sent with the NON_PERSISTENT mode as follows:

MessageProducer producer = session.createProducer(queue);
TextMessage message = session.createTextMessage("my message");
producer.send(message, DeliveryMode.NON_PERSISTENT,3, 0);

The impact of using the NON_PERSISTENT mode are the following ones:

1) If the consumer is not available at the time the message is pushed to the Queue, it will be delivered, provide no server restart happens. This is obvious since the message is held in memory not on a storage

2) Because of the rolled back transaction, no redelivery will take place in case a Runtime Exception will be thrown.

A even more restrictive scenario is in case you provide a time to live to a NON_PERSISTENT message:

producer.send(message, DeliveryMode.NON_PERSISTENT,3, 0,5000);

In this case, the message will expiry after 5000ms, hence if the Consumer does not connect within 5 seconds, the message will be lost.