From 31c1127dc249b45b6d1462668de2a825c34687bc Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Wed, 20 Aug 2008 01:00:48 +0000 Subject: [PATCH] Updated the individual channel sections and the Message Bus section. --- spring-integration-reference/src/core-api.xml | 77 +++++++++++-------- 1 file changed, 47 insertions(+), 30 deletions(-) diff --git a/spring-integration-reference/src/core-api.xml b/spring-integration-reference/src/core-api.xml index 1633b68a37..2121b0f060 100644 --- a/spring-integration-reference/src/core-api.xml +++ b/spring-integration-reference/src/core-api.xml @@ -269,9 +269,10 @@ boolean unsubscribe(MessageTarget target); Document Messages which are generally intended to be processed by a single consumer. 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 receive - Messages by invoking receive(). Instead, any subscriber must - be a MessageTarget itself, and the subscriber's + 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 MessageTarget itself, and the subscriber's send(Message) method will be invoked in turn. @@ -300,7 +301,7 @@ boolean unsubscribe(MessageTarget target); 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' property within each message's header. However, for custom priority determination + '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. @@ -330,8 +331,10 @@ boolean unsubscribe(MessageTarget target); 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. In other words, it also dispatches Messages directly but only to a single receiver. Its - primary purpose is to enable a single thread to perform the operations on "both sides" of the channel. For + described above. In other words, it does not implement the PollableChannel + interface, but rather dispatches Messages directly to a subscriber. As a point-to-point channel, however, + it will only send each Message to a single subscribed MessageTarget. + Its primary purpose is to enable a single thread to perform the operations on "both sides" of the channel. For example, if a receiving target is subscribed to a DirectChannel, then sending a Message to that channel will trigger invocation of that target's send(Message) method directly in the sender's thread. The key motivation for providing a channel @@ -350,7 +353,7 @@ boolean unsubscribe(MessageTarget target); 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 could collect its replies. + ThreadLocalChannel, the original sending thread can collect its replies from it. @@ -365,30 +368,37 @@ boolean unsubscribe(MessageTarget target); the send and receive operations. The ChannelInterceptor strategy interface provides methods for each of those operations: message, MessageChannel channel); + + Message preSend(Message message, MessageChannel channel); + void postSend(Message message, MessageChannel channel, boolean sent); + boolean preReceive(MessageChannel channel); - void postReceive(Message message, MessageChannel channel); + + Message postReceive(Message message, MessageChannel channel); }]]> After implementing the interface, registering the interceptor with a channel is just a matter of calling: channel.addInterceptor(someChannelInterceptor); - The methods that return a boolean value can return 'false' to prevent the - send or receive operation from proceeding (send would return 'false' and receive would return 'null'). + The methods that return a Message instance can be used for transforming the Message or can return 'null' + to prevent further processing (of course, any of the methods can throw an Exception). Also, the + preReceive method can return 'false' to prevent the receive + operation from proceeding. Because it is rarely necessary to implement all of the interceptor methods, a ChannelInterceptorAdapter class is also available for sub-classing. It provides no-op - methods (the void methods are empty, and the boolean methods return - true). Therefore, it is often easiest to extend that class and just implement the method(s) - that you need as in the following example. + methods (the void method is empty, the Message returning methods + return the Message parameter as-is, and the boolean method returns true). + Therefore, it is often easiest to extend that class and just implement the method(s) that you need as in the + following example. message, MessageChannel channel) { + public Message preSend(Message message, MessageChannel channel) { sendCount.incrementAndGet(); - return true; + return message; } }]]> @@ -413,17 +423,22 @@ boolean unsubscribe(MessageTarget target);
MessageBus - So far, you have seen that the MessageChannel provides a - receive() method that returns a Message, and the - MessageHandler provides a handle() method that accepts a - Message, but how do the messages get passed from the channel to the handler? - As mentioned earlier, the MessageBus provides a runtime form of inversion of control, and - one of the primary responsibilities that it assumes is connecting the channels to the handlers. It also connects - MessageSources and MessageTargets to channels, and it manages the scheduling of pollers and dispatchers. + So far, you have seen that the PollableChannel provides a + receive() method that returns a Message, the subscribable + MessageChannels invoke one or more subscribers directly, and the MessageHandler + provides a handle() method that accepts a Message. + However, we have not yet discussed how messages get passed from a channel to a handler. As mentioned earlier, + the MessageBus provides a runtime form of inversion of control, and one of the primary + responsibilities that it assumes is connecting the channels to the handlers. It also connects MessageSources and + MessageTargets to channels (thereby creating Channel Adapters), and it manages the scheduling of polling + dispatchers. Ultimately, every MessageHandler should be invoked as if it is an event-driven consumer, and this + works fine when the handler's input source is a SubscribableSource. However, the + bus creates and manages these polling dispatchers so that even when handlers receive input from a + PollableSource, they will still behave as event-driven consumers. - The MessageBus is an example of a mediator. It performs a number of roles - mostly - by delegating to other strategies. One of its main responsibilities is to manage registration of the + The MessageBus is an example of a mediator. It performs a number of roles - + mostly by delegating to other strategies. One of its main responsibilities is to manage registration of the MessageChannels and endpoints, such as Channel Adapters and Service Activators. It recognizes any of these instances that have been defined within its ApplicationContext. @@ -437,11 +452,13 @@ boolean unsubscribe(MessageTarget target); (we will look at examples of both configuration options shortly). - The bus creates and schedules triggers for all of its registered endpoints. When an endpoint - receives a trigger event, it will poll the MessageSource that - was provided in its metadata. For example, a Channel Adapter will poll the - referenced "source", and a Service Activator will poll the referenced - "input-channel". + The bus is responsible for activating all of its registered endpoints by connecting them to channels within + its registry, and if necessary scheduling a poller so that the endpoint can be event-driven even when connected + to a channel that requires polling. For example, the poller for an outbound Channel Adapter + will poll the referenced "channel", and the poller for a Service Activator will poll the + referenced "input-channel". If that "channel" or "input-channel" is subscribable rather than pollable, the bus + will simply activate the subscription. The important point is that the endpoint itself does not need to know + whether its source is pollable or subscribable.