Spring Integration provides several different Message Channel implementations. Each is briefly described in the sections below.
        The PublishSubscribeChannel implementation broadcasts any Message
        sent to it to all of its subscribed handlers. This is most often used for sending
        Event Messages whose primary role is notification as opposed to
        Document Messages which are generally intended to be processed by
        a single handler. Note that the PublishSubscribeChannel is
        intended for sending only. Since it broadcasts to its subscribers directly when its
        send(Message) method is invoked, consumers cannot poll for
        Messages (it does not implement PollableChannel and
        therefore has no receive() method). Instead, any subscriber
        must be a MessageHandler itself, and the subscriber's
        handleMessage(Message) method will be invoked in turn.
      
        The QueueChannel implementation wraps a queue. Unlike, the
        PublishSubscribeChannel, the QueueChannel has point-to-point
        semantics. In other words, even if the channel has multiple consumers, only one of them should receive any
        Message sent to that channel. It provides a default no-argument constructor (providing an essentially unbounded
        capacity of Integer.MAX_VALUE) as well as a constructor that accepts the queue capacity:
        
public QueueChannel(int capacity)
        A channel that has not reached its capacity limit will store messages in its internal queue, and the
        send() method will return immediately even if no receiver is ready to handle the
        message. If the queue has reached capacity, then the sender will block until room is available. Or, if using
        the send call that accepts a timeout, it will block until either room is available or the timeout period
        elapses, whichever occurs first. Likewise, a receive call will return immediately if a message is available
        on the queue, but if the queue is empty, then a receive call may block until either a message is available
        or the timeout elapses. In either case, it is possible to force an immediate return regardless of the
        queue's state by passing a timeout value of 0. The no-argument send and receive methods block indefinitely.
        Note however, that calling the no-arg versions of send() and
        receive() will block indefinitely.
      
        Whereas the QueueChannel enforces first-in/first-out (FIFO) ordering, the
        PriorityChannel is an alternative implementation that allows for messages
        to be ordered within the channel based upon a priority. By default the priority is determined by the
        'priority' header within each message. However, for custom priority determination
        logic, a comparator of type Comparator<Message<?>> can be provided
        to the PriorityChannel's constructor.
      
        The RendezvousChannel enables a "direct-handoff" scenario where a sender will block
        until another party invokes the channel's receive() method or vice-versa. Internally,
        this implementation is quite similar to the QueueChannel except that it uses a
        SynchronousQueue (a zero-capacity implementation of
        BlockingQueue). This works well in situations where the sender and receiver are
        operating in different threads but simply dropping the message in a queue asynchronously is not appropriate.
        In other words, with a RendezvousChannel at least the sender knows that some receiver
        has accepted the message, whereas with a QueueChannel, the message would have been
        stored to the internal queue and potentially never received.
      
![]()  | Tip | 
|---|---|
          Keep in mind that all of these queue-based channels are storing messages in-memory only. When persistence
          is required, you can either invoke a database operation within a handler or use Spring Integration's
          support for JMS-based Channel Adapters. The latter option allows you to take advantage of any JMS provider's
          implementation for message persistence, and it will be discussed in Chapter 18, JMS Support. However, when
          buffering in a queue is not necessary, the simplest approach is to rely upon the
            | 
        The RendezvousChannel is also useful for implementing request-reply
        operations. The sender can create a temporary, anonymous instance of RendezvousChannel
        which it then sets as the 'replyChannel' header when building a Message. After sending that Message, the sender
        can immediately call receive (optionally providing a timeout value) in order to block while waiting for a reply
        Message. This is very similar to the implementation used internally by many of Spring Integration's
        request-reply components.
      
        The DirectChannel has point-to-point semantics but otherwise is more similar to the
        PublishSubscribeChannel than any of the queue-based channel implementations described
        above. It implements the SubscribableChannel interface instead of the
        PollableChannel interface, so it dispatches Messages directly to a subscriber.
        As a point-to-point channel, however, it differs from the PublishSubscribeChannel in
        that it will only send each Message to a single subscribed
        MessageHandler.
      
        In addition to being the simplest point-to-point channel option, one of its most important features is that
        it enables a single thread to perform the operations on "both sides" of the channel. For example, if a handler
        is subscribed to a DirectChannel, then sending a Message to that channel will trigger
        invocation of that handler's handleMessage(Message) method directly in the
        sender's thread, before the send() method invocation can return.
      
The key motivation for providing a channel implementation with this behavior is to support transactions that must span across the channel while still benefiting from the abstraction and loose coupling that the channel provides. If the send call is invoked within the scope of a transaction, then the outcome of the handler's invocation (e.g. updating a database record) will play a role in determining the ultimate result of that transaction (commit or rollback).
![]()  | Note | 
|---|---|
          Since the DirectChannel is the simplest option and does not add any additional
          overhead that would be required for scheduling and managing the threads of a poller, it is the default
          channel type within Spring Integration. The general idea is to define the channels for an application and
          then to consider which of those need to provide buffering or to throttle input, and then modify those to
          be queue-based PollableChannels. Likewise, if a channel needs to broadcast
          messages, it should not be a DirectChannel but rather a
          PublishSubscribeChannel. Below you will see how each of these can be configured.
         | 
        The DirectChannel internally delegates to a Message Dispatcher to invoke its
        subscribed Message Handlers, and that dispatcher can have a load-balancing strategy. The load-balancer
        determines how invocations will be ordered in the case that there are multiple handlers subscribed to the
        same channel. When using the namespace support described below, the default strategy is
        "round-robin" which essentially load-balances across the handlers in rotation.
        
![]()  | Note | 
|---|---|
| The "round-robin" strategy is currently the only implementation available out-of-the-box in Spring Integration. Other strategy implementations may be added in future versions. | 
The load-balancer also works in combination with a boolean failover property. If the "failover" value is true (the default), then the dispatcher will fall back to any subsequent handlers as necessary when preceding handlers throw Exceptions. The order is determined by an optional order value defined on the handlers themselves or, if no such value exists, the order in which the handlers are subscribed.
If a certain situation requires that the dispatcher always try to invoke the first handler, then fallback in the same fixed order sequence every time an error occurs, no load-balancing strategy should be provided. In other words, the dispatcher still supports the failover boolean property even when no load-balancing is enabled. Without load-balancing, however, the invocation of handlers will always begin with the first according to their order. For example, this approach works well when there is a clear definition of primary, secondary, tertiary, and so on. When using the namespace support, the "order" attribute on any endpoint will determine that order.
![]()  | Note | 
|---|---|
| Keep in mind that load-balancing and failover only apply when a channel has more than one subscribed Message Handler. When using the namespace support, this means that more than one endpoint shares the same channel reference in the "input-channel" attribute. | 
        The ExecutorChannel is a point-to-point channel that supports
        the same dispatcher configuration as DirectChannel (load-balancing strategy
        and the failover boolean property). The key difference between these two dispatching channel types
        is that the ExecutorChannel delegates to an instance of
        TaskExecutor to perform the dispatch. This means that the send method
        typically will not block, but it also means that the handler invocation may not occur in the sender's
        thread. It therefore does not support transactions spanning the sender and receiving
        handler.
        
![]()  | Tip | 
|---|---|
	      Note that there are occasions where the sender may block. For example, when using a
	      TaskExecutor with a rejection-policy that throttles back on the client (such as the
          ThreadPoolExecutor.CallerRunsPolicy), the sender's thread will execute
          the method directly anytime the thread pool is at its maximum capacity and the
          executor's work queue is full. Since that situation would only occur in a non-predictable
          way, that obviously cannot be relied upon for transactions.
         | 
        The final channel implementation type is ThreadLocalChannel. This channel also delegates
        to a queue internally, but the queue is bound to the current thread. That way the thread that sends to the
        channel will later be able to receive those same Messages, but no other thread would be able to access them.
        While probably the least common type of channel, this is useful for situations where
        DirectChannels are being used to enforce a single thread of operation but any reply
        Messages should be sent to a "terminal" channel. If that terminal channel is a
        ThreadLocalChannel, the original sending thread can collect its replies from it.