INT-2243: Delayer: Add 'expression' Support
Previously, the `<delayer>` provided a `delay-header-name` attribute. In complex cases there was need to precede it with `<header-enricher>`. * Add support for an 'expression' attribute and sub-element * Deprecate `delay-header-name` * Make `DelayHandler.DelayedMessageWrapper` *public* to allow access for Messages in the Store * Add tests * Add 'What's new' section * Polishing Delayer's doc regarding new abilities JIRA: https://jira.springsource.org/browse/INT-2243, https://jira.springsource.org/browse/INT-3049 INT-2243: ban delay-header-name with expression INT-2243 Polishing INT-2243: fall-back to default on Eval Exception INT-2243: DelayedMessageWrapper refactoring * Make `DelayedMessageWrapper` Spring Data Mongo mapping compatible. In terms of Spring Data - add Persistence Constructor INT-2243 add 'ignore-expression-failures' support * Add `ignore-expression-failures` to the `<delayer>` * Add tests for `ignore-expression-failures` * Add a note to the RM * Describe SpEL side-effects for `DelayHandler` Doc Polishing
This commit is contained in:
committed by
Gary Russell
parent
67fd4a5a60
commit
afe56ca6d5
@@ -21,33 +21,56 @@
|
||||
<para>
|
||||
The <code><delayer></code> 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:
|
||||
but the delayer also has 'default-delay' and 'expression' attributes (and 'expression' sub-element) that are used to
|
||||
determine the number of milliseconds that each Message should be delayed. The following delays all messages by 3 seconds:
|
||||
<programlisting language="xml"><![CDATA[<int:delayer id="delayer" input-channel="input"
|
||||
default-delay="3000" output-channel="output"/>]]></programlisting>
|
||||
If you need per-Message determination of the delay, then you can also provide the name of a header
|
||||
using the 'delay-header-name' attribute:
|
||||
If you need per-Message determination of the delay, then you can also provide the SpEL expression
|
||||
using the 'expression' attribute:
|
||||
<programlisting language="xml"><![CDATA[<int:delayer id="delayer" input-channel="input" output-channel="output"
|
||||
default-delay="3000" delay-header-name="delay"/>]]></programlisting>
|
||||
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 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.
|
||||
default-delay="3000" expression="headers['delay']"/>]]></programlisting>
|
||||
In the example above, the 3 second delay would only apply when the expression evaluates to
|
||||
<emphasis>null</emphasis> for a given inbound Message. If you only want to apply a delay to Messages that have
|
||||
a valid result of the expression evaluation, then you can use a 'default-delay' of 0 (the default).
|
||||
For any Message that has a delay of 0 (or less), the Message will be sent immediately, on the calling Thread.
|
||||
<tip>
|
||||
The delay handler supports header values that represent an interval in milliseconds (any
|
||||
The delay handler supports expression evaluation results that represent an interval in milliseconds (any
|
||||
Object whose <methodname>toString()</methodname> method produces a value that can be parsed into a
|
||||
Long) as well as <classname>java.util.Date</classname> instances representing an absolute time.
|
||||
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
|
||||
With a Date instance, the Message will not be released until the time represented by that Date object.
|
||||
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 on the original
|
||||
sender's Thread. If the header is not a Date, and can not be parsed as a Long, the default
|
||||
sender's Thread. If the expression evaluation result is not a Date, and can not be parsed as a Long, the default
|
||||
delay (if any) will be applied.
|
||||
</tip>
|
||||
<important>
|
||||
The expression evaluation may throw an evaluation Exception for various reasons, including an invalid
|
||||
expression, or other conditions. By default, such exceptions are ignored (logged at DEBUG level) and
|
||||
the delayer falls back to the default delay (if any). You can modify this behavior by setting the
|
||||
<code>ignore-expression-failures</code> attribute.
|
||||
By default this attribute is set to <code>true</code> and the Delayer behavior is as described above.
|
||||
However, if you wish to not ignore expression evaluation exceptions, and throw them to the delayer's caller,
|
||||
set the <code>ignore-expression-failures</code> attribute to <code>false</code>.
|
||||
</important>
|
||||
</para>
|
||||
<tip>
|
||||
Notice in the example above that the delay expression is specified as <code>headers['delay']</code>.
|
||||
This is the SpEL <classname>Indexer</classname> syntax to access a <interfacename>Map</interfacename> element
|
||||
(<classname>MessageHeaders</classname> implements <interfacename>Map</interfacename>),
|
||||
it invokes: <code>headers.get("delay")</code>. For simple map element names (that do not contain '.')
|
||||
you can also use the SpEL <emphasis>dot accessor</emphasis> syntax, where the above header expression
|
||||
can be specified as <code>headers.delay</code>. But, different results are achieved if the header is missing.
|
||||
In the first case, the expression will evaluate to <code>null</code>; the second will result in
|
||||
something like:
|
||||
<programlisting language="java"><![CDATA[ org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 8):
|
||||
Field or property 'delay' cannot be found on object of type 'org.springframework.integration.MessageHeaders']]></programlisting>
|
||||
So, if there is a possibility of the header being omitted, and you want to fall back to the default
|
||||
delay, it is generally more efficient (and recommended) to use the
|
||||
<emphasis>Indexer</emphasis> syntax instead of <emphasis>dot property accessor</emphasis> syntax, because detecting
|
||||
the null is faster than catching an exception.
|
||||
</tip>
|
||||
<para>
|
||||
The delayer delegates to an instance of Spring's <interfacename>TaskScheduler</interfacename> abstraction.
|
||||
The default scheduler used by the delayer is the <classname>ThreadPoolTaskScheduler</classname> instance
|
||||
@@ -55,7 +78,7 @@
|
||||
If you want to delegate to a different scheduler, you can provide a reference through the delayer element's
|
||||
'scheduler' attribute:
|
||||
<programlisting language="xml"><![CDATA[<int:delayer id="delayer" input-channel="input" output-channel="output"
|
||||
delay-header-name="delay"
|
||||
expression="headers.delay"
|
||||
scheduler="exampleTaskScheduler"/>
|
||||
|
||||
<task:scheduler id="exampleTaskScheduler" pool-size="3"/>]]></programlisting>
|
||||
@@ -106,7 +129,7 @@
|
||||
<interfacename>org.aopalliance.aop.Advice</interfacename> implementation within the <code><advice-chain></code>.
|
||||
A sample configuration of the <code><delayer></code> may look like this:
|
||||
<programlisting language="xml"><![CDATA[<int:delayer id="delayer" input-channel="input" output-channel="output"
|
||||
delay-header-name="delay"
|
||||
expression="headers.delay"
|
||||
message-store="jdbcMessageStore">
|
||||
<int:advice-chain>
|
||||
<beans:ref bean="customAdviceBean"/>
|
||||
|
||||
@@ -312,5 +312,19 @@
|
||||
set <code>requires-reply</code> to false.
|
||||
</important>
|
||||
</section>
|
||||
<section id="3.0-dalay-expression">
|
||||
<title>Delayer: delay expression</title>
|
||||
<para>
|
||||
Previously, the <code><delayer></code> provided a <code>delay-header-name</code> attribute
|
||||
to determine the <emphasis>delay</emphasis> value at runtime. In complex cases it was necessary
|
||||
to precede the <code><delayer></code> with a <code><header-enricher></code>.
|
||||
Spring Integration 3.0 introduced the <code>expression</code> attribute and <code>expression</code>
|
||||
sub-element for dynamic delay determination. The <code>delay-header-name</code> attribute is now deprecated
|
||||
because the header evaluation can be specified in the <code>expression</code>. In addition,
|
||||
the <code>ignore-expression-failures</code> was introduced to control the behavior when an
|
||||
expression evaluation fails.
|
||||
For more information see <xref linkend="delayer"/>.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
Reference in New Issue
Block a user