327 lines
21 KiB
XML
327 lines
21 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
|
<chapter id="overview">
|
|
<title>Spring Integration Overview</title>
|
|
|
|
<section id="overview-background">
|
|
<title>Background</title>
|
|
<para>
|
|
One of the key themes of the Spring Framework is <emphasis>inversion of control</emphasis>. In its broadest
|
|
sense, this means that the framework handles responsibilities on behalf of the components that are managed within
|
|
its context. The components themselves are simplified since they are relieved of those responsibilities. For
|
|
example, <emphasis>dependency injection</emphasis> relieves the components of the responsibility of locating or
|
|
creating their dependencies. Likewise, <emphasis>aspect-oriented programming</emphasis> relieves business
|
|
components of generic cross-cutting concerns by modularizing them into reusable aspects. In each case, the end
|
|
result is a system that is easier to test, understand, maintain, and extend.
|
|
</para>
|
|
<para>
|
|
Furthermore, the Spring framework and portfolio provide a comprehensive programming model for building
|
|
enterprise applications. Developers benefit from the consistency of this model and especially the fact that it is
|
|
based upon well-established best practices such as programming to interfaces and favoring composition over
|
|
inheritance. Spring's simplified abstractions and powerful support libraries boost developer productivity while
|
|
simultaneously increasing the level of testability and portability.
|
|
</para>
|
|
<para>
|
|
Spring Integration is a new member of the Spring portfolio motivated by these same goals and principles. It
|
|
extends the Spring programming model into the messaging domain and builds upon Spring's existing enterprise
|
|
integration support to provide an even higher level of abstraction. It supports message-driven architectures
|
|
where inversion of control applies to runtime concerns, such as <emphasis>when</emphasis> certain business logic
|
|
should execute and <emphasis>where</emphasis> the response should be sent. It supports routing and transformation
|
|
of messages so that different transports and different data formats can be integrated without impacting
|
|
testability. In other words, the messaging and integration concerns are handled by the framework, so business
|
|
components are further isolated from the infrastructure and developers are relieved of complex integration
|
|
responsibilities.
|
|
</para>
|
|
<para>
|
|
As an extension of the Spring programming model, Spring Integration provides a wide variety of configuration
|
|
options including annotations, XML with namespace support, XML with generic "bean" elements, and of course direct
|
|
usage of the underlying API. That API is based upon well-defined strategy interfaces and non-invasive, delegating
|
|
adapters. Spring Integration's design is inspired by the recognition of a strong affinity between common patterns
|
|
within Spring and the well-known <ulink url="http://www.eaipatterns.com">Enterprise Integration Patterns</ulink>
|
|
as described in the book of the same name by Gregor Hohpe and Bobby Woolf (Addison Wesley, 2004). Developers who
|
|
have read that book should be immediately comfortable with the Spring Integration concepts and terminology.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="overview-goalsandprinciples">
|
|
<title>Goals and Principles</title>
|
|
<para>Spring Integration is motivated by the following goals:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Provide a simple model for implementing complex enterprise integration solutions.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Facilitate asynchronous, message-driven behavior within a Spring-based application.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Promote intuitive, incremental adoption for existing Spring users.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
<para>Spring Integration is guided by the following principles:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Components should be <emphasis>loosely coupled</emphasis> for modularity and testability.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>The framework should enforce <emphasis>separation of concerns</emphasis> between business logic and
|
|
integration logic.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Extension points should be abstract in nature but within well-defined boundaries to promote
|
|
<emphasis>reuse</emphasis> and <emphasis>portability</emphasis>.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
</section>
|
|
|
|
<section id="overview-components">
|
|
<title>Main Components</title>
|
|
|
|
<para>
|
|
From the <emphasis>vertical</emphasis> perspective, a layered architecture facilitates separation of concerns,
|
|
and interface-based contracts between layers promote loose coupling. Spring-based applications are typically
|
|
designed this way, and the Spring framework and portfolio provide a strong foundation for following this best
|
|
practice for the full-stack of an enterprise application. Message-driven architectures add a
|
|
<emphasis>horizontal</emphasis> perspective, yet these same goals are still relevant. Just as "layered
|
|
architecture" is an extremely generic and abstract paradigm, messaging systems typically follow the similarly
|
|
abstract "pipes-and-filters" model. The "filters" represent any component that is capable of producing and/or
|
|
consuming messages, and the "pipes" transport the messages between filters so that the components themselves
|
|
remain loosely-coupled. It is important to note that these two high-level paradigms are not mutually exclusive.
|
|
The underlying messaging infrastructure that supports the "pipes" should still be encapsulated in a layer whose
|
|
contracts are defined as interfaces. Likewise, the "filters" themselves would typically be managed within a layer
|
|
that is logically above the application's service layer, interacting with those services through interfaces much
|
|
in the same way that a web-tier would.
|
|
</para>
|
|
<section id="overview-components-message">
|
|
<title>Message</title>
|
|
<para>
|
|
In Spring Integration, a Message is a generic wrapper for any Java object combined with metadata used by the
|
|
framework while handling that object. It consists of a payload and headers. The payload can be of any type and
|
|
the headers hold commonly required information such as id, timestamp, expiration, and return address.
|
|
Developers can also store any arbitrary key-value pair in the headers.
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata align="center" fileref="images/message.png" format="PNG"/>
|
|
</imageobject>
|
|
</mediaobject>
|
|
</para>
|
|
</section>
|
|
<section id="overview-components-source">
|
|
<title>Message Source</title>
|
|
<para>
|
|
Since a Spring Integration Message is a generic wrapper for any Object, there is no limit to the number of
|
|
potential sources for such messages. In fact, a source implementation can act as an adapter that converts
|
|
Objects from any other system into Spring Integration Messages.
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata align="center" fileref="images/source.png" format="PNG"/>
|
|
</imageobject>
|
|
</mediaobject>
|
|
There are two types of source: those which require polling and those which send Messages directly. Therefore,
|
|
Spring Integration provides two main interfaces that extend the <interfacename>MessageSource</interfacename>
|
|
interface: <interfacename>PollableSource</interfacename> and <interfacename>SubscribableSource</interfacename>.
|
|
While it is relatively easy to implement these interfaces directly, an adapter is also available for invoking
|
|
arbitrary methods on plain Objects. Also, several <interfacename>MessageSource</interfacename> implementations
|
|
are already available within the Spring Integration Adapters module. For a detailed discussion of the various
|
|
adapters, see <xref linkend="adapters"/>.
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title>Message Target</title>
|
|
<para>
|
|
Just as the <interfacename>MessageSource</interfacename> implementations enable Message reception, a
|
|
<interfacename>MessageTarget</interfacename> handles the responsibility of sending Messages. As with the
|
|
<interfacename>MessageSource</interfacename>, a <interfacename>MessageTarget</interfacename> can act as an
|
|
adapter that converts Messages into the Objects expected by some other system.
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata align="center" fileref="images/target.png" format="PNG"/>
|
|
</imageobject>
|
|
</mediaobject>
|
|
The MessageTarget interface may be implemented directly, but an adapter is also available for invoking arbitrary
|
|
methods on plain Objects (delegating to a <interfacename>MessageMapper</interfacename> strategy in the process).
|
|
As with MessageSources, several MessageTarget implementations are already available within the Spring Integration
|
|
Adapters module as discussed in <xref linkend="adapters"/>.
|
|
</para>
|
|
</section>
|
|
<section id="overview-components-handler">
|
|
<title>Message Handler</title>
|
|
<para>
|
|
As described above, the MessageSource and MessageTarget components support conversion between Objects and
|
|
Messages so that application code and/or external systems can be connected to a Spring Integration application
|
|
rather easily. However, both MessageSource and MessageTarget are unidirectional while the application code or
|
|
external system to be invoked may provide a return value. The <interfacename>MessageHandler</interfacename>
|
|
interface supports these request-reply scenarios.
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata align="center" fileref="images/handler.png" format="PNG"/>
|
|
</imageobject>
|
|
</mediaobject>
|
|
As with the MessageSource and MessageTarget, Spring Integration also provides an adapter that itself implements
|
|
the <interfacename>MessageHandler</interfacename> interface while supporting the invocation of arbitrary methods
|
|
on plain Objects. For more information about the Message Handler, see <xref linkend="api-messagehandler"/>.
|
|
</para>
|
|
</section>
|
|
<section id="overview-components-channel">
|
|
<title>Message Channel</title>
|
|
<para>
|
|
A Message Channel represents the "pipe" of a pipes-and-filters architecture. Producers send Messages to
|
|
a channel, and consumers receive Messages from a channel. By providing both send and receive operations, a
|
|
Message Channel basically combines the roles of MessageSource and MessageTarget.
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata align="center" fileref="images/channel.png" format="PNG"/>
|
|
</imageobject>
|
|
</mediaobject>
|
|
Every channel is also a <interfacename>MessageTarget</interfacename>, so Messages can be sent to a channel.
|
|
Likewise, every channel is a <interfacename>MessageSource</interfacename>, but as discussed above, Spring
|
|
Integration defines two types of source: pollable and subscribable. Subscribable channels include
|
|
PublishSubscribeChannel and DirectChannel. Pollable channels include QueueChannel, PriorityChannel,
|
|
RendezvousChannel, and ThreadLocalChannel. These are described in detail in
|
|
<xref linkend="api-messagechannel"/>.
|
|
</para>
|
|
</section>
|
|
<section id="overview-components-endpoint">
|
|
<title>Message Endpoint</title>
|
|
<para>
|
|
Thus far, the component diagrams show consumers, producers, and requesters invoking the MessageSource,
|
|
MessageTarget, and MessageHandlers respectively. However, one of the primary goals of Spring Integration is to
|
|
simplify the development of enterprise integration solutions through <emphasis>inversion of control</emphasis>.
|
|
This means that you should not have to implement such consumers, producers, and requesters directly. Instead,
|
|
you should be able to focus on your domain logic with an implementation based on plain Objects. Then, by
|
|
providing declarative configuration, you can "connect" your application code to the messaging infrastructure
|
|
provided by Spring Integration. The components responsible for these connections are Message Endpoints.
|
|
</para>
|
|
<para>
|
|
A Message Endpoint represents the "filter" of a pipes-and-filters architecture. As mentioned above, the
|
|
endpoint's primary role is to connect application code to the messaging framework and to do so in a
|
|
non-invasive manner. In other words, the application code should have no awareness of the Message objects or
|
|
the Message Channels. This is similar to the role of a Controller in the MVC paradigm. Just as a Controller
|
|
handles HTTP requests, the Message Endpoint handles Messages. Just as Controllers are mapped to URL patterns,
|
|
Message Endpoints are mapped to Message Channels. The goal is the same in both cases: isolate application code
|
|
from the infrastructure. Spring Integration provides Message Endpoints for connecting each of the component
|
|
types described above. The description of each of the main types of endpoint follows.
|
|
</para>
|
|
<section>
|
|
<title>Channel Adapter</title>
|
|
<para>
|
|
A Channel Adapter is an endpoint that connects either a MessageSource or a MessageTarget to a
|
|
MessageChannel. If a MessageSource is being adapted, then the adapter is responsible for receiving
|
|
Messages from the MessageSource and sending them to the MessageChannel. If a Message Target is being
|
|
adapted, then the adapter is responsible for receiving Messages from the MessageChannel and sending
|
|
them to the MessageTarget.
|
|
</para>
|
|
<para>
|
|
When a Channel Adapter is used to connect a PollableSource implementation to a Message Channel,
|
|
the invocation of the MessageSource's receive operation may be controlled by scheduling information
|
|
provided within the Channel Adapter's configuration. Any time the receive operation returns a non-null
|
|
Message, it is sent to the MessageChannel.
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata align="center" fileref="images/source-endpoint.png" format="PNG"/>
|
|
</imageobject>
|
|
<caption>An inbound "Channel Adapter" endpoint connects a MessageSource to a MessageChannel</caption>
|
|
</mediaobject>
|
|
</para>
|
|
<para>
|
|
If the source being connected by the Channel Adapter is a SubscribableSource, then no scheduling
|
|
information should be provided. Instead the source will send the Message directly, and the Channel Adapter
|
|
will pass it along to its Message Channel.
|
|
</para>
|
|
<para>
|
|
When a Channel Adapter is used to connect a MessageTarget implementation to a Pollable Message Channel,
|
|
the invocation of the MessageChannel's receive operation may be controlled by scheduling information
|
|
provided within the Channel Adapter's configuration. Any time a non-null Message is received from the
|
|
MessageChannel, it is sent to the MessageTarget.
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata align="center" fileref="images/target-endpoint.png" format="PNG"/>
|
|
</imageobject>
|
|
<caption>An outbound "Channel Adapter" endpoint connects a MessageChannel to a MessageTarget</caption>
|
|
</mediaobject>
|
|
</para>
|
|
<para>
|
|
If the MessageChannel being connected is not Pollable but Subscribable (e.g. Direct Channel or Publish
|
|
Subscribe Channel), then no scheduling information should be provided. Instead the channel will send
|
|
Messages directly, and the Channel Adapter will pass them along to the MessageTarget.
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title>Service Activator</title>
|
|
<para>
|
|
When the Object to be invoked is capable of returning a value, another type of endpoint is
|
|
needed to accommodate the additional responsibilities of the <emphasis>request/reply</emphasis>
|
|
interaction. The general behavior is similar to a Channel Adapter, but this type of endpoint -
|
|
the Service Activator - must make a distinction between the "input-channel" and the "output-channel".
|
|
Also, the Service Activator invokes an operation on some Message Handler to process the request
|
|
Message. Whenever the Message-handling Object returns a reply Message, that Message is sent to the
|
|
output channel. If no output channel has been configured, then the reply will be sent to the channel
|
|
specified in the MessageHeader's "return address" if available.
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata align="center" fileref="images/handler-endpoint.png" format="PNG"/>
|
|
</imageobject>
|
|
<caption>
|
|
A request-reply "Service Activator" endpoint connects a MessageHandler to input and output MessageChannels.
|
|
</caption>
|
|
</mediaobject>
|
|
</para>
|
|
</section>
|
|
</section>
|
|
<section id="overview-component-router">
|
|
<title>Message Router</title>
|
|
<para>
|
|
A Message Router is a particular type of Message Endpoint that is capable of receiving a Message from
|
|
a MessageChannel and then deciding what channel or channels should receive the Message next (if any).
|
|
Typically the decision is based upon the Message's content and/or metadata available in the MessageHeader.
|
|
A Message Router is often used as a dynamic alternative to a statically configured output channel on
|
|
a Service Activator or other Message-handling endpoint.
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata align="center" fileref="images/router.png" format="PNG"/>
|
|
</imageobject>
|
|
</mediaobject>
|
|
</para>
|
|
</section>
|
|
<section id="overview-component-splitter">
|
|
<title>Splitter</title>
|
|
<para>
|
|
A Splitter is another type of Message Endpoint whose responsibility is to accept a Message from its input
|
|
channel, split that Message into multiple Messages, and then send each of those to its output channel. This
|
|
is typically used for dividing a "composite" payload object into a group of Messages containing the
|
|
sub-divided payloads.
|
|
</para>
|
|
</section>
|
|
<section id="overview-component-aggregator">
|
|
<title>Aggregator</title>
|
|
<para>
|
|
Basically a mirror-image of the Splitter, the Aggregator is a type of Message Endpoint that receives multiple
|
|
Messages and combines them into a single Message. In fact, Aggregators are often downstream consumers in a
|
|
pipeline that includes a Splitter. Technically, the Aggregator is more complex than a Splitter, because it
|
|
is required to maintain state (the Messages to-be-aggregated), to decide when the complete group of Messages
|
|
is available, and to timeout if necessary. Furthermore, in case of a timeout, the Aggregator needs to know
|
|
whether to send the partial results or to discard them to a separate channel. Spring Integration provides
|
|
a <interfacename>CompletionStrategy</interfacename> as well as configurable settings for timeout, whether
|
|
to send partial results, and the discard channel.
|
|
</para>
|
|
</section>
|
|
<section id="overview-component-bus">
|
|
<title>Message Bus</title>
|
|
<para>
|
|
The Message Bus acts as a registry for Message Channels and Message Endpoints. It also encapsulates the
|
|
complexity of message retrieval and dispatching. Essentially, the Message Bus forms a logical extension of the
|
|
Spring application context into the messaging domain. For example, it will automatically detect Message Channel
|
|
and Message Endpoint components from within the application context. It handles the scheduling of pollers, the
|
|
creation of thread pools, and the lifecycle management of all messaging components that can be initialized,
|
|
started, and stopped. The Message Bus is the primary example of inversion of control within Spring Integration.
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata align="center" fileref="images/message-bus.png" format="PNG"/>
|
|
</imageobject>
|
|
</mediaobject>
|
|
</para>
|
|
</section>
|
|
</section>
|
|
|
|
</chapter> |