diff --git a/build.gradle b/build.gradle index ec97b25390..9ba3ab3144 100644 --- a/build.gradle +++ b/build.gradle @@ -140,7 +140,7 @@ subprojects { subproject -> springSocialTwitterVersion = '1.1.0.RELEASE' springRetryVersion = '1.1.2.RELEASE' springVersion = project.hasProperty('springVersion') ? project.springVersion : '4.2.0.RELEASE' - springWsVersion = '2.2.1.RELEASE' + springWsVersion = '2.2.2.RELEASE' xmlUnitVersion = '1.5' xstreamVersion = '1.4.7' zookeeperVersion = '3.4.6' diff --git a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/inbound/InboundEndpointTests.java b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/inbound/InboundEndpointTests.java index 5778c020b7..d0684f43d8 100644 --- a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/inbound/InboundEndpointTests.java +++ b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/inbound/InboundEndpointTests.java @@ -33,8 +33,6 @@ import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import com.rabbitmq.client.Channel; - import org.springframework.amqp.core.AcknowledgeMode; import org.springframework.amqp.core.MessageProperties; import org.springframework.amqp.rabbit.connection.Connection; @@ -62,6 +60,8 @@ import org.springframework.messaging.Message; import org.springframework.messaging.PollableChannel; import org.springframework.messaging.support.GenericMessage; +import com.rabbitmq.client.Channel; + /** * @author Artem Bilan * @author Gary Russell diff --git a/src/reference/asciidoc/aggregator.adoc b/src/reference/asciidoc/aggregator.adoc index d57f6df7af..30c2c00fc4 100644 --- a/src/reference/asciidoc/aggregator.adoc +++ b/src/reference/asciidoc/aggregator.adoc @@ -205,7 +205,7 @@ Partial sequences can be released by using a `MessageGroupStoreReaper` together IMPORTANT: To facilitate discarding of late-arriving messages, the aggregator must maintain state about the group after it has been released. This can eventually cause out of memory conditions. To avoid such situations, you should consider configuring a `MessageGroupStoreReaper` to remove the group metadata; the expiry parameters should be set to expire groups after it is not expected that late messages will arrive. -For information about configuring a reaper, see<>. +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. @@ -694,6 +694,32 @@ All of the configuration options provided by the xml element are also available The aggregator can be either referenced explicitly from XML or, if the @MessageEndpoint is defined on the class, detected automatically through classpath scanning. +Annotation configuration (`@Aggregator` and others) for the Aggregator component covers only simple use cases, +where most default options are sufficient. +If you need more control over those options using Annotation configuration, consider using +a `@Bean` definition for the `AggregatingMessageHandler` and mark its +`@Bean` method with `@ServiceActivator`: + +[source,java] +---- +@ServiceActivator(inputChannel = "aggregatorChannel") +@Bean +public MessageHandler aggregator(MessageGroupStore jdbcMessageGroupStore) { + AggregatingMessageHandler aggregator = + new AggregatingMessageHandler(new DefaultAggregatingMessageGroupProcessor(), + jdbcMessageGroupStore); + aggregator.setOutputChannel(resultsChannel()); + aggregator.setGroupTimeoutExpression(new ValueExpression<>(500L)); + aggregator.setTaskScheduler(this.taskScheduler); + return aggregator; +} +---- + +See <> and <> for more information. + +NOTE: Starting with the _version 4.2_ the `AggregatorFactoryBean` is available, to simplify Java configuration +for the `AggregatingMessageHandler`. + [[reaper]] ==== Managing State in an Aggregator: MessageGroupStore @@ -729,7 +755,7 @@ public interface MessageGroupStore { } ---- -For more information please refer to the http://static.springsource.org/spring-integration/api/org/springframework/integration/store/MessageGroupStore.html[JavaDoc]. +For more information please refer to the http://docs.spring.io/spring-integration/api/org/springframework/integration/store/MessageGroupStore.html[JavaDoc]. The `MessageGroupStore` accumulates state information in `MessageGroups` while waiting for a release strategy to be triggered, and that event might not ever happen. So to prevent stale messages from lingering, and for volatile stores to provide a hook for cleaning up when the application shuts down, the `MessageGroupStore` allows the user to register callbacks to apply to its `MessageGroups` when they expire. diff --git a/src/reference/asciidoc/amqp.adoc b/src/reference/asciidoc/amqp.adoc index 7334b2ff70..c6bebb8e7d 100644 --- a/src/reference/asciidoc/amqp.adoc +++ b/src/reference/asciidoc/amqp.adoc @@ -598,7 +598,7 @@ Note, previously, the `channel-transacted` was `true` by default, now it changed [[amqp-message-headers]] === AMQP Message Headers -The Spring Integration AMPQ Adapters will map standard AMQP properties automatically. +The Spring Integration AMQP Adapters will map standard AMQP properties automatically. These properties will be copied by default to and from Spring Integration `MessageHeaders` using the http://static.springsource.org/spring-integration/api/org/springframework/integration/amqp/support/DefaultAmqpHeaderMapper.html[DefaultAmqpHeaderMapper]. Of course, you can pass in your own implementation of AMQP specific header mappers, as the adapters have respective properties to support that. @@ -606,7 +606,7 @@ Of course, you can pass in your own implementation of AMQP specific header mappe Any user-defined headers within the AMQP http://static.springsource.org/spring-amqp/api/org/springframework/amqp/core/MessageProperties.html[MessageProperties] will NOT be copied to or from an AMQP Message, unless explicitly specified by the _requestHeaderNames_ and/or _replyHeaderNames_ properties of the `DefaultAmqpHeaderMapper`. TIP: When mapping user-defined headers, the values can also contain simple wildcard patterns (e.g. "foo*" or "*foo") to be matched. -For example, if you need to copy all user-defined headers simply use the wild-card character `*`. +For example, if you need to copy all user-defined headers simply use the wildcard character `*`, but see the CAUTION below. Starting with _version 4.1_, the `AbstractHeaderMapper` (a `DefaultAmqpHeaderMapper` superclass) allows the `NON_STANDARD_HEADERS` token to be configured for the _requestHeaderNames_ and/or _replyHeaderNames_ properties (in addition to existing `STANDARD_REQUEST_HEADERS` and `STANDARD_REPLY_HEADERS`) to map all user-defined headers. Note, it is recommended to use the combination like this `STANDARD_REPLY_HEADERS, NON_STANDARD_HEADERS` instead of generic `*`, to avoid mapping of _request_ headers to the reply. @@ -661,6 +661,23 @@ Class `org.springframework.amqp.support.AmqpHeaders` identifies the default head * amqp_returnRoutingKey +CAUTION: As mentioned above, using a header mapping pattern `*` is a common way to copy all headers. +However, this can have some unexpected side-effects because certain RabbitMQ proprietary properties/headers will be +copied as well. +For example, when you use https://www.rabbitmq.com/federated-exchanges.html[Federation], the received message may have +a property named `x-received-from` which contains the node that sent the message. +If you use the wildcard character `*` for the request and reply header mapping on the Inbound Gateway, this header will +be copied as well, +which may cause some issues with federation; this reply message may be federated back to the +sending broker, which will think that a message is looping and is thus silently dropped. +If you wish to use the convenience of wildcard header mapping, you may need to filter out some headers in the +downstream flow. +For example, to avoid copying the `x-received-from` header back to the reply you can use +`` +before sending the reply to the AMQP Inbound Gateway. +Alternatively, you could explicitly list those properties that you actually want mapped instead of using +wildcards. + === AMQP Samples To experiment with the AMQP adapters, check out the samples available in the Spring Integration Samples Git repository at: diff --git a/src/reference/asciidoc/configuration.adoc b/src/reference/asciidoc/configuration.adoc index f93fd53623..55ef08ac47 100644 --- a/src/reference/asciidoc/configuration.adoc +++ b/src/reference/asciidoc/configuration.adoc @@ -259,7 +259,8 @@ Annotations available in Spring Integration include: The behavior of each is described in its own chapter or section within this reference. NOTE: If you are using XML configuration in combination with annotations, the `@MessageEndpoint` annotation is not required. -If you want to configure a POJO reference from the "ref" attribute of a element, it is sufficient to provide the method-level annotations. +If you want to configure a POJO reference from the "ref" attribute of a element, +it is sufficient to provide the method-level annotations. In that case, the annotation prevents ambiguity even when no "method" attribute exists on the element. In most cases, the annotated handler method should not require the `Message` type as its parameter. @@ -304,8 +305,10 @@ public class FooService { } ---- -NOTE: The value of the annotation can also be a SpEL expression (e.g., 'payload.getCustomerId()') which is quite useful when the name of the header has to be dynamically computed. -It also provides an optional 'required' property which specifies whether the attribute value must be available within the header. +NOTE: The value of the annotation can also be a SpEL expression (e.g., `someHeader.toUpperCase()`) which is useful +when you wish to manipulate the header value before injecting it. +It also provides an optional 'required' property which specifies whether the attribute value must be available within +the headers. The default value for 'required' is `true`. For several of these annotations, when a Message-handling method returns a non-null value, the endpoint will attempt to send a reply. @@ -319,6 +322,7 @@ In addition to the examples shown here, these annotations also support inputChan [source,java] ---- +@Service public class FooService { @ServiceActivator(inputChannel="input", outputChannel="output") @@ -330,7 +334,9 @@ public class FooService { ---- The processing of these annotations creates the same beans (`AbstractEndpoint` s and `MessageHandler` s (or `MessageSource` s for the inbound channel adapter - see below) as with similar xml components. -The bean names are generated with this pattern: `[componentName].[methodName].[decapitalizedAnnotationClassShortName]` for the `AbstractEndpoint` and the same name with an additional `.handler` (`.source`) suffix for the `MessageHandler` (`MessageSource`) bean. +The bean names are generated with this pattern: `[componentName].[methodName].[decapitalizedAnnotationClassShortName]` +(e.g for the sample above - `fooService.bar.serviceActivator`) +for the `AbstractEndpoint` and the same name with an additional `.handler` (`.source`) suffix for the `MessageHandler` (`MessageSource`) bean. The `MessageHandler` s (`MessageSource` s) are also eligible to be tracked by <>. Starting with _version 4.0_, all Messaging Annotations provide `SmartLifecycle` options - `autoStartup` and `phase` to allow endpoint lifecycle control on application context initialization. @@ -466,6 +472,7 @@ public Object service(Object payload) { This allows users to set defaults for various attributes and enables isolation of framework Java dependencies to user annotations, avoiding their use in user classes. If the framework finds a method with a user annotation that has a framework meta-annotation, it is treated as if the method was annotated directly with the framework annotation. +[[annotations_on_beans]] ==== Annotations on @Beans Starting with _version 4.0_, Messaging Annotations can be configured on `@Bean` method definitions in `@Configuration` classes, to produce Message Endpoints based on the beans, not methods. @@ -508,8 +515,20 @@ public class MyFlowConfiguration { The meta-annotation rules work on `@Bean` methods as well (`@MyServiceActivator` above can be applied to a `@Bean` definition). -NOTE: When using these annotations on consumer `@Bean` definitions, if the bean definition returns an appropriate `MessageHandler` (depending on the annotation type), attributes such as `outputChannel, requiresReply` etc, must be set on the `@Bean` itself. -The only annotation attributes used are `adviceChain, autoStartup, inputChannel, phase, poller`, all other attributes are for the handler. +NOTE: When using these annotations on consumer `@Bean` definitions, if the bean definition returns an appropriate +`MessageHandler` (depending on the annotation type), attributes such as `outputChannel`, `requiresReply` etc, +must be set on the `MessageHandler` `@Bean` definition itself. +The only annotation attributes used are `adviceChain`, `autoStartup`, `inputChannel`, `phase`, `poller`, +all other attributes are for the handler. + +NOTE: The bean names are generated with this algorithm: +* The `MessageHandler` (`MessageSource`) `@Bean` gets its own standard name from the method name or `name` attribute on +the `@Bean`. +This works like there is no Messaging Annotation on the `@Bean` method. +* The `AbstractEndpoint` bean name is generated with the pattern: +`[configurationComponentName].[methodName].[decapitalizedAnnotationClassShortName]`. +For example the endpoint (`SourcePollingChannelAdapter`) for the `consoleSource()` definition above gets a bean name like: +`myFlowConfiguration.consoleSource.inboundChannelAdapter`. IMPORTANT: When using these annotations on `@Bean` definitions, the `inputChannel` must reference a declared bean; channels are not automatically declared in this case. diff --git a/src/reference/asciidoc/http.adoc b/src/reference/asciidoc/http.adoc index d8ef7dc5ec..8d3033fbe3 100644 --- a/src/reference/asciidoc/http.adoc +++ b/src/reference/asciidoc/http.adoc @@ -558,7 +558,7 @@ If you wish to partially encode some of the URL, this can be achieved using an ` + .encodeWithinQuery('Hello World!')"/> ---- @@ -784,7 +784,7 @@ On the server side we have the following configuration: ---- diff --git a/src/reference/asciidoc/whats-new.adoc b/src/reference/asciidoc/whats-new.adoc index 7f00afb692..285796d29d 100644 --- a/src/reference/asciidoc/whats-new.adoc +++ b/src/reference/asciidoc/whats-new.adoc @@ -98,7 +98,7 @@ As an alternative to the existing `selector` attribute, the `` now su See <> for more information about these changes. -===== Appending NewLines +===== Appending New Lines The `` and `` now support an `append-new-line` attribute. If set to `true`, a new line is appended to the file after a message is written. @@ -126,6 +126,11 @@ The `LastModifiedFileListFilter` has been added. The `WatchServiceDirectoryScanner` is now available. +===== Persistent File List Filter Changes + +The `AbstractPersistentFileListFilter` has a new property `flushOnUpdate` which, when set to true, will `flush()` the +metadata store if it implements `Flushable` (e.g. the `PropertiesPersistingMetadataStore`). + [[x4.2-class-package-change]] ==== Class Package Change @@ -279,13 +284,6 @@ The default is now `500 Internal Server Error` instead of `200 OK`. See <> for more information. -[[x4.2-file-filter]] -==== Persistent File List Filter Changes - -The `AbstractPersistentFileListFilter` has a new property `flushOnUpdate` which, when set to true, will `flush()` the -metadata store if it implements `Flushable` (e.g. the `PropertiesPersistingMetadataStore`). - - [[x4.2-gw]] ==== Gateway Changes @@ -310,7 +308,7 @@ New methods (`removeMessagesFromGroup`) have been added to the message store. Set the `removeBatchSize` property (default `100`) to adjust the number of messages deleted in each operation. Currently, JDBC, Redis and MongoDB message stores support this property. -===== Output MessageGroupProcessor +===== Output Message Group Processor When using a `ref` or inner bean for the aggregator, it is now possible to bind a `MessageGroupProcessor` directly. In addition, a `SimpleMessageGroupProcessor` is provided that simply returns the collection of messages in the group. @@ -340,7 +338,7 @@ thread context value. See <> and <> for more information. -===== DefaultSftpSessionFactory +===== Default Sftp Session Factory Previously, the `DefaultSftpSessionFactory` unconditionally allowed connections to unknown hosts. This is now configurable (default false). @@ -350,7 +348,7 @@ false). See <> for more information. -===== MessageSessionCallback +===== Message Session Callback The `MessageSessionCallback` has been introduced to perform any custom `Session` operation(s) with the `requestMessage` context in the ``. diff --git a/src/reference/asciidoc/ws.adoc b/src/reference/asciidoc/ws.adoc index 0d6f80dd87..f3dc23a8e8 100644 --- a/src/reference/asciidoc/ws.adoc +++ b/src/reference/asciidoc/ws.adoc @@ -17,11 +17,11 @@ Both require a Spring Web Services `DestinationProvider` for determining the URI ---- NOTE: When using the namespace support described below, you will only need to set a URI. -Internally, the parser will configure a fixed URI DestinationProvider implementation. -If you do need dynamic resolution of the URI at runtime, however, then the DestinationProvider can provide such behavior as looking up the URI from a registry. -See the Spring Web Serviceshttp://static.springsource.org/spring-ws/site/apidocs/org/springframework/ws/client/support/destination/DestinationProvider.html[DestinationProvider] JavaDoc for more information about this strategy. +Internally, the parser will configure a fixed URI `DestinationProvider` implementation. +If you do need dynamic resolution of the URI at runtime, however, then the `DestinationProvider` can provide such behavior as looking up the URI from a registry. +See the Spring Web Services http://docs.spring.io/spring-ws/docs/current/api/org/springframework/ws/client/support/destination/DestinationProvider.html[DestinationProvider] JavaDoc for more information about this strategy. -For more detail on the inner workings, see the Spring Web Services reference guide's chapter covering http://static.springframework.org/spring-ws/site/reference/html/client.html[client access] as well as the chapter covering http://static.springframework.org/spring-ws/site/reference/html/oxm.html[Object/XML mapping]. +For more detail on the inner workings, see the Spring Web Services reference guide's chapter covering http://docs.spring.io/spring-ws/docs/current/reference/html/client.html[client access] as well as the chapter covering http://static.springframework.org/spring-ws/site/reference/html/oxm.html[Object/XML mapping]. [[webservices-inbound]] === Inbound Web Service Gateways @@ -44,8 +44,26 @@ If the incoming web service message is a SOAP message the SOAP Action header wil Both gateways implement the Spring Web Services `MessageEndpoint` interface, so they can be configured with a `MessageDispatcherServlet` as per standard Spring Web Services configuration. -For more detail on how to use these components, see the Spring Web Services reference guide's chapter covering http://static.springframework.org/spring-ws/site/reference/html/server.html[creating a Web Service]. -The chapter coveringhttp://static.springframework.org/spring-ws/site/reference/html/oxm.html[Object/XML mapping] is also applicable again. +For more detail on how to use these components, see the Spring Web Services reference guide's chapter covering http://docs.spring.io/spring-ws/docs/current/reference/html/server.html[creating a Web Service]. +The chapter covering http://docs.spring.io/spring/docs/current/spring-framework-reference/html/oxm.html[Object/XML mapping] is also applicable again. + +To include the `SimpleWebServiceInboundGateway` and `MarshallingWebServiceInboundGateway` configurations to the Spring WS +infrastructure you should add the `EndpointMapping` definition between `MessageDispatcherServlet` and the target +`MessageEndpoint` implementations like you do that with normal Spring WS application. +For this purpose (from Spring Integration perspective), the Spring WS provides these convenient `EndpointMapping` +implementations: + +* `org.springframework.ws.server.endpoint.mapping.UriEndpointMapping` +* `org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping` +* `org.springframework.ws.soap.server.endpoint.mapping.SoapActionEndpointMapping` +* `org.springframework.ws.server.endpoint.mapping.XPathPayloadEndpointMapping` + +The beans for these classes must be specified in the application context referencing to the +`SimpleWebServiceInboundGateway` and/or `MarshallingWebServiceInboundGateway` bean definitions according to the WS +mapping algorithm. + +Please, refer to the http://docs.spring.io/spring-ws/docs/current/reference/html/server.html#server-endpoint-mapping[Endpoint mappings] +for the more information. [[webservices-namespace]] === Web Service Namespace Support @@ -109,7 +127,7 @@ This might be useful, for example, when a custom Transformer works against the ` [[outbound-uri]] === Outbound URI Configuration -For all URI-schemes supported by Spring Web Services (http://static.springsource.org/spring-ws/site/reference/html/client.html#client-transports[URIs and Transports]) `` substitution is provided: +For all URI-schemes supported by Spring Web Services (http://docs.spring.io/spring-ws/docs/current/reference/html/client.html#client-transports[URIs and Transports]) `` substitution is provided: [source,xml] ---- @@ -132,7 +150,7 @@ If a `DestinationProvider` is supplied, variable substitution is not supported a _Controlling URI Encoding_ -By default, the URL string is encoded (see http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/util/UriComponentsBuilder.html[UriComponentsBuilder]) to the URI object before sending the request. +By default, the URL string is encoded (see http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/util/UriComponentsBuilder.html[UriComponentsBuilder]) to the URI object before sending the request. In some scenarios with a non-standard URI it is undesirable to perform the encoding. Since _version 4.1 _ the `` provides an `encode-uri` attribute. To disable encoding the URL, this attribute should be set to `false` (by default it is `true`). @@ -142,7 +160,7 @@ If you wish to partially encode some of the URL, this can be achieved using an ` + .encodeWithinQuery('Hello World!')"/> ----