Renamed transformation.xml to transformer.xml

This commit is contained in:
Mark Fisher
2008-11-03 03:57:39 +00:00
parent 66519d30f1
commit 32c7618e24
3 changed files with 1 additions and 176 deletions

View File

@@ -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&lt;?&gt; handle(Message&lt;?&gt; 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>

View File

@@ -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"/>