Introduction
You face a difficult challenge when your enterprise applications must communicate across organizational and technical boundaries. Integration projects often fail because developers rely on ad-hoc point-to-point connections that create brittle systems. You need a common vocabulary and proven architectural guidance to build flexible distributed solutions.
Enterprise integration patterns provide a proven vocabulary and architectural guide to solving distributed integration problems using asynchronous messaging.
Gregor Hohpe and Bobby Woolf present a pattern language that helps you design robust messaging solutions. The book covers foundational messaging primitives, channel topologies, routing mechanisms, message construction, and management strategies. How do you route messages through complex workflows without creating central bottlenecks? How do you ensure reliable delivery across unreliable networks?
1. Solving Integration Problems Using Patterns
Applications spread across multiple systems because writing a single monolithic application for an entire enterprise is nearly impossible. Distributed applications allow businesses to select the best specialized software for distinct functions. Enterprise Resource Planning vendors like SAP, Oracle, and Peoplesoft only perform a fraction of the business functions required in a typical enterprise. Spreading functions across multiple packages gives flexibility, but it leads to functional spillover and complex integration needs. An enterprise might operate 30 Web sites or run 3 instances of SAP.
Enterprise integration is difficult because it spans technical and political boundaries, requiring you to manage semantic differences and technical heterogeneity across legacy systems.
The Need for Integration
Enterprise Application Integration is difficult because it spans technical and political boundaries, requires coordination across multiple platforms and legacy systems, and lacks universal semantic standards. Developers often have limited control over participating legacy packages and must handle semantic differences where a shared term like account has different meanings in separate systems. Furthermore, Enterprise Application Integration solutions increase operational complexity despite high-level visions. Conway's law influences these technical boundaries.
Loose Coupling
The core principle of loose coupling is to reduce the assumptions that communicating parties make about each other, making the system more tolerant of interruptions and changes. While tight coupling like local method invocation allows high efficiency through shared process, language, and immediate synchronous execution, applying these same assumptions to remote integration leads to brittle and hard-to-maintain solutions. In 1994, Waldo and colleagues published 'A Note on Distributed Computing' regarding distributed objects.
Connecting systems via raw TCP/IP sockets requires deep assumptions about platform technologies, internal memory representations, machine addresses, and simultaneous component availability. A basic socket connection sending integer amounts and names in C# works for a simple test, but fails when different machine architectures use different bit-widths, byte orderings like big-endian versus little-endian, or encounter network interruptions. Operating systems and libraries have consistently included TCP/IP stacks for 15 years.
Sending a 1000 dollar deposit from an online banking front-end to a financial system uses a 10-line C# socket program that transmits raw byte arrays. The connection uses port 80 and transfers 4 bytes across the network to represent a 32-bit integer in .NET. A big-endian system would assign the miscalculated value 3,892,510,720 to the little-endian byte stream representing 1,000. After executing the transmission, the system returns a 7 bytes sent confirmation message.
To transform a tightly coupled integration into a loosely coupled one, systems must replace direct machine addresses with logical channels, use self-describing data formats, and queue requests to remove temporal dependencies. Message-oriented middleware provides these services, enabling the sender to transmit self-contained messages into a channel without needing to know the receiver's location, internal data format, or operational status at that exact moment.
2. Root Messaging Patterns
Messaging architectures rely on foundational elements such as message channels, discrete packets of data, and pipes and filters that transform and route information asynchronously.
Message Channel
Applications communicate asynchronously through a Message Channel, which acts as a virtual pipe connecting a sender to a receiver and hiding underlying configuration details. Rather than broadcasting information randomly, the sending application adds data to a specific message channel designed for that type of information. The receiving application selects the appropriate channel to retrieve it. Channels are logical addresses that require administrative setup before client code can instantiate runtime objects to access them.
In J2EE JMS, a destination is created via the j2eeadmin tool and then looked up in Java using JNDI. In IBM WebSphere MQ, a queue is defined using DEFINE Q(myQueue) and accessed via a JMS session.
To configure your infrastructure successfully, follow these practice steps:
- Determine how applications need to communicate and design the required channels.
- Configure the messaging system software at deployment time using administrative tools to set up the expected channels.
- Instantiate a runtime object in code using APIs like JMS or .NET to access the already created channel resource.
Message
Messaging systems transmit discrete atomic packets of data called Messages, which consist of a header used by the messaging system and a body containing the application payload. Because separate processes have distinct memory spaces, data must be marshaled into a byte stream or data record at the sender and unmarshaled at the receiver. The header describes data origin, destination, and system routing instructions, while the body carries the raw information transparently across the infrastructure.
A SOAP message encapsulates an XML document containing an optional header element and a required body element, demonstrating how messages can be nested inside internal messaging protocols. A value representing a transaction identifier inside a SOAP header example guides the underlying tracking logic.
Pipes and Filters
The Pipes and Filters architectural style divides a large processing task into a sequence of smaller, independent processing steps connected by channels. Each filter exposes a uniform interface with an input and output port, receiving a message, performing an action, and passing the result forward. This modular approach allows steps to be added, removed, or rearranged without modifying the components, and enables pipeline processing where multiple stages execute concurrently in separate threads.
An incoming order processing workflow uses three filters connected by four pipes to perform decryption, digital certificate authentication, and duplicate message elimination. Kahn described Kahn Process Networks in 1974, and Hoare introduced Communicating Sequential Processes in 1978.
Execute this architectural style using these steps:
- Divide a complex message processing task into a sequence of smaller, independent filtering steps.
- Connect the filter components using messaging channels or abstract pipe interfaces.
- Register for incoming messages using an event-driven consumer and invoke message processing methods upon arrival.
3. Messaging Channels and Infrastructure
Specifying channel semantics, guaranteed delivery mechanisms, and system bridges ensures that your messages reach the correct recipients reliably despite network failures.
Point-to-Point and Publish-Subscribe Channels
A Point-to-Point Channel ensures that each message placed on it is consumed by exactly one receiver, even if multiple receivers are listening. This pattern is essential when implementing remote procedure calls or document transfers where a task should only be executed once. When multiple consumers listen to the same channel, they act as competing consumers, enabling scalable load balancing.
In a stock trading system, a request to execute a specific trade must be processed by exactly one receiver, so it is sent over a Point-to-Point Channel.
A Publish-Subscribe Channel broadcasts a copy of a particular event message to every registered subscriber. It decouples event originators from observers. The channel takes an input message and delivers a distinct copy to an output channel for each subscriber, allowing concurrent non-competing consumption.
In a stock trading system, trade completions and stock quote data are broadcast across a Publish-Subscribe Channel so that multiple interested systems can receive updates.
Guaranteed Delivery and Bridges
Guaranteed Delivery uses built-in local datastores to persist messages to disk so they survive system crashes or network outages. A send operation does not complete until the message is safely stored, and it is not deleted from one datastore until successfully forwarded to the next. While it increases reliability, it incurs performance overhead and consumes disk space during prolonged outages.
In a stock trading system, trade requests and trade confirmations are sent with Guaranteed Delivery to ensure none are lost, whereas high-frequency price updates typically bypass it.
A Channel Adapter connects non-messaging applications to the messaging infrastructure by interfacing directly with their APIs, user interfaces, or databases. It bridges the gap for packaged legacy systems where source code cannot be modified, translating application events into published messages and incoming messages into application function calls across UI, business logic, or data layers.
A stock trading system uses a relational database adapter to log every message from a channel directly into a database table, and an Internet adapter to ingest external HTTP quote requests.
A Messaging Bridge connects multiple incompatible messaging systems by linking corresponding channels and translating message formats between them. Different vendors implement proprietary message formats and stores, and standard APIs like JMS do not make messaging systems interoperable. A Messaging Bridge acts as a set of Channel Adapters where the non-messaging client is another messaging system, consuming messages from one side and replicating them to the corresponding channel on the other side.
Microsoft's Host Integration Server provides an MSMQ-MQSeries Bridge, and Envoy Technologies offers Envoy Connect to coordinate J2EE and .NET messaging.
4. Message Construction and Routing Architecture
Advanced message structures and routing components like content-based routers and process managers let you handle complex workflows without central bottlenecks.
You must determine how messages carry instructions or data. A Command Message encapsulates a request to invoke a specific function or method in another application as an asynchronous message. SOAP and WSDL RPC-style requests carry method names and parameter values inside the message body XML. By turning a procedure call into a Command Message sent over a Point-to-Point Channel, you ensure the receiver executes the invocation reliably and locally. A Document Message reliably transfers a standalone data structure between applications without prescribing what action the receiver should take. A purchase order containing customer shipping data and items is transmitted as a JMS TextMessage containing XML. An Event Message transmits asynchronous notifications about state changes from a subject to interested observers. A B2B system sends an event message notifying other businesses that a computer disk drive price has changed.
Message Construction
You can manage message formats and large payloads effectively. The Claim Check pattern stores large message payloads in a persistent store and passes a small reference key instead. Checking luggage at an airport counter where the passenger receives a reference sticker on their ticket and retrieves the bags at the final destination illustrates this pattern.
- A message with data arrives.
- The Check Luggage component generates a unique key for the information.
- The Check Luggage component extracts the data from the message and stores it in a persistent store, such as a file or a database.
- It associates the stored data with the key.
- It removes the persisted data from the message and adds the Claim Check.
Advanced Routers
You coordinate complex flows using sophisticated routing elements. A Content-Based Router inspects the contents of a message and routes it to a specific destination channel based on predefined rules or criteria. A C# or MSMQ implementation checks if a message text starts with W to route it to widgetQueue, G for gadgetQueue, or sends it to a dunnoQueue.
- Receive the message from the input channel.
- Inspect the message content or fields.
- Evaluate the routing rules to determine the correct destination channel.
- Publish the message to the selected output channel.
A Process Manager uses a central processing unit to maintain the state of complex, non-linear sequences and determine subsequent steps based on intermediate results. Microsoft BizTalk Orchestration Manager receives an order message and executes two parallel activities for inventory and credit systems before continuing.
- Initialize a new process instance upon receiving a trigger message.
- Store the unique process identifier and current execution state.
- Send messages to processing units while including a correlation identifier.
- Receive replies, update process state, and evaluate business rules to determine the next step.
The Scatter-Gather pattern broadcasts a single request message to multiple potential recipients and then uses an Aggregator to collect and distill the responses back into a single cohesive response message. The Loan Broker example uses Scatter-Gather to route requests for loan quotes to multiple banks simultaneously and selects the best offer.
- Broadcast the request message to multiple recipients using a Recipient List or Publish-Subscribe Channel.
- Include a Return Address in the message so responses flow back consistently.
- Collect individual replies using an Aggregator component.
- Distill and combine the collected responses based on business rules into a single message.
5. Endpoints and Systems Management
Endpoints, control buses, and test messages secure your messaging infrastructure by monitoring quality of service metrics and isolating business logic.
Endpoints
Most applications access messaging infrastructure through vendor APIs involving concepts like open channel and send message, leading to tight coupling and complex asynchronous handling. A Messaging Gateway hides this infrastructure, allowing applications to use strongly typed domain methods like GetCreditScore.
A CreditBureauGateway in a .NET Loan Broker example wraps message queues and correlation IDs behind a GetCreditScore method.
- Encapsulate messaging-specific code and separate it from the rest of the application code.
- Expose meaningful business methods that accept strongly typed parameters.
- Choose between a blocking implementation that waits for replies or an event-driven implementation using callbacks and ACT.
- Catch messaging exceptions inside the gateway and throw application-specific exceptions instead.
A Transactional Client allows an application to explicitly control transaction boundaries with the messaging system to coordinate multiple message sends, receives, or database updates. Messaging systems use internal transactions to manage channels, but applications often need broader distributed transactions.
- Make the client's session with the messaging system transactional to specify transaction boundaries.
- Start a transaction before receiving or sending messages.
- Commit the transaction only after all related tasks succeed.
- Abort the transaction if an exception occurs to roll back consumption and return messages to the queue.
System Management
A Control Bus uses the messaging infrastructure with separate channels to transmit administrative and management data for components. It provides a centralized mechanism for configuration, heartbeats, test messages, exceptions, and statistics.
An instrumented loan broker uses a Control Bus and a simple management console to display the status of components in real time.
- Connect each component to both the application message flow and the Control Bus.
- Have components send periodic heartbeat messages at specified intervals.
- Channel exception conditions and statistics through the Control Bus to a central management console.
A Wire Tap is a fixed recipient list that publishes each incoming message to both the main channel and a secondary inspection channel. It allows monitoring and debugging of Point-to-Point channels without changing channel semantics.
- Insert a Wire Tap into the channel as a recipient list with two output channels.
- Base runtime calculations on the time when secondary messages were sent to avoid skewing by travel time.
Conclusion
Enterprise integration patterns provide a proven vocabulary and architectural guide to solving distributed integration problems using asynchronous messaging.
You can apply these architectural patterns systematically by following a disciplined design process.
- Analyze your integration requirements to identify communication boundaries, technical heterogeneity, and non-functional constraints between disparate applications.
- Select foundational messaging primitives such as message channels, pipes, and message endpoints to establish asynchronous communication foundations.
- Design routing and transformation logic using content-based routers and message translators to decouple message producers from consumers.
- Implement process managers and control bus mechanisms to monitor system health, handle failures, and orchestrate complex multi-step workflows.
- Continuously test your messaging infrastructure with mock endpoints and specialized test messages to verify quality of service under production loads.
10 Key Ideas
- Enterprise integration is difficult because it spans technical and political boundaries, requiring you to manage semantic differences and technical heterogeneity across legacy systems.
- To transform a tightly coupled integration into a loosely coupled one, systems must replace direct machine addresses with logical channels, use self-describing data formats, and queue requests to remove temporal dependencies.
- Messaging architectures rely on foundational elements such as message channels, discrete packets of data, and pipes and filters that transform and route information asynchronously.
- A Point-to-Point Channel ensures that each message placed on it is consumed by exactly one receiver, even if multiple receivers are listening.
- Guaranteed Delivery uses built-in local datastores to persist messages to disk so they survive system crashes or network outages.
- The Claim Check pattern stores large message payloads in a persistent store and passes a small reference key instead.
- A Content-Based Router inspects the contents of a message and routes it to a specific destination channel based on predefined rules or criteria.
- A Process Manager uses a central processing unit to maintain the state of complex, non-linear sequences and determine subsequent steps based on intermediate results.
- A Messaging Gateway hides this infrastructure, allowing applications to use strongly typed domain methods like GetCreditScore.
- A Control Bus uses the messaging infrastructure with separate channels to transmit administrative and management data for components.