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.ApplicationContextAware, org.springframework.context.ApplicationListener<org.springframework.context.event.ContextRefreshedEvent>, org.springframework.core.Ordered, Orderable, MessageHandler, MessageProducer, DelayHandlerManagement, TrackableComponent, NamedComponent

@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 result of evaluation delayExpression 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 delayExpression property is configured, that evaluation result value will take precedence over the handler's defaultDelay value. The actual evaluation result 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<Advice> to advise DelayHandler.ReleaseMessageHandler proxy.
 void setDelayExpression(org.springframework.expression.Expression delayExpression)
          Specify the Expression that should be checked for a delay period (in milliseconds) or a Date to delay until.
 void setDelayHeaderName(java.lang.String delayHeaderName)
          Deprecated. in favor of delayExpression
 void setIgnoreExpressionFailures(boolean ignoreExpressionFailures)
          Specify whether Exceptions thrown by delayExpression evaluation should be ignored (only logged).
 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
doInvokeAdvisedRequestHandler, getMessagingTemplate, handleMessageInternal, hasAdviceChain, 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, getApplicationContextId, getBeanFactory, getComponentName, getConversionService, getTaskScheduler, setApplicationContext, 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.support.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 delayExpression property has been provided, the default delay will be applied to all Messages. If a delay should only be applied to Messages with evaluation result from


setDelayHeaderName

@Deprecated
public void setDelayHeaderName(java.lang.String delayHeaderName)
Deprecated. in favor of delayExpression

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.


setDelayExpression

public void setDelayExpression(org.springframework.expression.Expression delayExpression)
Specify the Expression that should be checked for a delay period (in milliseconds) or a Date to delay until. If this property is set, the result of the expression evaluation will take precedence over this handler's default delay.


setIgnoreExpressionFailures

public void setIgnoreExpressionFailures(boolean ignoreExpressionFailures)
Specify whether Exceptions thrown by delayExpression evaluation should be ignored (only logged). In this case case the delayer will fall back to the to the defaultDelay. If this property is specified as false, any delayExpression evaluation Exception will be thrown to the caller without falling back to the to the defaultDelay. Default is true.

See Also:
determineDelayForMessage(org.springframework.integration.Message)

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<Advice> 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