This chapter covers
1.2 Spring Integration’s support for enterprise integration patterns
Enterprise Integration Patterns describes the patterns used in the exchange of messages, as well as the patterns that provide the glue between applications. Like the diagram in figure 1.1, it’s about messaging and integration in the broadest sense, and the patterns apply to both intra -application and inter application scenarios. Spring Integration sup- ports the patterns described in the book, so we need to establish a broad understand- ing of the definitions of these patterns and the relations between them.
From the most general perspective, only three base patterns make up enterprise integration patterns: Message, Message Channel, and Message Endpoint. Figure 1.2 shows how these components interact with each other in a typical integration application.
There are two main ways to differentiate between these patterns. First, each pattern has more specific subtypes, and second, some patterns are composite patterns. This section focuses on the subtypes so you have a clear understanding of the building blocks. Composite patterns are introduced as needed throughout the book.
1.2.1 Messages
A message is a unit of information that can be passed between different components, called message endpoints. Messages are typically sent after one endpoint is done with a bit of work, and they trigger another endpoint to do another bit of work. Messages can contain information in any format that’s convenient for the sending and receiving endpoints. For example, the message’s payload may be XML, a simple string, or a pri- mary key referencing a record in a database. See
figure 1.3.
Each message consists of headers and a pay- load. The header contains data that’s relevant to the messaging system, such as the Return Address or Correlation ID. The payload contains the actual data to be accessed or processed by the receiver. Messages can have different functions. For exam- ple, a Command Message tells the receiver to do something, an Event Message notifies the receiver that something has happened, and a Document Message transfers some data from the sender to the receiver.
Endpoint
Channel
Message Endpoint
Figure 1.2 A message is passed through a channel from one endpoint to another endpoint.
Payload Header
Figure 1.3 A message consists of a single payload and zero or more headers, represented here by the square and circle, respectively.
9
Spring Integration’s support for enterprise integration patterns
In all of these cases, the message is a representation of the contract between the sender and receiver. In some applications it might be fine to send a reference to an object over the channel, but in others it might be necessary to use a more interopera- ble representation like an identifier or a serialized version of the original data. 1.2.2 Message Channels
The message channel is the connection between multiple endpoints. The channel implementation manages the details of how and where a message is delivered but shouldn’t need to interact with the payload of a message. Whereas the most important characteristic of any channel is that it logically decouples producers from consumers, there are a number of practical implementation options. For example, a particular channel implementation might dispatch messages directly to passive consumers within the same thread of control. On the other hand, a different channel implemen- tation might buffer messages in a queue whose reference is shared by the producer and an active consumer such that the send and receive operations each occur within different threads of control. Additionally, channels may be classified according to whether messages are delivered to a single endpoint (point-to-point) or to any end- point that is listening to the channel (publish-subscribe). As mentioned earlier, regardless of the implementation details, the main goal of any message channel is to decouple the message endpoints on both sides from each other and from any con- cerns of the underlying transport.
Two endpoints can exchange messages only if they’re connected through a chan- nel. The details of the delivery process depend on the type of channel being used. We review many characteristics of the different types of channels later when we discuss their implementations in Spring Integration. Message channels are the key enabler for loose coupling. Both the sender and receiver can be completely unaware of each other thanks to the channel between them. Additional components may be needed to connect services that are completely unaware of messaging to the channels. We dis- cuss this facet in the next section on message endpoints.
Channels can be categorized based on two dimensions: type of handoff and type of delivery. The handoff can be either synchronous or asynchronous, and the delivery can be either point-to-point or publish-subscribe. The former distinction will be dis- cussed in detail in the synchronous versus asynchronous section of the next chapter. The latter distinction is conceptually simpler, and central to enterprise integration patterns, so we describe it here.
In point-to-point messaging (see figure 1.4), each single message that’s sent by a producer is received by exactly one consumer. This
is conceptually equivalent to a postcard or phone call. If no consumer receives the message, it should be considered an error. This is especially true for any system that must support guaranteed delivery. Robust point-to-point messaging systems should
Point-to-Point Channel
10 CHAPTER 1 Introduction to Spring Integration
also include support for load balancing and failover. The former would be like calling each number on a list in turn as new messages are to be delivered, and the latter would be like a home phone that’s configured to fall back to a mobile when nobody is home to answer it.
As these cases imply, which consumer receives the message isn’t necessarily fixed. For example, in the Competing Consumers (composite) pattern, multiple consumers compete for messages from a single channel. Once one of the consumers wins the race, no other consumer will receive that message from the channel. Different con- sumers may win each time, though, because the main characteristic of that pattern is that it offers a consumer-driven approach to load balancing. When a consumer can’t handle any more load, it stops competing for another message. Once it’s able to han- dle load again, it will resume.
Unlike point-to-point messaging, a Publish-Subscribe Channel (figure 1.5) delivers the same message to zero or more subscribers. This is conceptually equivalent to a newspaper or the radio. It provides a gain in flexibility because consumers can tune in to the channel at runtime. The drawback of
publish-subscribe messaging is that the sender isn’t informed about message deliv- ery or failure to the same extent as in point- to-point configurations. Publish-subscribe scenarios often require failure-handling pat- terns such as Idempotent Receiver or Compensat- ing Transactions.
1.2.3 Message endpoints
Message endpoints are the components that actually do something with the message. This can be as simple as routing to another channel or as complicated as splitting the message into multiple parts or aggregating the parts back together. Connections to the application or the outside world are also endpoints, and these connections take the form of channel adapters, messaging gateways, or service activators. We discuss each of them later in this section.
Message endpoints basically provide the connections between functional services and the messaging framework. From the point of view of the messaging framework, endpoints are at the end of channels. In other words, a message can leave the channel successfully only by being consumed by an endpoint, and a message can enter the channel only by being produced by an endpoint. There are many different types of endpoints. We discuss a few of them here to give you a general idea.
CHANNEL ADAPTER
A Channel Adapter (see figure 1.6) connects an application to the messaging system. In Spring Integration we chose to constrict the definition to include only connec- tions that are unidirectional, so a unidirectional message flow begins and ends in a channel adapter. Many different kinds of channel adapters exist, ranging from a method-invoking channel adapter to a web service channel adapter. We go into the
Publish-Subscribe Channel
11
Spring Integration’s support for enterprise integration patterns
details of these different types in the appropriate chapters on different transports. For now, it’s sufficient to remember that a channel adapter is placed at the beginning and the end of a unidirectional message flow.
MESSAGING GATEWAY
In Spring Integration, a Messaging Gateway (see figure 1.7) is a connection that’s spe- cific to bidirectional messaging. If an incoming request needs to be serviced by multi- ple threads but the invoker needs to remain unaware of the messaging system, an inbound gateway provides the solution. On the outbound side, an incoming message can be used in a synchronous invocation, and the result is sent on the reply channel. For example, outbound gateways can be used for invoking web services and for syn- chronous request-reply interactions over JMS.
A gateway can also be used midstream in a unidirectional message flow. As with the channel adapter, we’ve constrained the definition of messaging gateway a bit in com- parison to Enterprise Integration Patterns (see figure 1.8.)
SERVICE ACTIVATOR
A Service Activator (see figure 1.9) is a component that invokes a service based on an incoming message and sends an outbound message based on the return value of this service invocation. In Spring Integration, the definition is constrained to local method calls, so you can think of a service activator as a method-invoking outbound gateway. The method that’s being invoked is defined on an object that’s referenced within the same Spring application context.
Application A
Channel Adapter Channel
Channel Adapter
Application B
Figure 1.6 Channel Adapter
Gateway Gateway
Application A Application B
output input
Figure 1.7 Messaging Gateway
Application A Application B Application A input output Gateway Figure 1.8 Messaging Gateway and Channel Adapters
12 CHAPTER 1 Introduction to Spring Integration
ROUTER
A Router (see figure 1.10) determines the next channel a message should be sent to based on the incoming message. This can be useful to send messages with different payloads to different, specialized consum- ers (Content-Based Router). The router doesn’t change anything in the message
and is aware of channels. Therefore, it’s the endpoint that’s typically closest to the infrastructure and furthest removed from the business concerns.
SPLITTER
A Splitter (see figure 1.11) receives one mes- sage and splits it into multiple messages that are sent to its output channel. This is useful whenever the act of processing mes- sage content can be split into multiple steps and executed by different consumers at the same time.
AGGREGATOR
An Aggregator (figure 1.12) waits for a group of correlated messages and merges them together when the group is complete. The correlation of the messages typically is based on a correlation ID, and the completion is typically related to the size of the group. A splitter and an aggregator are often used in a symmetric setup, where some work is done in parallel after a splitter, and the aggregated result is sent back to the upstream gateway.
You’ll see many more patterns throughout the book, but what we covered here should be sufficient for this general introduction. If you paid close attention while read- ing the first paragraph in section 1.2, you may have noticed that we said Spring Inte- gration supports the enterprise integration
patterns, not that it implements the patterns. That’s a subtle but important distinction. In general, software patterns describe proven solutions to common problems. They shouldn’t be treated as recipes. In reality,
Service input
output
Service Activator
Figure 1.9 Service Activator
Router Figure 1.10 Router Splitter Figure 1.11 Splitter Aggregator Figure 1.12 Aggregator
13
Enterprise integration patterns meet Inversion of Control
patterns rarely have a one-to-one mapping to a single implementation, and context- dependent factors often lead to particular implementation details.
As far as the enterprise integration patterns are concerned, some, such as the mes- sage and message channel patterns, are more or less implemented. Others are only partially implemented because they require the addition of some domain-specific logic; examples are the content-based router in which the content is dependent on the domain model and the service activator in which the service to be activated is part of a specific domain. Yet other patterns describe individual parts of a larger process; examples are the correlation ID we mentioned when describing splitter and aggrega- tors and the return address that we discuss later. Finally, there are patterns that simply describe a general style, such as the pipes-and-filters pattern. With these various pat- tern categories in mind, let’s now see how the concept of inversion of control applies to Spring Integration’s support for the patterns.