274 lines
17 KiB
XML
274 lines
17 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, 2003). 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 header and has a unique identifier. The
|
|
payload can be of any type and the header holds commonly required information such as timestamp, expiration,
|
|
and return address. Developers can also store any arbitrary key-value properties or attributes in the header.
|
|
<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>
|
|
To facilitate the conversion of Objects to Messages, Spring Integration also defines a strategy interface
|
|
for creating Messages called <interfacename>MessageCreator</interfacename>. While it is relatively easy to
|
|
implement Source directly, an adapter is also available for invoking arbitrary methods on plain Objects. Also,
|
|
several Source 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 a Source enables Message reception, a Target handles the responsibility of sending Messages. As with
|
|
a Source, a Target 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>
|
|
Spring Integration provides a strategy interface for mapping Messages to Objects called
|
|
<interfacename>MessaegMapper</interfacename>. The Target interface may be implemented directly, but an adapter
|
|
is also available for invoking arbitrary methods on plain Objects (delegating to the Message-mapping strategy
|
|
in the process). As with Sources, several Target 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 Source and Target 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 Source and Target are unidirectional while the application code or external system to be invoked
|
|
may provide a return value. The Message Handler interface supports these request-reply scenarios.
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata align="center" fileref="images/handler.png" format="PNG"/>
|
|
</imageobject>
|
|
</mediaobject>
|
|
As with the Source and Target, Spring Integration also provides an adapter that itself implements the Message
|
|
Handler interface while supporting the invocation of arbitrary methods on plain Objects. The adapter relies
|
|
upon the message-creating and message-mapping strategies to handle the bidirectional Object/Message conversion.
|
|
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 Source and Target.
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata align="center" fileref="images/channel.png" format="PNG"/>
|
|
</imageobject>
|
|
</mediaobject>
|
|
Spring Integration provides a number of different channel implementations: QueueChannel, PriorityChannel,
|
|
RendezvousChannel, DirectChannel, 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 Source, Target, and
|
|
Message Handlers 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 Producers, Consumers, 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 three types of endpoints - one for each of the component
|
|
types described above: Source Endpoint, Target Endpoint, and Handler Endpoint.
|
|
</para>
|
|
<section>
|
|
<title>Source Endpoint</title>
|
|
<para>
|
|
A Source Endpoint connects any Source implementation to a Message Channel. The invocation of the Source's
|
|
receive operation is controlled by scheduling information provided within the Source Endpoint's
|
|
configuration. Any time the receive operation returns a non-null Message, it is sent to the channel.
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata align="center" fileref="images/source-endpoint.png" format="PNG"/>
|
|
</imageobject>
|
|
</mediaobject>
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title>Target Endpoint</title>
|
|
<para>
|
|
A Target Endpoint connects a Message Channel to any Target implementation. The invocation of the Message
|
|
Channel's receive operation is controlled by scheduling information provided within the Target Endpoint's
|
|
configuration. Any time a non-null Message is received from the channel, it is sent to the Target.
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata align="center" fileref="images/target-endpoint.png" format="PNG"/>
|
|
</imageobject>
|
|
</mediaobject>
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title>Handler Endpoint</title>
|
|
<para>
|
|
Since Message Handler's are capable of returning reply Messages, the Handler Endpoint has some additional
|
|
responsibilities. The general behavior is the same as the Target Endpoint, but the Handler Endpoint must
|
|
make a distinction between "input-channel" and "output-channel". Whenever the Message Handler does return
|
|
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 as the Message header's "return address" if available.
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata align="center" fileref="images/handler-endpoint.png" format="PNG"/>
|
|
</imageobject>
|
|
</mediaobject>
|
|
</para>
|
|
</section>
|
|
</section>
|
|
<section id="overview-component-router">
|
|
<title>Message Router</title>
|
|
<para>
|
|
A Message Router is a particular type of <interfacename>MessageHandler</interfacename> that is capable of
|
|
receiving a Message and then deciding what channel or channels should receive the Message next. Typically the
|
|
decision is based upon the Message's content and/or metadata. A Message Router is often used as a dynamic
|
|
alternative to configuring the input and output channels for an endpoint.
|
|
<mediaobject>
|
|
<imageobject>
|
|
<imagedata align="center" fileref="images/router.png" format="PNG"/>
|
|
</imageobject>
|
|
</mediaobject>
|
|
</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> |