Renamed transformation.xml to transformer.xml
This commit is contained in:
@@ -1,175 +0,0 @@
|
||||
|
||||
|
||||
<section id="api-messagehandler">
|
||||
<title>MessageHandler</title>
|
||||
<para>
|
||||
So far we have seen that generic message objects are sent-to and received-from simple channel objects. Here is
|
||||
Spring Integration's callback interface for handling the <interfacename>Messages</interfacename>:
|
||||
<programlisting language="java">public interface MessageHandler {
|
||||
Message<?> handle(Message<?> message);
|
||||
}</programlisting>
|
||||
The handler plays an important role, since it is typically responsible for translating between the generic
|
||||
<interfacename>Message</interfacename> objects and the domain objects or primitive values expected by business
|
||||
components that consume the message payload. That said, developers will rarely need to implement this interface
|
||||
directly. While that option will always be available, we will soon discuss the higher-level configuration options
|
||||
including both annotation-driven techniques and XML-based configuration with convenient namespace support.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="api-messagebus">
|
||||
<title>MessageBus</title>
|
||||
<para>
|
||||
So far, you have seen that the <interfacename>PollableChannel</interfacename> provides a
|
||||
<methodname>receive()</methodname> method that returns a <interfacename>Message</interfacename>, the subscribable
|
||||
MessageChannels invoke one or more subscribers directly, and the <interfacename>MessageHandler</interfacename>
|
||||
provides a <methodname>handle()</methodname> method that accepts a <interfacename>Message</interfacename>.
|
||||
However, we have not yet discussed how messages get passed from a channel to a handler. As mentioned earlier,
|
||||
the <classname>MessageBus</classname> provides a runtime form of inversion of control, and one of the primary
|
||||
responsibilities that it assumes is connecting the channels to the handlers. It also connects MessageSources and
|
||||
MessageTargets to channels (thereby creating Channel Adapters), and it manages the scheduling of polling
|
||||
dispatchers. Ultimately, every MessageHandler should be invoked as if it is an event-driven consumer, and this
|
||||
works fine when the handler's input source is a <interfacename>SubscribableSource</interfacename>. However, the
|
||||
bus creates and manages these polling dispatchers so that even when handlers receive input from a
|
||||
<interfacename>PollableSource</interfacename>, they will still behave as event-driven consumers.
|
||||
</para>
|
||||
<para>
|
||||
The <interfacename>MessageBus</interfacename> is an example of a mediator. It performs a number of roles -
|
||||
mostly by delegating to other strategies. One of its main responsibilities is to manage registration of the
|
||||
<interfacename>MessageChannels</interfacename> and endpoints, such as <emphasis>Channel Adapters</emphasis>
|
||||
and <emphasis>Service Activators</emphasis>. It recognizes any of these instances that have been defined
|
||||
within its <interfacename>ApplicationContext</interfacename>.
|
||||
</para>
|
||||
<para>
|
||||
The message bus handles several of the concerns so that the channels, sources, targets, and Message-handling
|
||||
objects can be as simple as possible. These responsibilities include the lifecycle management of
|
||||
message endpoints, the activation of subscriptions, and the scheduling of dispatchers (including
|
||||
the configuration of thread pools). The bus coordinates all of that behavior based upon the metadata provided
|
||||
in bean definitions. Furthermore, those bean definitions may be provided via XML and/or annotations
|
||||
(we will look at examples of both configuration options shortly).
|
||||
</para>
|
||||
<para>
|
||||
The bus is responsible for activating all of its registered endpoints by connecting them to channels within
|
||||
its registry, and if necessary scheduling a poller so that the endpoint can be event-driven even when connected
|
||||
to a channel that requires polling. For example, the poller for an outbound <emphasis>Channel Adapter</emphasis>
|
||||
will poll the referenced "channel", and the poller for a <emphasis>Service Activator</emphasis> will poll the
|
||||
referenced "input-channel". If that "channel" or "input-channel" is subscribable rather than pollable, the bus
|
||||
will simply activate the subscription. The important point is that the endpoint itself does not need to know
|
||||
whether its source is pollable or subscribable.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="api-messageendpoint">
|
||||
<title>MessageEndpoint</title>
|
||||
<para>
|
||||
As described in <xref linkend="overview"/>, there are different types of Message Endpoint, such
|
||||
as the <emphasis>Channel Adapter</emphasis> (inbound or outbound) and the <emphasis>Service Activator</emphasis>.
|
||||
Spring Integration provides many other components that are also endpoints, such as Routers,
|
||||
Splitters, and Aggregators. Each endpoint may provide its own specific metadata so that the
|
||||
<classname>MessageBus</classname> can manage its connection to channels and its poller (if necessary).
|
||||
</para>
|
||||
<para>
|
||||
The scheduling metadata is provided as an implementation of the <interfacename>Schedule</interfacename> interface.
|
||||
This is an abstraction designed to allow extensibility of schedulers for messaging tasks. Currently, there are two
|
||||
implementations: <classname>PollingSchedule</classname> and <classname>CronSchedule</classname>. The former has
|
||||
a <emphasis>period</emphasis> property, and the latter has a <emphasis>cronExpression</emphasis>. The polling
|
||||
schedule may be configured based on throughput expectations and/or the type of MessageSource
|
||||
(e.g. file-system vs. JMS).
|
||||
</para>
|
||||
<para>
|
||||
While the MessageBus manages the scheduling of the pollers, it is often beneficial to have multiple task
|
||||
executors with different concurrency settings for an endpoint or group of endpoints. This provides more control
|
||||
over the number of threads available for each receive-and-handle unit of work and depending on the type of
|
||||
task executor, may also enable dynamic adjustments. When the <interfacename>MessageBus</interfacename>
|
||||
activates an endpoint, it will create and schedule the poller for that endpoint based on the endpoint's
|
||||
configuration. This will be described in more detail in <xref linkend="namespace-endpoint"/>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="api-messageselector">
|
||||
<title>MessageSelector</title>
|
||||
<para>
|
||||
As described above, each endpoint is registered with the message bus and is thereby subscribed
|
||||
to a channel. Often it is necessary to provide additional <emphasis>dynamic</emphasis> logic to
|
||||
determine what messages the endpoint should receive. The <interfacename>MessageSelector</interfacename>
|
||||
strategy interface fulfills that role.
|
||||
<programlisting language="java"><![CDATA[public interface MessageSelector {
|
||||
|
||||
boolean accept(Message<?> message);
|
||||
|
||||
}]]></programlisting>
|
||||
A <interfacename>MessageEndpoint</interfacename> can be configured with a selector (or selector-chain)
|
||||
and will only receive messages that are accepted by each selector. Even though the interface is simple
|
||||
to implement, a couple common selector implementations are provided. For example, the
|
||||
<classname>PayloadTypeSelector</classname> provides similar functionality to Datatype Channels
|
||||
(as described in <xref linkend="namespace-channel"/>) except that in this case the type-matching can be done
|
||||
by the endpoint rather than the channel.
|
||||
<programlisting language="java"><![CDATA[PayloadTypeSelector selector = new PayloadTypeSelector(String.class, Integer.class);
|
||||
assertTrue(selector.accept(new StringMessage("example")));
|
||||
assertTrue(selector.accept(new GenericMessage<Integer>(123)));
|
||||
assertFalse(selector.accept(new GenericMessage<SomeObject>(someObject)));]]></programlisting>
|
||||
Another simple but useful <interfacename>MessageSelector</interfacename> provided out-of-the-box is the
|
||||
<classname>UnexpiredMessageSelector</classname>. As the name suggests, it only accepts messages that have
|
||||
not yet expired.
|
||||
</para>
|
||||
<para>
|
||||
Essentially, using a selector provides <emphasis>reactive</emphasis> routing whereas the Datatype Channel
|
||||
and Message Router provide <emphasis>proactive</emphasis> routing. However, selectors accommodate additional
|
||||
uses. For example, a <interfacename>PollableChannel</interfacename>'s 'purge' method accepts a selector:
|
||||
<programlisting language="java">channel.purge(someSelector);</programlisting>
|
||||
There is a <classname>ChannelPurger</classname> utility class whose purge operation is a good candidate for
|
||||
Spring's JMX support:
|
||||
<programlisting language="java">ChannelPurger purger = new ChannelPurger(new ExampleMessageSelector(), channel);
|
||||
purger.purge();</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Implementations of <interfacename>MessageSelector</interfacename> might provide opportunities for reuse on
|
||||
channels in addition to endpoints. For that reason, Spring Integration provides a simple selector-wrapping
|
||||
<interfacename>ChannelInterceptor</interfacename> that accepts one or more selectors in its constructor.
|
||||
<programlisting language="java">MessageSelectingInterceptor interceptor =
|
||||
new MessageSelectingInterceptor(selector1, selector2);
|
||||
channel.addInterceptor(interceptor);</programlisting>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="api-gateway">
|
||||
<title>MessagingGateway</title>
|
||||
<para>
|
||||
Even though the <classname>MessageExchangeTemplate</classname> is fairly straightforward, it does not hide the
|
||||
details of messaging from your application code. To support working with plain Objects instead of messages,
|
||||
Spring Integration provides <classname>SimpleMessagingGateway</classname> with the following methods:
|
||||
<programlisting language="java">public void send(Object object) { ... }
|
||||
|
||||
public Object receive() { ... }
|
||||
|
||||
public Object sendAndReceive(Object object) { ... }
|
||||
|
||||
public void receiveAndForward() { ... }</programlisting>
|
||||
It enables configuration of a request and/or reply channel and delegates to an instance of the
|
||||
<interfacename>MessageMapper</interfacename> and <interfacename>MessageCreator</interfacename> strategy
|
||||
interfaces.
|
||||
<programlisting language="java">SimpleMessagingGateway gateway = new SimpleMessagingGateway();
|
||||
gateway.setRequestChannel(requestChannel);
|
||||
gateway.setReplyChannel(replyChannel);
|
||||
gateway.setMessageCreator(messageCreator);
|
||||
gateway.setMessageMapper(messageMapper);
|
||||
Object result = gateway.sendAndReceive("test");
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Working with Objects instead of Messages is an improvement. However, it would be even better to have no
|
||||
dependency on the Spring Integration API at all - including the gateway class. For that reason, Spring
|
||||
Integration also provides a <classname>GatewayProxyFactoryBean</classname> that generates a proxy for
|
||||
any interface and internally invokes the gateway methods shown above. Namespace support is also
|
||||
provided as demonstrated by the following example.
|
||||
<programlisting language="xml"><![CDATA[<gateway id="fooService"
|
||||
service-interface="org.example.FooService"
|
||||
request-channel="requestChannel"
|
||||
reply-channel="replyChannel"
|
||||
message-creator="messageCreator"
|
||||
message-mapper="messageMapper"/>]]></programlisting>
|
||||
Then, the "fooService" can be injected into other beans, and the code that invokes the methods on that
|
||||
proxied instance of the FooService interface has no awareness of the Spring Integration API. The general
|
||||
approach is similar to that of Spring Remoting (RMI, HttpInvoker, etc.).
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
@@ -47,7 +47,7 @@
|
||||
<xi:include href="./service-activator.xml"/>
|
||||
<xi:include href="./channel-adapter.xml"/>
|
||||
<xi:include href="./router.xml"/>
|
||||
<xi:include href="./transformation.xml"/>
|
||||
<xi:include href="./transformer.xml"/>
|
||||
<xi:include href="./splitter.xml"/>
|
||||
<xi:include href="./aggregator.xml"/>
|
||||
<xi:include href="./resequencer.xml"/>
|
||||
|
||||
Reference in New Issue
Block a user