diff --git a/src/reference/asciidoc/aggregator.adoc b/src/reference/asciidoc/aggregator.adoc index 06682efa54..579ffbe830 100644 --- a/src/reference/asciidoc/aggregator.adoc +++ b/src/reference/asciidoc/aggregator.adoc @@ -161,17 +161,11 @@ public interface ReleaseStrategy { In general, any POJO can implement the completion decision logic if it provides a method that accepts a single `java.util.List` as an argument (parameterized lists are supported as well), and returns a boolean value. This method will be invoked after the arrival of each new message, to decide whether the group is complete or not, as follows: -if the argument is a `java.util.List`, and the parameter type T is assignable to `Message`, then the whole list of messages accumulated in the group will be sent to the method - - - -if the argument is a non-parametrized `java.util.List` or the parameter type is not assignable to `Message`, then the method will receive the payloads of the accumulated messages - - - -the method must return true if the message group is ready for aggregation, and false otherwise. +* if the argument is a `java.util.List`, and the parameter type T is assignable to `Message`, then the whole list of messages accumulated in the group will be sent to the method +* if the argument is a non-parametrized `java.util.List` or the parameter type is not assignable to `Message`, then the method will receive the payloads of the accumulated messages +* the method must return true if the message group is ready for aggregation, and false otherwise. For example: @@ -222,7 +216,7 @@ To avoid such situations, you should consider configuring a `MessageGroupStoreRe For information about configuring a reaper, see <>. Spring Integration provides an out-of-the box implementation for `ReleaseStrategy`, the `SequenceSizeReleaseStrategy`. -This implementation consults the SEQUENCE_NUMBER and SEQUENCE_SIZE headers of each arriving message to decide when a message group is complete and ready to be aggregated. +This implementation consults the `SEQUENCE_NUMBER` and `SEQUENCE_SIZE` headers of each arriving message to decide when a message group is complete and ready to be aggregated. As shown above, it is also the default strategy. ===== CorrelationStrategy @@ -239,14 +233,14 @@ public interface CorrelationStrategy { ---- The method returns an Object which represents the correlation key used for associating the message with a message group. -The key must satisfy the criteria used for a key in a Map with respect to the implementation of equals() and hashCode(). +The key must satisfy the criteria used for a key in a Map with respect to the implementation of `equals()` and `hashCode()`. In general, any POJO can implement the correlation logic, and the rules for mapping a message to a method's argument (or arguments) are the same as for a `ServiceActivator` (including support for @Header annotations). The method must return a value, and the value must not be `null`. Spring Integration provides an out-of-the box implementation for `CorrelationStrategy`, the `HeaderAttributeCorrelationStrategy`. This implementation returns the value of one of the message headers (whose name is specified by a constructor argument) as the correlation key. -By default, the correlation strategy is a `HeaderAttributeCorrelationStrategy` returning the value of the CORRELATION_ID header attribute. +By default, the correlation strategy is a `HeaderAttributeCorrelationStrategy` returning the value of the `CORRELATION_ID` header attribute. If you have a custom header name you would like to use for correlation, then simply configure that on an instance of `HeaderAttributeCorrelationStrategy` and provide that as a reference for the Aggregator's correlation-strategy. ===== LockRegistry @@ -517,7 +511,7 @@ If the group is not released by the release strategy during timeout, then the ex Timed-out groups are either discarded, or a partial release occurs (based on `send-partial-result-on-expiry`). ===== -Using a `ref` attribute is generally recommended if a custom aggregator handler implementation may be referenced in other`` definitions. +Using a `ref` attribute is generally recommended if a custom aggregator handler implementation may be referenced in other `` definitions. However if a custom aggregator implementation is only being used by a single definition of the ``, you can use an inner bean definition (starting with version 1.0.3) to configure the aggregation POJO within the `` element: [source,xml] ---- @@ -542,7 +536,6 @@ public class PojoAggregator { } return total; } - } ---- @@ -685,7 +678,6 @@ public class Waiter { public String correlateBy(OrderItem item) { ... } - } ---- diff --git a/src/reference/asciidoc/channel.adoc b/src/reference/asciidoc/channel.adoc index 0c8284ec7d..47bc7ff036 100644 --- a/src/reference/asciidoc/channel.adoc +++ b/src/reference/asciidoc/channel.adoc @@ -68,7 +68,7 @@ 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). +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. Prior to version 3.0, invoking the send method on a `PublishSubscribeChannel` that had no subscribers returned `false`. @@ -144,7 +144,7 @@ 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 exposed via _load-balancer_ or _load-balancer-ref_ attributes (mutually exclusive). The load balancing strategy is used by the Message Dispatcher to help determine how Messages are distributed amongst Message Handlers in the case that there are multiple Message Handlers subscribed to the same channel. -As a convinience the _load-balancer_ attribute exposes enumeration of values pointing to pre-existing implementations of `LoadBalancingStrategy`. +As a convenience the _load-balancer_ attribute exposes enumeration of values pointing to pre-existing implementations of `LoadBalancingStrategy`. The "round-robin" (load-balances across the handlers in rotation) and "none" (for the cases where one wants to explicitely disable load balancing) are the only available values. Other strategy implementations may be added in future versions. However, since version 3.0 you can provide your own implementation of the `LoadBalancingStrategy` and inject it using _load-balancer-ref_ attribute which should point to a bean that implements `LoadBalancingStrategy`. @@ -254,7 +254,7 @@ NOTE: Keep in mind that `receive()` calls are only relevant for `PollableChannel In fact the `SubscribableChannel` interface does not even define a `receive()` method. The reason for this is that when a Message is sent to a `SubscribableChannel` it will be sent directly to one or more subscribers depending on the type of channel (e.g. a PublishSubscribeChannel sends to all of its subscribers). -Therefore, the `preReceive(..)` and `postReceive(..)` interceptor methods are only invoked when the interceptor is applied to a `PollableChannel`. +Therefore, the `preReceive(..)`, `postReceive(..)` and `afterReceiveCompletion(..)` interceptor methods are only invoked when the interceptor is applied to a `PollableChannel`. Spring Integration also provides an implementation of the http://eaipatterns.com/WireTap.html[Wire Tap] pattern. It is a simple interceptor that sends the Message to another channel without otherwise altering the existing flow. @@ -336,15 +336,15 @@ To create a Message Channel instance, you can use the element: ---- The default channel type is _Point to Point_. -To create a _Publish Subscribe_ channel, use the element: +To create a _Publish Subscribe_ channel, use the `` element: [source,xml] ---- ---- -When using the element without any sub-elements, it will create a `DirectChannel` instance (a `SubscribableChannel`). +When using the `` element without any sub-elements, it will create a `DirectChannel` instance (a `SubscribableChannel`). -However, you can alternatively provide a variety of sub-elements to create any of the pollable channel types (as described in<>). +However, you can alternatively provide a variety of `` sub-elements to create any of the pollable channel types (as described in <>). Examples of each are shown below. [[channel-configuration-directchannel]] @@ -358,7 +358,7 @@ As mentioned above, `DirectChannel` is the default type. ---- A default channel will have a _round-robin_ load-balancer and will also have failover enabled (See the discussion in <> for more detail). -To disable one or both of these, add a sub-element and configure the attributes: +To disable one or both of these, add a `` sub-element and configure the attributes: [source,xml] ---- @@ -396,7 +396,7 @@ Multiple types can be provided as a comma-delimited list: ---- So the 'numberChannel' above will only accept Messages with a data-type of `java.lang.Number`. -But what happens if the payload of the Message is not of the required type? It depends on whether you have defined a bean named "integrationConversionService" that is an instance of Spring's http://static.springsource.org/spring/docs/current/spring-framework-reference/html/validation.html#core-convert-ConversionService-API[Conversion Service]. +But what happens if the payload of the Message is not of the required type? It depends on whether you have defined a bean named `integrationConversionService` that is an instance of Spring's http://static.springsource.org/spring/docs/current/spring-framework-reference/html/validation.html#core-convert-ConversionService-API[Conversion Service]. If not, then an Exception would be thrown immediately, but if you do have an "integrationConversionService" bean defined, it will be used in an attempt to convert the Message's payload to the acceptable type. You can even register custom converters. @@ -425,9 +425,9 @@ All we need to do is implement a Converter. [source,java] ---- public static class StringToIntegerConverter implements Converter { - public Integer convert(String source) { - return Integer.parseInt(source); - } + public Integer convert(String source) { + return Integer.parseInt(source); + } } ---- @@ -518,7 +518,7 @@ public BasicMessageGroupStore mongoDbChannelMessageStore(MongoDbFactory mongoDbF @Bean public PollableChannel priorityQueue(BasicMessageGroupStore mongoDbChannelMessageStore) { - return new QueueChannel(new MessageGroupQueue(mongoDbChannelMessageStore, "priorityQueue")); + return new QueueChannel(new MessageGroupQueue(mongoDbChannelMessageStore, "priorityQueue")); } ---- @@ -724,7 +724,7 @@ The default value for `order` will be 0 and for `pattern`, the default is '*' (t ===== Wire Tap As mentioned above, Spring Integration provides a simple _Wire Tap_ interceptor out of the box. -You can configure a _Wire Tap_ on any channel within an element. +You can configure a _Wire Tap_ on any channel within an `` element. This is especially useful for debugging, and can be used in conjunction with Spring Integration's logging Channel Adapter as follows: [source,xml] ---- diff --git a/src/reference/asciidoc/codec.adoc b/src/reference/asciidoc/codec.adoc index 40dd99efaa..718ff354ea 100644 --- a/src/reference/asciidoc/codec.adoc +++ b/src/reference/asciidoc/codec.adoc @@ -58,17 +58,18 @@ serializer that is aware of the object's structure and can directly serialize se [source,java] ---- public class AddressSerializer extends Serializer
{ - @Override - public void write(Kryo kryo, Output output, Address address) { - output.writeString(address.getStreet()); - output.writeString(address.getCity()); - output.writeString(address.getCountry()); - } - @Override - public Address read(Kryo kryo, Input input, Class
type) { - return new Address(input.readString(),input.readString(),input.readString()); - } + @Override + public void write(Kryo kryo, Output output, Address address) { + output.writeString(address.getStreet()); + output.writeString(address.getCity()); + output.writeString(address.getCountry()); + } + + @Override + public Address read(Kryo kryo, Input input, Class
type) { + return new Address(input.readString(), input.readString(), input.readString()); + } } ---- @@ -103,21 +104,21 @@ registering a custom serializer explicitly: [source,java] ---- public class Address implements KryoSerializable { - ... + ... - @Override - public void write(Kryo kryo, Output output) { - output.writeString(this.street); - output.writeString(this.city); - output.writeString(this.country); - } + @Override + public void write(Kryo kryo, Output output) { + output.writeString(this.street); + output.writeString(this.city); + output.writeString(this.country); + } - @Override - public void read(Kryo kryo, Input input) { - this.street = input.readString(); - this.city = input.readString(); - this.country = input.readString(); - } + @Override + public void read(Kryo kryo, Input input) { + this.street = input.readString(); + this.city = input.readString(); + this.country = input.readString(); + } } ---- diff --git a/src/reference/asciidoc/content-enrichment.adoc b/src/reference/asciidoc/content-enrichment.adoc index f4810e6d39..914156eb28 100644 --- a/src/reference/asciidoc/content-enrichment.adoc +++ b/src/reference/asciidoc/content-enrichment.adoc @@ -36,8 +36,8 @@ It is exposed via the `` element. [source,xml] ---- - - + + ---- @@ -46,12 +46,12 @@ The _Header Enricher_ also provides helpful sub-elements to set well-known heade [source,xml] ---- - - - - - - + + + + + + ---- @@ -79,10 +79,10 @@ Let's look at the following configuration: [source,java] ---- public class MyBean { + public String computeValue(String payload){ return payload.toUpperCase() + "_US"; } - } ---- @@ -91,9 +91,9 @@ You can also configure your POJO as inner bean: [source,xml] ---- - - - + + + ---- @@ -102,9 +102,9 @@ as well as point to a Groovy script: [source,xml] ---- - - - + + + ---- @@ -119,7 +119,7 @@ That is where SpEL shows its true power. [source,xml] ---- - + ---- @@ -146,13 +146,13 @@ public HeaderEnricher enrichHeaders() { @Bean @Transformer(inputChannel="enrichHeadersChannel", outputChannel="emailChannel") public HeaderEnricher enrichHeaders() { - Map> headersToAdd = new HashMap<>(); - headersToAdd.put("emailUrl", new StaticHeaderValueMessageProcessor(this.imapUrl)); - Expression expression = new SpelExpressionParser().parseExpression("payload.from[0].toString()"); - headersToAdd.put("from", - new ExpressionEvaluatingHeaderValueMessageProcessor<>(expression, String.class)); - HeaderEnricher enricher = new HeaderEnricher(headersToAdd); - return enricher; + Map> headersToAdd = new HashMap<>(); + headersToAdd.put("emailUrl", new StaticHeaderValueMessageProcessor(this.imapUrl)); + Expression expression = new SpelExpressionParser().parseExpression("payload.from[0].toString()"); + headersToAdd.put("from", + new ExpressionEvaluatingHeaderValueMessageProcessor<>(expression, String.class)); + HeaderEnricher enricher = new HeaderEnricher(headersToAdd); + return enricher; } ---- @@ -205,11 +205,11 @@ This sub-element is a convenience only, and is the equivalent of specifying: [source,xml] ---- + expression="@integrationHeaderChannelRegistry.channelToChannelName(headers.replyChannel)" + overwrite="true" /> + expression="@integrationHeaderChannelRegistry.channelToChannelName(headers.errorChannel)" + overwrite="true" /> ---- Starting with _version 4.1_, you can now override the registry's configured reaper delay, so the the channel mapping is retained for at least the specified time, regardless of the reaper delay: @@ -217,12 +217,12 @@ Starting with _version 4.1_, you can now override the registry's configured reap [source,xml] ---- - + - + ---- @@ -381,14 +381,14 @@ Through the implicitly set `reply-channel` a `User` object is returned and using ---- NOTE: The code samples shown here, are part of the _Spring - Integration Samples_ project. + Integration Samples_ project. Please feel free to check it out at:null _How do I pass only a subset of data to the request channel?_ Using a `request-payload-expression` attribute a single property of the payload can be passed on to the request channel instead of the full message. In the example below on the username property is passed on to the request channel. -Keep in mind, that alwhough only the username is passed on, the resulting message send to the request channel will contain the full set of `MessageHeaders`. +Keep in mind, that although only the username is passed on, the resulting message send to the request channel will contain the full set of `MessageHeaders`. [source,xml] ---- @@ -414,7 +414,7 @@ The reply contains a full `User` object, which is ultimately added to the `Map` input-channel="findUserWithMapEnricherChannel" request-channel="findUserByUsernameServiceChannel" request-payload-expression="payload.username"> - + ---- diff --git a/src/reference/asciidoc/logging-adapter.adoc b/src/reference/asciidoc/logging-adapter.adoc index e413be76cc..39c9d46ed4 100644 --- a/src/reference/asciidoc/logging-adapter.adoc +++ b/src/reference/asciidoc/logging-adapter.adoc @@ -1,7 +1,7 @@ [[logging-channel-adapter]] === Logging Channel Adapter -The `` is often used in conjunction with a Wire Tap, as discussed in<>. +The `` is often used in conjunction with a Wire Tap, as discussed in <>. However, it can also be used as the ultimate consumer of any flow. For example, consider a flow that ends with a `` that returns a result, but you wish to discard that result. To do that, you could send the result to `NullChannel`. @@ -12,11 +12,11 @@ With a `NullChannel`, you would only see the discarded message when logging at ` ---- - level="INFO" <2> - expression="" <3> - log-full-message="false" <4> - logger-name="" /> <5> + channel="" <1> + level="INFO" <2> + expression="" <3> + log-full-message="false" <4> + logger-name="" /> <5> ---- diff --git a/src/reference/asciidoc/metrics.adoc b/src/reference/asciidoc/metrics.adoc index c8e69e663c..110a55a54d 100644 --- a/src/reference/asciidoc/metrics.adoc +++ b/src/reference/asciidoc/metrics.adoc @@ -40,12 +40,12 @@ A number of options are available: @Configuration @EnableIntegration @EnableIntegrationManagement( - defaultLoggingEnabled = "false", <1> - defaultCountsEnabled = "false", <2> - defaultStatsEnabled = "false", <3> - countsEnabled = { "foo", "${count.patterns}" }, <4> - statsEnabled = { "qux", "!*" }, <5> - MetricsFactory = "myMetricsFactory") <6> + defaultLoggingEnabled = "false", <1> + defaultCountsEnabled = "false", <2> + defaultStatsEnabled = "false", <3> + countsEnabled = { "foo", "${count.patterns}" }, <4> + statsEnabled = { "qux", "!*" }, <5> + MetricsFactory = "myMetricsFactory") <6> public static class ContextConfiguration { ... } diff --git a/src/reference/asciidoc/resequencer.adoc b/src/reference/asciidoc/resequencer.adoc index 04478b1a68..8b7c0a2446 100644 --- a/src/reference/asciidoc/resequencer.adoc +++ b/src/reference/asciidoc/resequencer.adoc @@ -8,10 +8,10 @@ Related to the Aggregator, albeit different from a functional standpoint, is the [[resequencer-functionality]] ==== Functionality -The Resequencer works in a similar way to the Aggregator, in the sense that it uses the CORRELATION_ID to store messages in groups, the difference being that the Resequencer does not process the messages in any way. -It simply releases them in the order of their SEQUENCE_NUMBER header values. +The Resequencer works in a similar way to the Aggregator, in the sense that it uses the `CORRELATION_ID` to store messages in groups, the difference being that the Resequencer does not process the messages in any way. +It simply releases them in the order of their `SEQUENCE_NUMBER` header values. -With respect to that, the user might opt to release all messages at once (after the whole sequence, according to the SEQUENCE_SIZE, has been released), or as soon as a valid sequence is available. +With respect to that, the user might opt to release all messages at once (after the whole sequence, according to the `SEQUENCE_SIZE`, has been released), or as soon as a valid sequence is available. ==== Configuring a Resequencer diff --git a/src/reference/asciidoc/splitter.adoc b/src/reference/asciidoc/splitter.adoc index 8a64a11875..4bdc1cfa3b 100644 --- a/src/reference/asciidoc/splitter.adoc +++ b/src/reference/asciidoc/splitter.adoc @@ -9,8 +9,8 @@ Very often, they are upstream producers in a pipeline that includes an Aggregato ==== Programming model -The API for performing splitting consists of one base class, `AbstractMessageSplitter`, which is a `MessageHandler` implementation, encapsulating features which are common to splitters, such as filling in the appropriate message headers CORRELATION_ID, SEQUENCE_SIZE, and SEQUENCE_NUMBER on the messages that are produced. -This enables tracking down the messages and the results of their processing (in a typical scenario, these headers would be copied over to the messages that are produced by the various transforming endpoints), and use them, for example, in ahttp://www.eaipatterns.com/DistributionAggregate.html[Composed Message Processor] scenario. +The API for performing splitting consists of one base class, `AbstractMessageSplitter`, which is a `MessageHandler` implementation, encapsulating features which are common to splitters, such as filling in the appropriate message headers `CORRELATION_ID`, `SEQUENCE_SIZE`, and `SEQUENCE_NUMBER` on the messages that are produced. +This enables tracking down the messages and the results of their processing (in a typical scenario, these headers would be copied over to the messages that are produced by the various transforming endpoints), and use them, for example, in a http://www.eaipatterns.com/DistributionAggregate.html[Composed Message Processor] scenario. An excerpt from `AbstractMessageSplitter` can be seen below: @@ -27,7 +27,7 @@ public abstract class AbstractMessageSplitter To implement a specific Splitter in an application, extend `AbstractMessageSplitter` and implement the `splitMessage` method, which contains logic for splitting the messages. The return value may be one of the following: -* A `Collection` or an array of Messages, or an `Iterable` (or `Iterator`) that iterates over Messages - in this case the messages will be sent as such (after the CORRELATION_ID, SEQUENCE_SIZE and SEQUENCE_NUMBER are populated). +* A `Collection` or an array of Messages, or an `Iterable` (or `Iterator`) that iterates over Messages - in this case the messages will be sent as such (after the `CORRELATION_ID`, `SEQUENCE_SIZE` and `SEQUENCE_NUMBER` are populated). Using this approach gives more control to the developer, for example for populating custom message headers as part of the splitting process. * A `Collection` or an array of non-Message objects, or an `Iterable` (or `Iterator`) that iterates over non-Message objects - works like the prior case, except that each collection element will be used as a Message payload. @@ -107,7 +107,7 @@ However if the custom splitter handler implementation should be scoped to a sing - + ---- NOTE: Using both a `ref` attribute and an inner handler definition in the same `` configuration is not allowed, as it creates an ambiguous condition and will result in an Exception being thrown.