INT-789, Added documentation around global channel interceptors.

This commit is contained in:
Oleg Zhurakousky
2010-05-08 04:26:35 +00:00
parent 8c22f5c749
commit 831c01d16b
2 changed files with 74 additions and 0 deletions

View File

@@ -70,6 +70,46 @@
values. You could obtain the same result by implementing a MessageHandler that did the header modifications
and wiring that as a bean.
</para>
<para>
Some time you need to make a nested call to another chain from within the chain and then come
back and continue execution within the original chain.
To accomplish this you can utilize Messaging Gateway by including light-configuration via &lt;gateway&gt; element.
For example:
<programlisting language="xml"><![CDATA[ <si:chain id="main-chain" input-channel="inputA" output-channel="inputB">
<si:header-enricher>
<si:header name="name" value="Many" />
</si:header-enricher>
<si:service-activator>
<bean class="org.foo.SampleService" />
</si:service-activator>
<si:gateway request-channel="inputC"/>  
</si:chain>
<si:chain id="nested-chain-a" input-channel="inputC">
<si:header-enricher>
<si:header name="name" value="Moe" />
</si:header-enricher>
<si:gateway request-channel="inputD"/> 
<si:service-activator>
<bean class="org.foo.SampleService" />
</si:service-activator>
</si:chain>
<si:chain id="nested-chain-b" input-channel="inputD">
<si:header-enricher>
<si:header name="name" value="Jack" />
</si:header-enricher>
<si:service-activator>
<bean class="org.foo.SampleService" />
</si:service-activator>
</si:chain>]]></programlisting>
In the above example the <emphasis>nested-chain-a</emphasis> will be called at the end of <emphasis>main-chain</emphasis> processing by the 'gateway' element
configured there. While in <emphasis>nested-chain-a</emphasis> a call to a <emphasis>nested-chain-b</emphasis> will be made after header enrichment and then it will
come back to finish execution in <emphasis>nested-chain-b</emphasis> finally getting back to the <emphasis>main-chain</emphasis>.
When light version of &lt;gateway&gt; element is defined in the chain SI will construct an instance <classname>SimpleMessagingGateway</classname>
(no need to provide 'service-interface' configuration) which will take the message in its current state and will place it on the channel defined via 'request-channel' attribute.
Upon processing <classname>Message</classname> will be returned to the gateway and continue its journey within the current chain.
</para>
</section>
</chapter>

View File

@@ -523,6 +523,40 @@ public Message<?> receive(final PollableChannel<?> channel) { ... }]]></programl
usually provide common behavior that can be reused across multiple channels.
</para>
</section>
<section id="global-channel-configuration-interceptors">
<title>Global Channel Interceptor Configuration</title>
<para>
Channel Interceptors allow you for a clean and concise way of applying cross-cutting behavior per individual channel.
But what if the same behavior should be applied on multiple channels, configuring the same set of interceptors for
each channel <emphasis>would not be</emphasis> the most efficient way. The better way would be to configure interceptors globally and apply
them on multiple channels in one shot. Spring Integration provides capabilities to configure <emphasis>Global Interceptor Chains</emphasis>
and apply them on multiple channels.
Look at the example below:
<programlisting language="xml"><![CDATA[<int:channel-interceptor-chain channel-name-pattern="input*, bar*, foo" order="3">
<bean class="foo.barSampleInterceptor"/>
<ref bean="someOtherInterceptor"/>
</int:channel-interceptor-chain>]]></programlisting>
&lt;channel-interceptor-chain&gt; element will assemble the chain of interceptors and will apply them on all the
channels defined in the &lt;channel-name-patter&gt; attribute. In the above case the two interceptors that are defined
within the chain are going to be applied on 'foo' channel and all other channels that begin with 'bar' and 'input'.
The &lt;order&gt; attribute allows you to manage the place where this interceptor chain will be injected.
For example, channel 'inputChannel' could have individual interceptors configured locally (see below):
<programlisting language="xml"><![CDATA[<int:channel id="inputChannel"> 
<int:interceptors>
<int:wire-tap channel="logger"/> 
</int:interceptors>
</int:channel>]]></programlisting>
The reasonable question would be where interceptors defined by <emphasis>channel-interceptor-cahin</emphasis> should be injected
in relation to the existing one(s) (configured locally or through other global chains)? Current implementation provides
a very simple and clever mechanism of handling this. Positive number in the <emphasis>order</emphasis> attribute will ensure interceptor injection
after existing interceptors and negative number will ensure that such interceptors injected before.
This means that in the above example interceptors configured in global interceptor chain would be injected after
'wire-tap' interceptor configured locally. If there was another global chain with matching <emphasis>channel-name-pattern</emphasis> the
order between the interceptors defined in two chains would be determined based on who's got the higher or lower
value in <emphasis>order</emphasis> attribute.
</para>
</section>
<section id="channel-wiretap">
<title>Wire Tap</title>