Spring Integration

org.springframework.integration.handler
Class DelayHandler

java.lang.Object
  extended by org.springframework.integration.context.IntegrationObjectSupport
      extended by org.springframework.integration.handler.AbstractMessageHandler
          extended by org.springframework.integration.handler.AbstractReplyProducingMessageHandler
              extended by org.springframework.integration.handler.DelayHandler
All Implemented Interfaces:
java.util.EventListener, org.springframework.beans.factory.Aware, org.springframework.beans.factory.BeanClassLoaderAware, org.springframework.beans.factory.BeanFactoryAware, org.springframework.beans.factory.BeanNameAware, org.springframework.beans.factory.InitializingBean, org.springframework.context.ApplicationListener<org.springframework.context.event.ContextRefreshedEvent>, org.springframework.core.Ordered, NamedComponent, Orderable, MessageHandler, MessageProducer, DelayHandlerManagement, TrackableComponent

@ManagedResource
public class DelayHandler
extends AbstractReplyProducingMessageHandler
implements DelayHandlerManagement, org.springframework.context.ApplicationListener<org.springframework.context.event.ContextRefreshedEvent>

A MessageHandler that is capable of delaying the continuation of a Message flow based on the presence of a delay header on an inbound Message or a default delay value configured on this handler. Note that the continuation of the flow is delegated to a TaskScheduler, and therefore, the calling thread does not block. The advantage of this approach is that many delays can be managed concurrently, even very long delays, without producing a buildup of blocked Threads.

One thing to keep in mind, however, is that any active transactional context will not propagate from the original sender to the eventual recipient. This is a side-effect of passing the Message to the output channel after the delay with a different Thread in control.

When this handler's 'delayHeaderName' property is configured, that value, if present on a Message, will take precedence over the handler's 'defaultDelay' value. The actual header value may be a long, a String that can be parsed as a long, or a Date. If it is a long, it will be interpreted as the length of time to delay in milliseconds counting from the current time (e.g. a value of 5000 indicates that the Message can be released as soon as five seconds from the current time). If the value is a Date, it will be delayed at least until that Date occurs (i.e. the delay in that case is equivalent to headerDate.getTime() - new Date().getTime()).

Since:
1.0.3
Author:
Mark Fisher, Artem Bilan

Nested Class Summary
static class DelayHandler.DelayedMessageWrapper
           
 
Nested classes/interfaces inherited from class org.springframework.integration.handler.AbstractReplyProducingMessageHandler
AbstractReplyProducingMessageHandler.RequestHandler
 
Field Summary
 
Fields inherited from class org.springframework.integration.context.IntegrationObjectSupport
logger
 
Fields inherited from interface org.springframework.core.Ordered
HIGHEST_PRECEDENCE, LOWEST_PRECEDENCE
 
Constructor Summary
DelayHandler(java.lang.String messageGroupId)
          Create a DelayHandler with the given 'messageGroupId' that is used as 'key' for MessageGroup to store delayed Messages in the MessageGroupStore.
DelayHandler(java.lang.String messageGroupId, org.springframework.scheduling.TaskScheduler taskScheduler)
          Create a DelayHandler with the given default delay.
 
Method Summary
 java.lang.String getComponentType()
          Subclasses may implement this method to provide component type information.
 int getDelayedMessageCount()
           
protected  java.lang.Object handleRequestMessage(Message<?> requestMessage)
          Checks if 'requestMessage' wasn't delayed before (releaseMessageAfterDelay(org.springframework.integration.Message, long) and DelayHandler.DelayedMessageWrapper).
 void onApplicationEvent(org.springframework.context.event.ContextRefreshedEvent event)
          Handles ContextRefreshedEvent to invoke reschedulePersistedMessages() as late as possible after application context startup.
protected  void onInit()
          Subclasses may implement this for initialization logic.
 void reschedulePersistedMessages()
          Used for reading persisted Messages in the 'messageStore' to reschedule them e.g.
 void setDefaultDelay(long defaultDelay)
          Set the default delay in milliseconds.
 void setDelayedAdviceChain(java.util.List<org.aopalliance.aop.Advice> delayedAdviceChain)
          Specify the List to advise DelayHandler.ReleaseMessageHandler proxy.
 void setDelayHeaderName(java.lang.String delayHeaderName)
          Specify the name of the header that should be checked for a delay period (in milliseconds) or a Date to delay until.
 void setMessageStore(MessageGroupStore messageStore)
          Specify the MessageGroupStore that should be used to store Messages while awaiting the delay.
 
Methods inherited from class org.springframework.integration.handler.AbstractReplyProducingMessageHandler
getMessagingTemplate, handleMessageInternal, setAdviceChain, setBeanClassLoader, setChannelResolver, setOutputChannel, setRequiresReply, setSendTimeout, shouldCopyRequestHeaders
 
Methods inherited from class org.springframework.integration.handler.AbstractMessageHandler
getOrder, handleMessage, setOrder, setShouldTrack
 
Methods inherited from class org.springframework.integration.context.IntegrationObjectSupport
afterPropertiesSet, getBeanFactory, getComponentName, getConversionService, getTaskScheduler, setBeanFactory, setBeanName, setComponentName, setConversionService, setTaskScheduler, toString
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 
Methods inherited from interface org.springframework.integration.context.NamedComponent
getComponentName
 

Constructor Detail

DelayHandler

public DelayHandler(java.lang.String messageGroupId)
Create a DelayHandler with the given 'messageGroupId' that is used as 'key' for MessageGroup to store delayed Messages in the MessageGroupStore. The sending of Messages after the delay will be handled by registered in the ApplicationContext default ThreadPoolTaskScheduler.

See Also:
IntegrationObjectSupport.getTaskScheduler()

DelayHandler

public DelayHandler(java.lang.String messageGroupId,
                    org.springframework.scheduling.TaskScheduler taskScheduler)
Create a DelayHandler with the given default delay. The sending of Messages after the delay will be handled by the provided TaskScheduler.

Method Detail

setDefaultDelay

public void setDefaultDelay(long defaultDelay)
Set the default delay in milliseconds. If no 'delayHeaderName' property has been provided, the default delay will be applied to all Messages. If a delay should only be applied to Messages with a header, then set this value to 0.


setDelayHeaderName

public void setDelayHeaderName(java.lang.String delayHeaderName)
Specify the name of the header that should be checked for a delay period (in milliseconds) or a Date to delay until. If this property is set, any such header value will take precedence over this handler's default delay.


setMessageStore

public void setMessageStore(MessageGroupStore messageStore)
Specify the MessageGroupStore that should be used to store Messages while awaiting the delay.


setDelayedAdviceChain

public void setDelayedAdviceChain(java.util.List<org.aopalliance.aop.Advice> delayedAdviceChain)
Specify the List to advise DelayHandler.ReleaseMessageHandler proxy. Usually used to add transactions to delayed messages retrieved from a transactional message store.

See Also:
createReleaseMessageTask()

getComponentType

public java.lang.String getComponentType()
Description copied from class: IntegrationObjectSupport
Subclasses may implement this method to provide component type information.

Specified by:
getComponentType in interface NamedComponent
Overrides:
getComponentType in class AbstractMessageHandler

onInit

protected void onInit()
Description copied from class: IntegrationObjectSupport
Subclasses may implement this for initialization logic.

Overrides:
onInit in class AbstractReplyProducingMessageHandler

handleRequestMessage

protected java.lang.Object handleRequestMessage(Message<?> requestMessage)
Checks if 'requestMessage' wasn't delayed before (releaseMessageAfterDelay(org.springframework.integration.Message, long) and DelayHandler.DelayedMessageWrapper). Than determine 'delay' for 'requestMessage' (determineDelayForMessage(org.springframework.integration.Message)) and if delay > 0 schedules 'releaseMessage' task after 'delay'.

Specified by:
handleRequestMessage in class AbstractReplyProducingMessageHandler
Parameters:
requestMessage - - the Message which may be delayed.
Returns:
- null if 'requestMessage' is delayed, otherwise - 'payload' from 'requestMessage'.
See Also:
releaseMessage(org.springframework.integration.Message)

getDelayedMessageCount

public int getDelayedMessageCount()
Specified by:
getDelayedMessageCount in interface DelayHandlerManagement

reschedulePersistedMessages

public void reschedulePersistedMessages()
Used for reading persisted Messages in the 'messageStore' to reschedule them e.g. upon application restart. The logic is based on iteration over 'messageGroup.getMessages()' and schedules task about 'delay' logic. This behavior is dictated by the avoidance of invocation thread overload.

Specified by:
reschedulePersistedMessages in interface DelayHandlerManagement

onApplicationEvent

public void onApplicationEvent(org.springframework.context.event.ContextRefreshedEvent event)
Handles ContextRefreshedEvent to invoke reschedulePersistedMessages() as late as possible after application context startup. Also it checks initialized to ignore other ContextRefreshedEvents which may be published in the 'parent-child' contexts, e.g. in the Spring-MVC applications.

Specified by:
onApplicationEvent in interface org.springframework.context.ApplicationListener<org.springframework.context.event.ContextRefreshedEvent>
Parameters:
event - - ContextRefreshedEvent which occurs after Application context is completely initialized.
See Also:
reschedulePersistedMessages()

Spring Integration