diff --git a/src/reference/docbook/delayer.xml b/src/reference/docbook/delayer.xml
index 0ed14b283f..9d341a7ba5 100644
--- a/src/reference/docbook/delayer.xml
+++ b/src/reference/docbook/delayer.xml
@@ -19,43 +19,94 @@
Configuring Delayer
- The <delayer> element is used to delay the Message flow between two Message Channels.
- As with the other endpoints, you can provide the "input-channel" and "output-channel" attributes,
- but the delayer also requires at least the 'default-delay' attribute with the number of milliseconds
- that each Message should be delayed.
- ]]>
+ The <delayer> element is used to delay the Message flow between two Message Channels.
+ As with the other endpoints, you can provide the 'input-channel' and 'output-channel' attributes,
+ but the delayer also has 'default-delay' and 'delay-header-name' attributes that are used to
+ determine the number of milliseconds
+ that each Message should be delayed. The following delays all messages by 3 seconds:
+ ]]>
If you need per-Message determination of the delay, then you can also provide the name of a header
- within the 'delay-header-name' attribute:
- ]]>
In the example above the 3 second delay would only apply in the case that the header value is
not present for a given inbound Message. If you only want to apply a delay to Messages that have
- an explicit header value, then you can set the 'default-delay' to 0. For any Message that has a
- delay of 0 (or less), the Message will be sent directly. In fact, if there is not a positive delay
+ an explicit header value, then you can set the 'default-delay' to 0 or don't use it at all (by default it is 0).
+ For any Message that has a delay of 0 (or less), the Message will be sent directly. In fact, if there is not a positive delay
value for a Message, it will be sent to the output channel on the calling Thread.
- The delay handler actually supports header values that represent an interval in milliseconds (any
+ The delay handler supports header values that represent an interval in milliseconds (any
Object whose toString() method produces a value that can be parsed into a
Long) as well as java.util.Date instances representing an absolute time.
- In the former case, the milliseconds will be counted from the current time (e.g. a value of 5000
- would delay the Message for at least 5 seconds from the time it is received by the Delayer). In
- the latter case, with an actual Date instance, the Message will not be released until that Date
+ In the first case, the milliseconds will be counted from the current time (e.g. a value of 5000
+ would delay the Message for at least 5 seconds from the time it is received by the Delayer).
+ With a Date instance, the Message will not be released until that Date
occurs. In either case, a value that equates to a non-positive delay, or a Date in the past, will
- not result in any delay. Instead, it will be sent directly to the output channel in the original
- sender's Thread.
+ not result in any delay. Instead, it will be sent directly to the output channel on the original
+ sender's Thread. If the header is not a Date, and can not be parsed as a Long, the default
+ delay (if any) will be applied.
The delayer delegates to an instance of Spring's TaskScheduler abstraction.
- The default scheduler used by the delayer is a ThreadPoolTaskScheduler instance with a pool size of 1.
+ The default scheduler used by the delayer is the ThreadPoolTaskScheduler instance
+ provided by Spring Integration on startup: .
If you want to delegate to a different scheduler, you can provide a reference through the delayer element's
'scheduler' attribute:
-
- ]]>
+ ]]>
+
+ If you configure an external ThreadPoolTaskScheduler
+ you can set on this scheduler property waitForTasksToCompleteOnShutdown = true.
+ It allows successful completion of 'delay' tasks, which already in the execution state (releasing the Message),
+ when the application is shutdown. Before Spring Integration 2.2 this property was available on
+ the <delayer> element, because DelayHandler could create its own
+ scheduler on the background. Since 2.2 delayer requires an external scheduler
+ instance and waitForTasksToCompleteOnShutdown was deleted; you should use the scheduler's own configuration.
+
+
+ Also keep in mind ThreadPoolTaskScheduler has a property errorHandler which
+ can be injected with some implementation of org.springframework.util.ErrorHandler.
+ This handler allows to process an Exception from the thread of the scheduled task sending
+ the delayed message.
+ By default it uses an org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler
+ and you will see a stack trace in the logs. You might want to consider using an
+ org.springframework.integration.channel.MessagePublishingErrorHandler,
+ which sends an ErrorMessage into an error-channel, either from the failed Message's header or
+ into the default error-channel.
+
+
+ Delayer and Message Store
+
+ The DelayHandler persists delayed Messages into the Message Group in the provided
+ MessageStore. (The 'groupId' is based on required 'id' attribute of <delayer> element.)
+ A delayed message is removed from the MessageStore by the scheduled task just before
+ the DelayHandler sends the Message to the output-channel. If the provided
+ MessageStore is persistent (e.g. JdbcMessageStore) it provides
+ the ability to not lose Messages on the application shutdown. After application startup, the
+ DelayHandler reads Messages from its Message Group in the MessageStore
+ and reschedules them with a delay based on the original arrival time of the Message (if the delay is numeric). For messages
+ where the delay header was a Date, that is used when rescheduling.
+ If a delayed Message remained in the MessageStore more
+ than its 'delay', it will be sent immediately after startup.
+
+
+ The DelayHandler can be exported as a JMX MBean
+ with managed operations getDelayedMessageCount and reschedulePersistedMessages,
+ which allows the rescheduling of delayed persisted Messages at runtime, for example, if the
+ TaskScheduler has previously been stopped. These operations can be invoked via a Control Bus command:
+ delayerReschedulingMessage = MessageBuilder.withPayload("@'delayer.handler'.reschedulePersistedMessages()").build();
+ controlBusChannel.send(delayerReschedulingMessage);]]>
+
+
+ For more information regarding the Message Store, JMX and the Control Bus, please read .
+
+