The following listing shows the possible configuration options for an AMQP Inbound Channel Adapter:
The following listing shows the possible configuration options for an AMQP Inbound Channel Adapter:
...
@@ -171,7 +171,7 @@ XML
...
@@ -171,7 +171,7 @@ XML
Starting with version 5.5, the `AmqpInboundChannelAdapter` can be configured with an `org.springframework.amqp.rabbit.retry.MessageRecoverer` strategy which is used in the `RecoveryCallback` when the retry operation is called internally.
Starting with version 5.5, the `AmqpInboundChannelAdapter` can be configured with an `org.springframework.amqp.rabbit.retry.MessageRecoverer` strategy which is used in the `RecoveryCallback` when the retry operation is called internally.
See `setMessageRecoverer()` JavaDocs for more information.
See `setMessageRecoverer()` JavaDocs for more information.
#### [](#amqp-debatching)Batched Messages
#### Batched Messages
See [the Spring AMQP Documentation](https://docs.spring.io/spring-amqp/docs/current/reference/html/#template-batching) for more information about batched messages.
See [the Spring AMQP Documentation](https://docs.spring.io/spring-amqp/docs/current/reference/html/#template-batching) for more information about batched messages.
...
@@ -185,9 +185,9 @@ The default `BatchingStrategy` is the `SimpleBatchingStrategy`, but this can be
...
@@ -185,9 +185,9 @@ The default `BatchingStrategy` is the `SimpleBatchingStrategy`, but this can be
| |The `org.springframework.amqp.rabbit.retry.MessageBatchRecoverer` must be used with batches when recovery is required for retry operations.|
| |The `org.springframework.amqp.rabbit.retry.MessageBatchRecoverer` must be used with batches when recovery is required for retry operations.|
Version 5.0.1 introduced a polled channel adapter, letting you fetch individual messages on demand — for example, with a `MessageSourcePollingTemplate` or a poller.
Version 5.0.1 introduced a polled channel adapter, letting you fetch individual messages on demand — for example, with a `MessageSourcePollingTemplate` or a poller.
See [Deferred Acknowledgment Pollable Message Source](./polling-consumer.html#deferred-acks-message-source) for more information.
See [Deferred Acknowledgment Pollable Message Source](./polling-consumer.html#deferred-acks-message-source) for more information.
...
@@ -227,13 +227,13 @@ XML
...
@@ -227,13 +227,13 @@ XML
This adapter currently does not have XML configuration support.
This adapter currently does not have XML configuration support.
```
```
#### [](#amqp-polled-debatching)Batched Messages
#### Batched Messages
See [Batched Messages](#amqp-debatching).
See [Batched Messages](#amqp-debatching).
For the polled adapter, there is no listener container, batched messages are always debatched (if the `BatchingStrategy` supports doing so).
For the polled adapter, there is no listener container, batched messages are always debatched (if the `BatchingStrategy` supports doing so).
### [](#amqp-inbound-gateway)Inbound Gateway
### Inbound Gateway
The inbound gateway supports all the attributes on the inbound channel adapter (except that 'channel' is replaced by 'request-channel'), plus some additional attributes.
The inbound gateway supports all the attributes on the inbound channel adapter (except that 'channel' is replaced by 'request-channel'), plus some additional attributes.
The following listing shows the available attributes:
The following listing shows the available attributes:
...
@@ -321,11 +321,11 @@ See the note in [Inbound Channel Adapter](#amqp-inbound-channel-adapter) about c
...
@@ -321,11 +321,11 @@ See the note in [Inbound Channel Adapter](#amqp-inbound-channel-adapter) about c
Starting with version 5.5, the `AmqpInboundChannelAdapter` can be configured with an `org.springframework.amqp.rabbit.retry.MessageRecoverer` strategy which is used in the `RecoveryCallback` when the retry operation is called internally.
Starting with version 5.5, the `AmqpInboundChannelAdapter` can be configured with an `org.springframework.amqp.rabbit.retry.MessageRecoverer` strategy which is used in the `RecoveryCallback` when the retry operation is called internally.
See `setMessageRecoverer()` JavaDocs for more information.
See `setMessageRecoverer()` JavaDocs for more information.
By default, the inbound endpoints use the `AUTO` acknowledge mode, which means the container automatically acknowledges the message when the downstream integration flow completes (or a message is handed off to another thread by using a `QueueChannel` or `ExecutorChannel`).
By default, the inbound endpoints use the `AUTO` acknowledge mode, which means the container automatically acknowledges the message when the downstream integration flow completes (or a message is handed off to another thread by using a `QueueChannel` or `ExecutorChannel`).
Setting the mode to `NONE` configures the consumer such that acknowledgments are not used at all (the broker automatically acknowledges the message as soon as it is sent).
Setting the mode to `NONE` configures the consumer such that acknowledgments are not used at all (the broker automatically acknowledges the message as soon as it is sent).
The following outbound endpoints have many similar configuration options.
The following outbound endpoints have many similar configuration options.
Starting with version 5.2, the `confirm-timeout` has been added.
Starting with version 5.2, the `confirm-timeout` has been added.
...
@@ -368,7 +368,7 @@ Normally, when publisher confirms are enabled, the broker will quickly return an
...
@@ -368,7 +368,7 @@ Normally, when publisher confirms are enabled, the broker will quickly return an
If a channel is closed before the confirm is received, the Spring AMQP framework will synthesize a nack.
If a channel is closed before the confirm is received, the Spring AMQP framework will synthesize a nack.
"Missing" acks should never occur but, if you set this property, the endpoint will periodically check for them and synthesize a nack if the time elapses without a confirm being received.
"Missing" acks should never occur but, if you set this property, the endpoint will periodically check for them and synthesize a nack if the time elapses without a confirm being received.
The following example shows the available properties for an AMQP outbound channel adapter:
The following example shows the available properties for an AMQP outbound channel adapter:
...
@@ -452,7 +452,7 @@ XML
...
@@ -452,7 +452,7 @@ XML
| |return-channel<br/><br/>Using a `return-channel` requires a `RabbitTemplate` with the `mandatory` property set to `true` and a `CachingConnectionFactory` with the `publisherReturns` property set to `true`.<br/>When using multiple outbound endpoints with returns, a separate `RabbitTemplate` is needed for each endpoint.|
| |return-channel<br/><br/>Using a `return-channel` requires a `RabbitTemplate` with the `mandatory` property set to `true` and a `CachingConnectionFactory` with the `publisherReturns` property set to `true`.<br/>When using multiple outbound endpoints with returns, a separate `RabbitTemplate` is needed for each endpoint.|
The gateway discussed in the previous section is synchronous, in that the sending thread is suspended until a
The gateway discussed in the previous section is synchronous, in that the sending thread is suspended until a
reply is received (or a timeout occurs).
reply is received (or a timeout occurs).
...
@@ -670,7 +670,7 @@ See also [Asynchronous Service Activator](./service-activator.html#async-service
...
@@ -670,7 +670,7 @@ See also [Asynchronous Service Activator](./service-activator.html#async-service
| |RabbitTemplate<br/><br/>When you use confirmations and returns, we recommend that the `RabbitTemplate` wired into the `AsyncRabbitTemplate` be dedicated.<br/>Otherwise, unexpected side-effects may be encountered.|
| |RabbitTemplate<br/><br/>When you use confirmations and returns, we recommend that the `RabbitTemplate` wired into the `AsyncRabbitTemplate` be dedicated.<br/>Otherwise, unexpected side-effects may be encountered.|
### [](#alternative-confirms-returns)Alternative Mechanism for Publisher Confirms and Returns
### Alternative Mechanism for Publisher Confirms and Returns
When the connection factory is configured for publisher confirms and returns, the sections above discuss the configuration of message channels to receive the confirms and returns asynchronously.
When the connection factory is configured for publisher confirms and returns, the sections above discuss the configuration of message channels to receive the confirms and returns asynchronously.
Starting with version 5.4, there is an additional mechanism which is generally easier to use.
Starting with version 5.4, there is an additional mechanism which is generally easier to use.
...
@@ -699,7 +699,7 @@ catch { ... }
...
@@ -699,7 +699,7 @@ catch { ... }
To improve performance, you may wish to send multiple messages and wait for the confirmations later, rather than one-at-a-time.
To improve performance, you may wish to send multiple messages and wait for the confirmations later, rather than one-at-a-time.
The returned message is the raw message after conversion; you can subclass `CorrelationData` with whatever additional data you need.
The returned message is the raw message after conversion; you can subclass `CorrelationData` with whatever additional data you need.
Inbound messages, arriving at the channel adapter or gateway, are converted to the `spring-messaging``Message<?>` payload using a message converter.
Inbound messages, arriving at the channel adapter or gateway, are converted to the `spring-messaging``Message<?>` payload using a message converter.
By default, a `SimpleMessageConverter` is used, which handles java serialization and text.
By default, a `SimpleMessageConverter` is used, which handles java serialization and text.
...
@@ -712,7 +712,7 @@ If the error flow throws an exception, the exception type, in conjunction with t
...
@@ -712,7 +712,7 @@ If the error flow throws an exception, the exception type, in conjunction with t
If the container is configured with `AcknowledgeMode.MANUAL`, the payload is a `ManualAckListenerExecutionFailedException` with additional properties `channel` and `deliveryTag`.
If the container is configured with `AcknowledgeMode.MANUAL`, the payload is a `ManualAckListenerExecutionFailedException` with additional properties `channel` and `deliveryTag`.
This enables the error flow to call `basicAck` or `basicNack` (or `basicReject`) for the message, to control its disposition.
This enables the error flow to call `basicAck` or `basicNack` (or `basicReject`) for the message, to control its disposition.
Spring AMQP 1.4 introduced the `ContentTypeDelegatingMessageConverter`, where the actual converter is selected based
Spring AMQP 1.4 introduced the `ContentTypeDelegatingMessageConverter`, where the actual converter is selected based
on the incoming content type message property.
on the incoming content type message property.
...
@@ -752,7 +752,7 @@ This applies to both the outbound channel adapter and gateway.
...
@@ -752,7 +752,7 @@ This applies to both the outbound channel adapter and gateway.
| |Starting with version 5.0, headers that are added to the `MessageProperties` of the outbound message are never overwritten by mapped headers (by default).<br/>Previously, this was only the case if the message converter was a `ContentTypeDelegatingMessageConverter` (in that case, the header was mapped first so that the proper converter could be selected).<br/>For other converters, such as the `SimpleMessageConverter`, mapped headers overwrote any headers added by the converter.<br/>This caused problems when an outbound message had some leftover `contentType` headers (perhaps from an inbound channel adapter) and the correct outbound `contentType` was incorrectly overwritten.<br/>The work-around was to use a header filter to remove the header before sending the message to the outbound endpoint.<br/><br/>There are, however, cases where the previous behavior is desired — for example, when a `String` payload that contains JSON, the `SimpleMessageConverter` is not aware of the content and sets the `contentType` message property to `text/plain` but your application would like to override that to `application/json` by setting the `contentType` header of the message sent to the outbound endpoint.<br/>The `ObjectToJsonTransformer` does exactly that (by default).<br/><br/>There is now a property called `headersMappedLast` on the outbound channel adapter and gateway (as well as on AMQP-backed channels).<br/>Setting this to `true` restores the behavior of overwriting the property added by the converter.<br/><br/>Starting with version 5.1.9, a similar `replyHeadersMappedLast` is provided for the `AmqpInboundGateway` when we produce a reply and would like to override headers populated by the converter.<br/>See its JavaDocs for more information.|
| |Starting with version 5.0, headers that are added to the `MessageProperties` of the outbound message are never overwritten by mapped headers (by default).<br/>Previously, this was only the case if the message converter was a `ContentTypeDelegatingMessageConverter` (in that case, the header was mapped first so that the proper converter could be selected).<br/>For other converters, such as the `SimpleMessageConverter`, mapped headers overwrote any headers added by the converter.<br/>This caused problems when an outbound message had some leftover `contentType` headers (perhaps from an inbound channel adapter) and the correct outbound `contentType` was incorrectly overwritten.<br/>The work-around was to use a header filter to remove the header before sending the message to the outbound endpoint.<br/><br/>There are, however, cases where the previous behavior is desired — for example, when a `String` payload that contains JSON, the `SimpleMessageConverter` is not aware of the content and sets the `contentType` message property to `text/plain` but your application would like to override that to `application/json` by setting the `contentType` header of the message sent to the outbound endpoint.<br/>The `ObjectToJsonTransformer` does exactly that (by default).<br/><br/>There is now a property called `headersMappedLast` on the outbound channel adapter and gateway (as well as on AMQP-backed channels).<br/>Setting this to `true` restores the behavior of overwriting the property added by the converter.<br/><br/>Starting with version 5.1.9, a similar `replyHeadersMappedLast` is provided for the `AmqpInboundGateway` when we produce a reply and would like to override headers populated by the converter.<br/>See its JavaDocs for more information.|
There are two message channel implementations available.
There are two message channel implementations available.
One is point-to-point, and the other is publish-subscribe.
One is point-to-point, and the other is publish-subscribe.
...
@@ -826,7 +826,7 @@ By default, Spring AMQP `MessageProperties` uses `PERSISTENT` delivery mode.
...
@@ -826,7 +826,7 @@ By default, Spring AMQP `MessageProperties` uses `PERSISTENT` delivery mode.
| |Starting with version 5.0, the pollable channel now blocks the poller thread for the specified `receiveTimeout` (the default is 1 second).<br/>Previously, unlike other `PollableChannel` implementations, the thread returned immediately to the scheduler if no message was available, regardless of the receive timeout.<br/>Blocking is a little more expensive than using a `basicGet()` to retrieve a message (with no timeout), because a consumer has to be created to receive each message.<br/>To restore the previous behavior, set the poller’s `receiveTimeout` to 0.|
| |Starting with version 5.0, the pollable channel now blocks the poller thread for the specified `receiveTimeout` (the default is 1 second).<br/>Previously, unlike other `PollableChannel` implementations, the thread returned immediately to the scheduler if no message was available, regardless of the receive timeout.<br/>Blocking is a little more expensive than using a `basicGet()` to retrieve a message (with no timeout), because a consumer has to be created to receive each message.<br/>To restore the previous behavior, set the poller’s `receiveTimeout` to 0.|
#### [](#configuring-with-java-configuration)Configuring with Java Configuration
#### Configuring with Java Configuration
The following example shows how to configure the channels with Java configuration:
The following example shows how to configure the channels with Java configuration:
...
@@ -859,7 +859,7 @@ public AmqpChannelFactoryBean pubSub(ConnectionFactory connectionFactory) {
...
@@ -859,7 +859,7 @@ public AmqpChannelFactoryBean pubSub(ConnectionFactory connectionFactory) {
}
}
```
```
#### [](#configuring-with-the-java-dsl)Configuring with the Java DSL
#### Configuring with the Java DSL
The following example shows how to configure the channels with the Java DSL:
The following example shows how to configure the channels with the Java DSL:
...
@@ -895,9 +895,9 @@ public IntegrationFlow pubSubInFlow(ConnectionFactory connectionFactory) {
...
@@ -895,9 +895,9 @@ public IntegrationFlow pubSubInFlow(ConnectionFactory connectionFactory) {
}
}
```
```
### [](#amqp-message-headers)AMQP Message Headers
### AMQP Message Headers
#### [](#overview-2)Overview
#### Overview
The Spring Integration AMQP Adapters automatically map all AMQP properties and headers.
The Spring Integration AMQP Adapters automatically map all AMQP properties and headers.
(This is a change from 4.3 - previously, only standard headers were mapped).
(This is a change from 4.3 - previously, only standard headers were mapped).
...
@@ -993,7 +993,7 @@ For this purpose a `!json_*` pattern should be configured for header mapper of t
...
@@ -993,7 +993,7 @@ For this purpose a `!json_*` pattern should be configured for header mapper of t
| |Starting with version 5.1, the `DefaultAmqpHeaderMapper` will fall back to mapping `MessageHeaders.ID` and `MessageHeaders.TIMESTAMP` to `MessageProperties.messageId` and `MessageProperties.timestamp` respectively, if the corresponding `amqp_messageId` or `amqp_timestamp` headers are not present on outbound messages.<br/>Inbound properties will be mapped to the `amqp_*` headers as before.<br/>It is useful to populate the `messageId` property when message consumers are using stateful retry.|
| |Starting with version 5.1, the `DefaultAmqpHeaderMapper` will fall back to mapping `MessageHeaders.ID` and `MessageHeaders.TIMESTAMP` to `MessageProperties.messageId` and `MessageProperties.timestamp` respectively, if the corresponding `amqp_messageId` or `amqp_timestamp` headers are not present on outbound messages.<br/>Inbound properties will be mapped to the `amqp_*` headers as before.<br/>It is useful to populate the `messageId` property when message consumers are using stateful retry.|
Unlike other headers, the `AmqpHeaders.CONTENT_TYPE` is not prefixed with `amqp_`; this allows transparent passing of the contentType header across different technologies.
Unlike other headers, the `AmqpHeaders.CONTENT_TYPE` is not prefixed with `amqp_`; this allows transparent passing of the contentType header across different technologies.
For example an inbound HTTP message sent to a RabbitMQ queue.
For example an inbound HTTP message sent to a RabbitMQ queue.
...
@@ -1004,18 +1004,18 @@ Prior to version 5.1, this header was also mapped as an entry in the `MessagePro
...
@@ -1004,18 +1004,18 @@ Prior to version 5.1, this header was also mapped as an entry in the `MessagePro
Such a change would be reflected in the first-class `content_type` property, but not in the RabbitMQ headers map.
Such a change would be reflected in the first-class `content_type` property, but not in the RabbitMQ headers map.
Inbound mapping ignored the headers map value.`contentType` is no longer mapped to an entry in the headers map.
Inbound mapping ignored the headers map value.`contentType` is no longer mapped to an entry in the headers map.
To experiment with the AMQP adapters, check out the samples available in the Spring Integration samples git repository at [https://github.com/SpringSource/spring-integration-samples](https://github.com/spring-projects/spring-integration-samples)
To experiment with the AMQP adapters, check out the samples available in the Spring Integration samples git repository at [https://github.com/SpringSource/spring-integration-samples](https://github.com/spring-projects/spring-integration-samples)
Spring Integration offers a number of configuration options.
Spring Integration offers a number of configuration options.
Which option you choose depends upon your particular needs and at what level you prefer to work.
Which option you choose depends upon your particular needs and at what level you prefer to work.
...
@@ -10,7 +10,7 @@ As much as possible, the two provide consistent naming.
...
@@ -10,7 +10,7 @@ As much as possible, the two provide consistent naming.
The XML elements defined by the XSD schema match the names of the annotations, and the attributes of those XML elements match the names of annotation properties.
The XML elements defined by the XSD schema match the names of the annotations, and the attributes of those XML elements match the names of annotation properties.
You can also use the API directly, but we expect most developers to choose one of the higher-level options or a combination of the namespace-based and annotation-driven configuration.
You can also use the API directly, but we expect most developers to choose one of the higher-level options or a combination of the namespace-based and annotation-driven configuration.
### [](#configuration-namespace)Namespace Support
### Namespace Support
You can configure Spring Integration components with XML elements that map directly to the terminology and concepts of enterprise integration.
You can configure Spring Integration components with XML elements that map directly to the terminology and concepts of enterprise integration.
In many cases, the element names match those of the [*Enterprise Integration Patterns*](https://www.enterpriseintegrationpatterns.com/) book.
In many cases, the element names match those of the [*Enterprise Integration Patterns*](https://www.enterpriseintegrationpatterns.com/) book.
...
@@ -87,7 +87,7 @@ For example, the following root element shows several of these namespace declara
...
@@ -87,7 +87,7 @@ For example, the following root element shows several of these namespace declara
This reference manual provides specific examples of the various elements in their corresponding chapters.
This reference manual provides specific examples of the various elements in their corresponding chapters.
Here, the main thing to recognize is the consistency of the naming for each namespace URI and schema location.
Here, the main thing to recognize is the consistency of the naming for each namespace URI and schema location.
### [](#namespace-taskscheduler)Configuring the Task Scheduler
### Configuring the Task Scheduler
In Spring Integration, the `ApplicationContext` plays the central role of a message bus, and you need to consider only a couple of configuration options.
In Spring Integration, the `ApplicationContext` plays the central role of a message bus, and you need to consider only a couple of configuration options.
First, you may want to control the central `TaskScheduler` instance.
First, you may want to control the central `TaskScheduler` instance.
...
@@ -119,7 +119,7 @@ However, when no task executor is provided for an endpoint’s poller, it is inv
...
@@ -119,7 +119,7 @@ However, when no task executor is provided for an endpoint’s poller, it is inv
See also [Error Handling](./error-handling.html#error-handling) for more information.
See also [Error Handling](./error-handling.html#error-handling) for more information.
### [](#global-properties)Global Properties
### Global Properties
Certain global framework properties can be overridden by providing a properties file on the classpath.
Certain global framework properties can be overridden by providing a properties file on the classpath.
In addition to the XML namespace support for configuring message endpoints, you can also use annotations.
In addition to the XML namespace support for configuring message endpoints, you can also use annotations.
First, Spring Integration provides the class-level `@MessageEndpoint` as a stereotype annotation, meaning that it is itself annotated with Spring’s `@Component` annotation and is therefore automatically recognized as a bean definition by Spring’s component scanning.
First, Spring Integration provides the class-level `@MessageEndpoint` as a stereotype annotation, meaning that it is itself annotated with Spring’s `@Component` annotation and is therefore automatically recognized as a bean definition by Spring’s component scanning.
...
@@ -296,7 +296,7 @@ For these purposes, you should use the `beanName` mentioned earlier in the prece
...
@@ -296,7 +296,7 @@ For these purposes, you should use the `beanName` mentioned earlier in the prece
| |Channels automatically created after parsing the mentioned annotations (when no specific channel bean is configured), and the corresponding consumer endpoints, are declared as beans near the end of the context initialization.<br/>These beans **can** be autowired in other services, but they have to be marked with the `@Lazy` annotation because the definitions, typically, won’t yet be available during normal autowiring processing.<br/><br/>```<br/>@Autowired<br/>@Lazy<br/>@Qualifier("someChannel")<br/>MessageChannel someChannel;<br/>...<br/><br/>@Bean<br/>Thing1 dependsOnSPCA(@Qualifier("someInboundAdapter") @Lazy SourcePollingChannelAdapter someInboundAdapter) {<br/> ...<br/>}<br/>```|
| |Channels automatically created after parsing the mentioned annotations (when no specific channel bean is configured), and the corresponding consumer endpoints, are declared as beans near the end of the context initialization.<br/>These beans **can** be autowired in other services, but they have to be marked with the `@Lazy` annotation because the definitions, typically, won’t yet be available during normal autowiring processing.<br/><br/>```<br/>@Autowired<br/>@Lazy<br/>@Qualifier("someChannel")<br/>MessageChannel someChannel;<br/>...<br/><br/>@Bean<br/>Thing1 dependsOnSPCA(@Qualifier("someInboundAdapter") @Lazy SourcePollingChannelAdapter someInboundAdapter) {<br/> ...<br/>}<br/>```|
#### [](#configuration-using-poller-annotation)Using the `@Poller` Annotation
#### Using the `@Poller` Annotation
Before Spring Integration 4.0, messaging annotations required that the `inputChannel` be a reference to a `SubscribableChannel`.
Before Spring Integration 4.0, messaging annotations required that the `inputChannel` be a reference to a `SubscribableChannel`.
For `PollableChannel` instances, an `<int:bridge/>` element was needed to configure an `<int:poller/>` and make the composite endpoint be a `PollingConsumer`.
For `PollableChannel` instances, an `<int:bridge/>` element was needed to configure an `<int:poller/>` and make the composite endpoint be a `PollingConsumer`.
...
@@ -373,7 +373,7 @@ See [Endpoint Namespace Support](./endpoint.html#endpoint-namespace) for more in
...
@@ -373,7 +373,7 @@ See [Endpoint Namespace Support](./endpoint.html#endpoint-namespace) for more in
The `poller()` attribute on the messaging annotations is mutually exclusive with the `reactive()` attribute.
The `poller()` attribute on the messaging annotations is mutually exclusive with the `reactive()` attribute.
The `ReactiveStreamsConsumer` has been around since version 5.0, but it was applied only when an input channel for the endpoint is a `FluxMessageChannel` (or any `org.reactivestreams.Publisher` implementation).
The `ReactiveStreamsConsumer` has been around since version 5.0, but it was applied only when an input channel for the endpoint is a `FluxMessageChannel` (or any `org.reactivestreams.Publisher` implementation).
Starting with version 5.3, its instance is also created by the framework when the target message handler is a `ReactiveMessageHandler` independently of the input channel type.
Starting with version 5.3, its instance is also created by the framework when the target message handler is a `ReactiveMessageHandler` independently of the input channel type.
...
@@ -398,7 +398,7 @@ public void handleReactive(String payload) {
...
@@ -398,7 +398,7 @@ public void handleReactive(String payload) {
The `reactive()` attribute on the messaging annotations is mutually exclusive with the `poller()` attribute.
The `reactive()` attribute on the messaging annotations is mutually exclusive with the `poller()` attribute.
See [Using the `@Poller` Annotation](#configuration-using-poller-annotation) and [Reactive Streams Support](./reactive-streams.html#reactive-streams) for more information.
See [Using the `@Poller` Annotation](#configuration-using-poller-annotation) and [Reactive Streams Support](./reactive-streams.html#reactive-streams) for more information.
#### [](#using-the-inboundchanneladapter-annotation)Using the `@InboundChannelAdapter` Annotation
#### Using the `@InboundChannelAdapter` Annotation
Version 4.0 introduced the `@InboundChannelAdapter` method-level annotation.
Version 4.0 introduced the `@InboundChannelAdapter` method-level annotation.
It produces a `SourcePollingChannelAdapter` integration component based on a `MethodInvokingMessageSource` for the annotated method.
It produces a `SourcePollingChannelAdapter` integration component based on a `MethodInvokingMessageSource` for the annotated method.
...
@@ -430,7 +430,7 @@ Using the `@MessagingGateway` Annotation
...
@@ -430,7 +430,7 @@ Using the `@MessagingGateway` Annotation
See [`@MessagingGateway` Annotation](./gateway.html#messaging-gateway-annotation).
See [`@MessagingGateway` Annotation](./gateway.html#messaging-gateway-annotation).
#### [](#using-the-integrationcomponentscan-annotation)Using the `@IntegrationComponentScan` Annotation
#### Using the `@IntegrationComponentScan` Annotation
The standard Spring Framework `@ComponentScan` annotation does not scan interfaces for stereotype `@Component` annotations.
The standard Spring Framework `@ComponentScan` annotation does not scan interfaces for stereotype `@Component` annotations.
To overcome this limitation and allow the configuration of `@MessagingGateway` (see [`@MessagingGateway` Annotation](./gateway.html#messaging-gateway-annotation)), we introduced the `@IntegrationComponentScan` mechanism.
To overcome this limitation and allow the configuration of `@MessagingGateway` (see [`@MessagingGateway` Annotation](./gateway.html#messaging-gateway-annotation)), we introduced the `@IntegrationComponentScan` mechanism.
...
@@ -439,7 +439,7 @@ such as `basePackages` and `basePackageClasses`.
...
@@ -439,7 +439,7 @@ such as `basePackages` and `basePackageClasses`.
In this case, all discovered interfaces annotated with `@MessagingGateway` are parsed and registered as `GatewayProxyFactoryBean` instances.
In this case, all discovered interfaces annotated with `@MessagingGateway` are parsed and registered as `GatewayProxyFactoryBean` instances.
All other class-based components are parsed by the standard `@ComponentScan`.
All other class-based components are parsed by the standard `@ComponentScan`.
Starting with version 4.0, all messaging annotations can be configured as meta-annotations and all user-defined messaging annotations can define the same attributes to override their default values.
Starting with version 4.0, all messaging annotations can be configured as meta-annotations and all user-defined messaging annotations can define the same attributes to override their default values.
In addition, meta-annotations can be configured hierarchically, as the following example shows:
In addition, meta-annotations can be configured hierarchically, as the following example shows:
...
@@ -473,7 +473,7 @@ public Object service(Object payload) {
...
@@ -473,7 +473,7 @@ public Object service(Object payload) {
Configuring meta-annotations hierarchically lets users set defaults for various attributes and enables isolation of framework Java dependencies to user annotations, avoiding their use in user classes.
Configuring meta-annotations hierarchically lets users 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 were annotated directly with the framework annotation.
If the framework finds a method with a user annotation that has a framework meta-annotation, it is treated as if the method were annotated directly with the framework annotation.
#### [](#annotations_on_beans)Annotations on `@Bean` Methods
#### Annotations on `@Bean` Methods
Starting with version 4.0, you can configure messaging annotations on `@Bean` method definitions in `@Configuration` classes, to produce message endpoints based on the beans, not the methods.
Starting with version 4.0, you can configure messaging annotations on `@Bean` method definitions in `@Configuration` classes, to produce message endpoints based on the beans, not the methods.
It is useful when `@Bean` definitions are “out-of-the-box” `MessageHandler` instances (`AggregatingMessageHandler`, `DefaultMessageSplitter`, and others), `Transformer` instances (`JsonToObjectTransformer`, `ClaimCheckOutTransformer`, and others), and `MessageSource` instances (`FileReadingMessageSource`, `RedisStoreMessageSource`, and others).
It is useful when `@Bean` definitions are “out-of-the-box” `MessageHandler` instances (`AggregatingMessageHandler`, `DefaultMessageSplitter`, and others), `Transformer` instances (`JsonToObjectTransformer`, `ClaimCheckOutTransformer`, and others), and `MessageSource` instances (`FileReadingMessageSource`, `RedisStoreMessageSource`, and others).
...
@@ -557,7 +557,7 @@ The meta-annotation rules work on `@Bean` methods as well (the `@MyServiceActiva
...
@@ -557,7 +557,7 @@ The meta-annotation rules work on `@Bean` methods as well (the `@MyServiceActiva
| |With Java configuration, you can use any `@Conditional` (for example, `@Profile`) definition on the `@Bean` method level to skip the bean registration for some conditional reason.<br/>The following example shows how to do so:<br/><br/>```<br/>@Bean<br/>@ServiceActivator(inputChannel = "skippedChannel")<br/>@Profile("thing")<br/>public MessageHandler skipped() {<br/> return System.out::println;<br/>}<br/>```<br/><br/>Together with the existing Spring container logic, the messaging endpoint bean (based on the `@ServiceActivator` annotation), is also not registered.|
| |With Java configuration, you can use any `@Conditional` (for example, `@Profile`) definition on the `@Bean` method level to skip the bean registration for some conditional reason.<br/>The following example shows how to do so:<br/><br/>```<br/>@Bean<br/>@ServiceActivator(inputChannel = "skippedChannel")<br/>@Profile("thing")<br/>public MessageHandler skipped() {<br/> return System.out::println;<br/>}<br/>```<br/><br/>Together with the existing Spring container logic, the messaging endpoint bean (based on the `@ServiceActivator` annotation), is also not registered.|
#### [](#creating-a-bridge-with-annotations)Creating a Bridge with Annotations
#### Creating a Bridge with Annotations
Starting with version 4.0, Java configuration provides the `@BridgeFrom` and `@BridgeTo` `@Bean` method annotations to mark `MessageChannel` beans in `@Configuration` classes.
Starting with version 4.0, Java configuration provides the `@BridgeFrom` and `@BridgeTo` `@Bean` method annotations to mark `MessageChannel` beans in `@Configuration` classes.
These really exists for completeness, providing a convenient mechanism to declare a `BridgeHandler` and its message endpoint configuration:
These really exists for completeness, providing a convenient mechanism to declare a `BridgeHandler` and its message endpoint configuration:
...
@@ -587,16 +587,16 @@ public MessageChannel bridgeToInput() {
...
@@ -587,16 +587,16 @@ public MessageChannel bridgeToInput() {
You can use these annotations as meta-annotations as well.
You can use these annotations as meta-annotations as well.
See [Advising Endpoints Using Annotations](./handler-advice.html#advising-with-annotations).
See [Advising Endpoints Using Annotations](./handler-advice.html#advising-with-annotations).
### [](#message-mapping-rules)Message Mapping Rules and Conventions
### Message Mapping Rules and Conventions
Spring Integration implements a flexible facility to map messages to methods and their arguments without providing extra configuration, by relying on some default rules and defining certain conventions.
Spring Integration implements a flexible facility to map messages to methods and their arguments without providing extra configuration, by relying on some default rules and defining certain conventions.
The examples in the following sections articulate the rules.
The examples in the following sections articulate the rules.
#### [](#sample-scenarios)Sample Scenarios
#### Sample Scenarios
The following example shows a single un-annotated parameter (object or primitive) that is not a `Map` or a `Properties` object with a non-void return type:
The following example shows a single un-annotated parameter (object or primitive) that is not a `Map` or a `Properties` object with a non-void return type:
...
@@ -674,7 +674,7 @@ public void soSomething();
...
@@ -674,7 +674,7 @@ public void soSomething();
This example is the same as the previous example, but it produces no output.
This example is the same as the previous example, but it produces no output.
Annotation-based mapping is the safest and least ambiguous approach to map messages to methods.
Annotation-based mapping is the safest and least ambiguous approach to map messages to methods.
The following example shows how to explicitly map a method to a header:
The following example shows how to explicitly map a method to a header:
...
@@ -715,7 +715,7 @@ However, with annotation-based mapping, the ambiguity is easily avoided.
...
@@ -715,7 +715,7 @@ However, with annotation-based mapping, the ambiguity is easily avoided.
In this example the first argument is mapped to all the message headers, while the second and third argument map to the values of the message headers named 'something' and 'someotherthing'.
In this example the first argument is mapped to all the message headers, while the second and third argument map to the values of the message headers named 'something' and 'someotherthing'.
The Spring Integration Java configuration and DSL provides a set of convenient builders and a fluent API that lets you configure Spring Integration message flows from Spring `@Configuration` classes.
The Spring Integration Java configuration and DSL provides a set of convenient builders and a fluent API that lets you configure Spring Integration message flows from Spring `@Configuration` classes.
...
@@ -52,7 +52,7 @@ The result of the preceding configuration example is that it creates, after `App
...
@@ -52,7 +52,7 @@ The result of the preceding configuration example is that it creates, after `App
Java configuration can be used both to replace and augment XML configuration.
Java configuration can be used both to replace and augment XML configuration.
You need not replace all of your existing XML configuration to use Java configuration.
You need not replace all of your existing XML configuration to use Java configuration.
### [](#java-dsl-basics)DSL Basics
### DSL Basics
The `org.springframework.integration.dsl` package contains the `IntegrationFlowBuilder` API mentioned earlier and a number of `IntegrationComponentSpec` implementations, which are also builders and provide the fluent API to configure concrete endpoints.
The `org.springframework.integration.dsl` package contains the `IntegrationFlowBuilder` API mentioned earlier and a number of `IntegrationComponentSpec` implementations, which are also builders and provide the fluent API to configure concrete endpoints.
The `IntegrationFlowBuilder` infrastructure provides common [enterprise integration patterns](https://www.enterpriseintegrationpatterns.com/)(EIP) for message-based applications, such as channels, endpoints, pollers, and channel interceptors.
The `IntegrationFlowBuilder` infrastructure provides common [enterprise integration patterns](https://www.enterpriseintegrationpatterns.com/)(EIP) for message-based applications, such as channels, endpoints, pollers, and channel interceptors.
...
@@ -118,7 +118,7 @@ The endpoints are automatically wired together by using direct channels.
...
@@ -118,7 +118,7 @@ The endpoints are automatically wired together by using direct channels.
| |Bean Definitions override<br/><br/>The Java DSL can register beans for the object defined in-line in the flow definition, as well as can reuse existing, injected beans.<br/>In case of the same bean name defined for in-line object and existing bean definition, a `BeanDefinitionOverrideException` is thrown indicating that such a configuration is wrong.<br/>However when you deal with `prototype` beans, there is no way to detect from the integration flow processor an existing bean definition because every time we call a `prototype` bean from the `BeanFactory` we get a new instance.<br/>This way a provided instance is used in the `IntegrationFlow` as is without any bean registration and any possible check against existing `prototype` bean definition.<br/>However `BeanFactory.initializeBean()` is called for this object if it has an explicit `id` and bean definition for this name is in `prototype` scope.|
| |Bean Definitions override<br/><br/>The Java DSL can register beans for the object defined in-line in the flow definition, as well as can reuse existing, injected beans.<br/>In case of the same bean name defined for in-line object and existing bean definition, a `BeanDefinitionOverrideException` is thrown indicating that such a configuration is wrong.<br/>However when you deal with `prototype` beans, there is no way to detect from the integration flow processor an existing bean definition because every time we call a `prototype` bean from the `BeanFactory` we get a new instance.<br/>This way a provided instance is used in the `IntegrationFlow` as is without any bean registration and any possible check against existing `prototype` bean definition.<br/>However `BeanFactory.initializeBean()` is called for this object if it has an explicit `id` and bean definition for this name is in `prototype` scope.|
In addition to the `IntegrationFlowBuilder` with EIP methods, the Java DSL provides a fluent API to configure `MessageChannel` instances.
In addition to the `IntegrationFlowBuilder` with EIP methods, the Java DSL provides a fluent API to configure `MessageChannel` instances.
For this purpose the `MessageChannels` builder factory is provided.
For this purpose the `MessageChannels` builder factory is provided.
...
@@ -208,7 +208,7 @@ Could not register object [queueChannel] under bean name 'queueChannel':
...
@@ -208,7 +208,7 @@ Could not register object [queueChannel] under bean name 'queueChannel':
To make it work, you need to declare `@Bean` for that channel and use its bean method from different `IntegrationFlow` instances.
To make it work, you need to declare `@Bean` for that channel and use its bean method from different `IntegrationFlow` instances.
### [](#java-dsl-pollers)Pollers
### Pollers
Spring Integration also provides a fluent API that lets you configure `PollerMetadata` for `AbstractPollingEndpoint` implementations.
Spring Integration also provides a fluent API that lets you configure `PollerMetadata` for `AbstractPollingEndpoint` implementations.
You can use the `Pollers` builder factory to configure common bean definitions or those created from `IntegrationFlowBuilder` EIP methods, as the following example shows:
You can use the `Pollers` builder factory to configure common bean definitions or those created from `IntegrationFlowBuilder` EIP methods, as the following example shows:
...
@@ -226,7 +226,7 @@ See [`Pollers`](https://docs.spring.io/spring-integration/api/org/springframewor
...
@@ -226,7 +226,7 @@ See [`Pollers`](https://docs.spring.io/spring-integration/api/org/springframewor
| |If you use the DSL to construct a `PollerSpec` as a `@Bean`, do not call the `get()` method in the bean definition.<br/>The `PollerSpec` is a `FactoryBean` that generates the `PollerMetadata` object from the specification and initializes all of its properties.|
| |If you use the DSL to construct a `PollerSpec` as a `@Bean`, do not call the `get()` method in the bean definition.<br/>The `PollerSpec` is a `FactoryBean` that generates the `PollerMetadata` object from the specification and initializes all of its properties.|
Starting with version 5.5, the `ConsumerEndpointSpec` provides a `reactive()` configuration property with an optional customizer `Function<? super Flux<Message<?>>, ? extends Publisher<Message<?>>>`.
Starting with version 5.5, the `ConsumerEndpointSpec` provides a `reactive()` configuration property with an optional customizer `Function<? super Flux<Message<?>>, ? extends Publisher<Message<?>>>`.
This option configures the target endpoint as a `ReactiveStreamsConsumer` instance, independently of the input channel type, which is converted to a `Flux` via `IntegrationReactiveUtils.messageChannelToFlux()`.
This option configures the target endpoint as a `ReactiveStreamsConsumer` instance, independently of the input channel type, which is converted to a `Flux` via `IntegrationReactiveUtils.messageChannelToFlux()`.
...
@@ -247,7 +247,7 @@ public IntegrationFlow reactiveEndpointFlow() {
...
@@ -247,7 +247,7 @@ public IntegrationFlow reactiveEndpointFlow() {
See [Reactive Streams Support](./reactive-streams.html#reactive-streams) for more information.
See [Reactive Streams Support](./reactive-streams.html#reactive-streams) for more information.
### [](#java-dsl-endpoints)DSL and Endpoint Configuration
### DSL and Endpoint Configuration
All `IntegrationFlowBuilder` EIP methods have a variant that applies the lambda parameter to provide options for `AbstractEndpoint` instances: `SmartLifecycle`, `PollerMetadata`, `request-handler-advice-chain`, and others.
All `IntegrationFlowBuilder` EIP methods have a variant that applies the lambda parameter to provide options for `AbstractEndpoint` instances: `SmartLifecycle`, `PollerMetadata`, `request-handler-advice-chain`, and others.
Each of them has generic arguments, so it lets you configure an endpoint and even its `MessageHandler` in the context, as the following example shows:
Each of them has generic arguments, so it lets you configure an endpoint and even its `MessageHandler` in the context, as the following example shows:
...
@@ -286,7 +286,7 @@ public IntegrationFlow clientTcpFlow() {
...
@@ -286,7 +286,7 @@ public IntegrationFlow clientTcpFlow() {
That is they are not merged, only the `testAdvice()` bean is used in this case.
That is they are not merged, only the `testAdvice()` bean is used in this case.
### [](#java-dsl-transformers)Transformers
### Transformers
The DSL API provides a convenient, fluent `Transformers` factory to be used as inline target object definition within the `.transform()` EIP method.
The DSL API provides a convenient, fluent `Transformers` factory to be used as inline target object definition within the `.transform()` EIP method.
The following example shows how to use it:
The following example shows how to use it:
...
@@ -309,7 +309,7 @@ See [Transformers](https://docs.spring.io/spring-integration/api/org/springframe
...
@@ -309,7 +309,7 @@ See [Transformers](https://docs.spring.io/spring-integration/api/org/springframe
Also see [Lambdas And `Message<?>` Arguments](#java-dsl-class-cast).
Also see [Lambdas And `Message<?>` Arguments](#java-dsl-class-cast).
Typically, message flows start from an inbound channel adapter (such as `<int-jdbc:inbound-channel-adapter>`).
Typically, message flows start from an inbound channel adapter (such as `<int-jdbc:inbound-channel-adapter>`).
The adapter is configured with `<poller>`, and it asks a `MessageSource<?>` to periodically produce messages.
The adapter is configured with `<poller>`, and it asks a `MessageSource<?>` to periodically produce messages.
...
@@ -338,7 +338,7 @@ public IntegrationFlow pollingFlow() {
...
@@ -338,7 +338,7 @@ public IntegrationFlow pollingFlow() {
For those cases that have no requirements to build `Message` objects directly, you can use a `IntegrationFlows.fromSupplier()` variant that is based on the `java.util.function.Supplier` .
For those cases that have no requirements to build `Message` objects directly, you can use a `IntegrationFlows.fromSupplier()` variant that is based on the `java.util.function.Supplier` .
The result of the `Supplier.get()` is automatically wrapped in a `Message` (if it is not already a `Message`).
The result of the `Supplier.get()` is automatically wrapped in a `Message` (if it is not already a `Message`).
### [](#java-dsl-routers)Message Routers
### Message Routers
Spring Integration natively provides specialized router types, including:
Spring Integration natively provides specialized router types, including:
...
@@ -410,7 +410,7 @@ The `.defaultOutputToParentFlow()` of the `.routeToRecipients()` definition lets
...
@@ -410,7 +410,7 @@ The `.defaultOutputToParentFlow()` of the `.routeToRecipients()` definition lets
Also see [Lambdas And `Message<?>` Arguments](#java-dsl-class-cast).
Also see [Lambdas And `Message<?>` Arguments](#java-dsl-class-cast).
### [](#java-dsl-splitters)Splitters
### Splitters
To create a splitter, use the `split()` EIP method.
To create a splitter, use the `split()` EIP method.
By default, if the payload is an `Iterable`, an `Iterator`, an `Array`, a `Stream`, or a reactive `Publisher`, the `split()` method outputs each item as an individual message.
By default, if the payload is an `Iterable`, an `Iterator`, an `Array`, a `Stream`, or a reactive `Publisher`, the `split()` method outputs each item as an individual message.
...
@@ -432,7 +432,7 @@ The preceding example creates a splitter that splits a message containing a comm
...
@@ -432,7 +432,7 @@ The preceding example creates a splitter that splits a message containing a comm
Also see [Lambdas And `Message<?>` Arguments](#java-dsl-class-cast).
Also see [Lambdas And `Message<?>` Arguments](#java-dsl-class-cast).
### [](#java-dsl-aggregators)Aggregators and Resequencers
### Aggregators and Resequencers
An `Aggregator` is conceptually the opposite of a `Splitter`.
An `Aggregator` is conceptually the opposite of a `Splitter`.
It aggregates a sequence of individual messages into a single message and is necessarily more complex.
It aggregates a sequence of individual messages into a single message and is necessarily more complex.
...
@@ -470,7 +470,7 @@ The preceding example correlates messages that have `myCorrelationKey` headers a
...
@@ -470,7 +470,7 @@ The preceding example correlates messages that have `myCorrelationKey` headers a
Similar lambda configurations are provided for the `resequence()` EIP method.
Similar lambda configurations are provided for the `resequence()` EIP method.
### [](#java-dsl-handle)Service Activators and the `.handle()` method
### ` method
The `.handle()` EIP method’s goal is to invoke any `MessageHandler` implementation or any method on some POJO.
The `.handle()` EIP method’s goal is to invoke any `MessageHandler` implementation or any method on some POJO.
Another option is to define an “activity” by using lambda expressions.
Another option is to define an “activity” by using lambda expressions.
...
@@ -523,7 +523,7 @@ public IntegrationFlow integerFlow() {
...
@@ -523,7 +523,7 @@ public IntegrationFlow integerFlow() {
Also see [Lambdas And `Message<?>` Arguments](#java-dsl-class-cast).
Also see [Lambdas And `Message<?>` Arguments](#java-dsl-class-cast).
### [](#java-dsl-gateway)Operator gateway()
###
The `gateway()` operator in an `IntegrationFlow` definition is a special service activator implementation, to call some other endpoint or integration flow via its input channel and wait for reply.
The `gateway()` operator in an `IntegrationFlow` definition is a special service activator implementation, to call some other endpoint or integration flow via its input channel and wait for reply.
Technically it plays the same role as a nested `<gateway>` component in a `<chain>` definition (see [Calling a Chain from within a Chain](./chain.html#chain-gateway)) and allows a flow to be cleaner and more straightforward.
Technically it plays the same role as a nested `<gateway>` component in a `<chain>` definition (see [Calling a Chain from within a Chain](./chain.html#chain-gateway)) and allows a flow to be cleaner and more straightforward.
| |If the downstream flow does not always return a reply, you should set the `requestTimeout` to 0 to prevent hanging the calling thread indefinitely.<br/>In that case, the flow will end at that point and the thread released for further work.|
| |If the downstream flow does not always return a reply, you should set the `requestTimeout` to 0 to prevent hanging the calling thread indefinitely.<br/>In that case, the flow will end at that point and the thread released for further work.|
For convenience, to log the message journey through the Spring Integration flow (`<logging-channel-adapter>`), a `log()` operator is presented.
For convenience, to log the message journey through the Spring Integration flow (`<logging-channel-adapter>`), a `log()` operator is presented.
Internally, it is represented by the `WireTap``ChannelInterceptor` with a `LoggingHandler` as its subscriber.
Internally, it is represented by the `WireTap``ChannelInterceptor` with a `LoggingHandler` as its subscriber.
...
@@ -577,7 +577,7 @@ In the preceding example, an `id` header is logged at the `ERROR` level onto `te
...
@@ -577,7 +577,7 @@ In the preceding example, an `id` header is logged at the `ERROR` level onto `te
When this operator is used at the end of a flow, it is a one-way handler and the flow ends.
When this operator is used at the end of a flow, it is a one-way handler and the flow ends.
To make it as a reply-producing flow, you can either use a simple `bridge()` after the `log()` or, starting with version 5.1, you can use a `logAndReply()` operator instead.`logAndReply` can only be used at the end of a flow.
To make it as a reply-producing flow, you can either use a simple `bridge()` after the `log()` or, starting with version 5.1, you can use a `logAndReply()` operator instead.`logAndReply` can only be used at the end of a flow.
### [](#java-dsl-intercept)Operator intercept()
###
Starting with version 5.3, the `intercept()` operator allows to register one or more `ChannelInterceptor` instances at the current `MessageChannel` in the flow.
Starting with version 5.3, the `intercept()` operator allows to register one or more `ChannelInterceptor` instances at the current `MessageChannel` in the flow.
This is an alternative to creating an explicit `MessageChannel` via the `MessageChannels` API.
This is an alternative to creating an explicit `MessageChannel` via the `MessageChannels` API.
...
@@ -589,7 +589,7 @@ The following example uses a `MessageSelectingInterceptor` to reject certain mes
...
@@ -589,7 +589,7 @@ The following example uses a `MessageSelectingInterceptor` to reject certain mes
Spring Integration includes a `.wireTap()` fluent API `MessageChannelSpec` builders.
Spring Integration includes a `.wireTap()` fluent API `MessageChannelSpec` builders.
The following example shows how to use the `wireTap` method to log input:
The following example shows how to use the `wireTap` method to log input:
...
@@ -621,7 +621,7 @@ The following example does not have any channel declaration:
...
@@ -621,7 +621,7 @@ The following example does not have any channel declaration:
In the preceding example (and any time no channel has been declared), an implicit `DirectChannel` is injected in the current position of the `IntegrationFlow` and used as an output channel for the currently configured `ServiceActivatingHandler` (from the `.handle()`, [described earlier](#java-dsl-handle)).
In the preceding example (and any time no channel has been declared), an implicit `DirectChannel` is injected in the current position of the `IntegrationFlow` and used as an output channel for the currently configured `ServiceActivatingHandler` (from the `.handle()`, [described earlier](#java-dsl-handle)).
### [](#java-dsl-flows)Working With Message Flows
### Working With Message Flows
`IntegrationFlowBuilder` provides a top-level API to produce integration components wired to message flows.
`IntegrationFlowBuilder` provides a top-level API to produce integration components wired to message flows.
When your integration may be accomplished with a single flow (which is often the case), this is convenient.
When your integration may be accomplished with a single flow (which is often the case), this is convenient.
...
@@ -662,7 +662,7 @@ The same pattern is applied for all the `NamedComponent` s when the bean name ha
...
@@ -662,7 +662,7 @@ The same pattern is applied for all the `NamedComponent` s when the bean name ha
These generated bean names are prepended with the flow ID for purposes such as parsing logs or grouping components together in some analysis tool, as well as to avoid a race condition when we concurrently register integration flows at runtime.
These generated bean names are prepended with the flow ID for purposes such as parsing logs or grouping components together in some analysis tool, as well as to avoid a race condition when we concurrently register integration flows at runtime.
See [Dynamic and Runtime Integration Flows](#java-dsl-runtime-flows) for more information.
See [Dynamic and Runtime Integration Flows](#java-dsl-runtime-flows) for more information.
We introduced the `FunctionExpression` class (an implementation of SpEL’s `Expression` interface) to let us use lambdas and `generics`.
We introduced the `FunctionExpression` class (an implementation of SpEL’s `Expression` interface) to let us use lambdas and `generics`.
The `Function<T, R>` option is provided for the DSL components, along with an `expression` option, when there is the implicit `Strategy` variant from Core Spring Integration.
The `Function<T, R>` option is provided for the DSL components, along with an `expression` option, when there is the implicit `Strategy` variant from Core Spring Integration.
...
@@ -676,7 +676,7 @@ The following example shows how to use a function expression:
...
@@ -676,7 +676,7 @@ The following example shows how to use a function expression:
The `FunctionExpression` also supports runtime type conversion, as is done in `SpelExpression`.
The `FunctionExpression` also supports runtime type conversion, as is done in `SpelExpression`.
### [](#java-dsl-subflows)Sub-flows support
### Sub-flows support
Some of `if…else` and `publish-subscribe` components provide the ability to specify their logic or mapping by using sub-flows.
Some of `if…else` and `publish-subscribe` components provide the ability to specify their logic or mapping by using sub-flows.
The simplest sample is `.publishSubscribeChannel()`, as the following example shows:
The simplest sample is `.publishSubscribeChannel()`, as the following example shows:
...
@@ -762,7 +762,7 @@ In fact, even in the router case, adding complex sub-flows within a flow would q
...
@@ -762,7 +762,7 @@ In fact, even in the router case, adding complex sub-flows within a flow would q
| |In cases where the DSL supports a subflow configuration, when a channel is normally needed for the component being configured, and that subflow starts with a `channel()` element, the framework implicitly places a `bridge()` between the component output channel and the flow’s input channel.<br/>For example, in this `filter` definition:<br/><br/>```<br/>.filter(p -> p instanceof String, e -> e<br/> .discardFlow(df -> df<br/> .channel(MessageChannels.queue())<br/> ...)<br/>```<br/><br/>the Framework internally creates a `DirectChannel` bean for injecting into the `MessageFilter.discardChannel`.<br/>Then it wraps the subflow into an `IntegrationFlow` starting with this implicit channel for the subscription and places a `bridge` before the `channel()` specified in the flow.<br/>When an existing `IntegrationFlow` bean is used as a subflow reference (instead of an inline subflow, e.g. a lambda), there is no such bridge required because the framework can resolve the first channel from the flow bean.<br/>With an inline subflow, the input channel is not yet available.|
| |In cases where the DSL supports a subflow configuration, when a channel is normally needed for the component being configured, and that subflow starts with a `channel()` element, the framework implicitly places a `bridge()` between the component output channel and the flow’s input channel.<br/>For example, in this `filter` definition:<br/><br/>```<br/>.filter(p -> p instanceof String, e -> e<br/> .discardFlow(df -> df<br/> .channel(MessageChannels.queue())<br/> ...)<br/>```<br/><br/>the Framework internally creates a `DirectChannel` bean for injecting into the `MessageFilter.discardChannel`.<br/>Then it wraps the subflow into an `IntegrationFlow` starting with this implicit channel for the subscription and places a `bridge` before the `channel()` specified in the flow.<br/>When an existing `IntegrationFlow` bean is used as a subflow reference (instead of an inline subflow, e.g. a lambda), there is no such bridge required because the framework can resolve the first channel from the flow bean.<br/>With an inline subflow, the input channel is not yet available.|
Starting with version 5.3, an `IntegrationFlowExtension` has been introduced to allow extension of the existing Java DSL with custom or composed EIP-operators.
Starting with version 5.3, an `IntegrationFlowExtension` has been introduced to allow extension of the existing Java DSL with custom or composed EIP-operators.
All that is needed is an extension of this class that provides methods which can be used in the `IntegrationFlow` bean definitions.
All that is needed is an extension of this class that provides methods which can be used in the `IntegrationFlow` bean definitions.
...
@@ -1146,7 +1146,7 @@ public IntegrationFlow customFlowDefinition() {
...
@@ -1146,7 +1146,7 @@ public IntegrationFlow customFlowDefinition() {
With the `MessageChannel` abstraction as a first class citizen in Spring Integration, the composition of integration flows was always assumed.
With the `MessageChannel` abstraction as a first class citizen in Spring Integration, the composition of integration flows was always assumed.
The input channel of any endpoint in the flow can be used to send messages from any other endpoint and not only from the one which has this channel as an output.
The input channel of any endpoint in the flow can be used to send messages from any other endpoint and not only from the one which has this channel as an output.
As discussed in the earlier sections, Spring Integration provides a number of endpoints used to interface with external systems, file systems, and others.
As discussed in the earlier sections, Spring Integration provides a number of endpoints used to interface with external systems, file systems, and others.
As described in the [overview](./overview.html#overview) at the very beginning of this manual, one of the main motivations behind a message-oriented framework such as Spring Integration is to promote loose coupling between components.
As described in the [overview](./overview.html#overview) at the very beginning of this manual, one of the main motivations behind a message-oriented framework such as Spring Integration is to promote loose coupling between components.
The message channel plays an important role, in that producers and consumers do not have to know about each other.
The message channel plays an important role, in that producers and consumers do not have to know about each other.
## [](#applicationevent)Spring `ApplicationEvent` Support
## Spring `ApplicationEvent` Support
Spring Integration provides support for inbound and outbound `ApplicationEvents`, as defined by the underlying Spring Framework.
Spring Integration provides support for inbound and outbound `ApplicationEvents`, as defined by the underlying Spring Framework.
For more information about Spring’s support for events and listeners, see the [Spring Reference Manual](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#context-functionality-events).
For more information about Spring’s support for events and listeners, see the [Spring Reference Manual](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#context-functionality-events).
### [](#appevent-inbound)Receiving Spring Application Events
### Receiving Spring Application Events
To receive events and send them to a channel, you can define an instance of Spring Integration’s `ApplicationEventListeningMessageProducer`.
To receive events and send them to a channel, you can define an instance of Spring Integration’s `ApplicationEventListeningMessageProducer`.
This class is an implementation of Spring’s `ApplicationListener` interface.
This class is an implementation of Spring’s `ApplicationListener` interface.
...
@@ -89,7 +89,7 @@ public IntegrationFlow eventFlow(ApplicationEventListeningMessageProducer events
...
@@ -89,7 +89,7 @@ public IntegrationFlow eventFlow(ApplicationEventListeningMessageProducer events
}
}
```
```
### [](#appevent-outbound)Sending Spring Application Events
### Sending Spring Application Events
To send Spring `ApplicationEvents`, create an instance of the `ApplicationEventPublishingMessageHandler` and register it within an endpoint.
To send Spring `ApplicationEvents`, create an instance of the `ApplicationEventPublishingMessageHandler` and register it within an endpoint.
This implementation of the `MessageHandler` interface also implements Spring’s `ApplicationEventPublisherAware` interface and consequently acts as a bridge between Spring Integration messages and `ApplicationEvents`.
This implementation of the `MessageHandler` interface also implements Spring’s `ApplicationEventPublisherAware` interface and consequently acts as a bridge between Spring Integration messages and `ApplicationEvents`.
The only adapter you really need to provide support for retrieving feeds is an inbound channel adapter.
The only adapter you really need to provide support for retrieving feeds is an inbound channel adapter.
It lets you subscribe to a particular URL.
It lets you subscribe to a particular URL.
...
@@ -63,7 +63,7 @@ Each entry is stored in the local entry queue and is released based on the value
...
@@ -63,7 +63,7 @@ Each entry is stored in the local entry queue and is released based on the value
If, during retrieval of the entries from the entry queue, the queue has become empty, the adapter attempts to update the feed, thereby populating the queue with more entries (`SyndEntry` instances), if any are available.
If, during retrieval of the entries from the entry queue, the queue has become empty, the adapter attempts to update the feed, thereby populating the queue with more entries (`SyndEntry` instances), if any are available.
Otherwise the next attempt to poll for a feed is determined by the trigger of the poller (every ten seconds in the preceding configuration).
Otherwise the next attempt to poll for a feed is determined by the trigger of the poller (every ten seconds in the preceding configuration).
### [](#duplicate-entries)Duplicate Entries
### Duplicate Entries
Polling for a feed can result in entries that have already been processed (“I already read that news item, why are you showing it to me again?”).
Polling for a feed can result in entries that have already been processed (“I already read that news item, why are you showing it to me again?”).
Spring Integration provides a convenient mechanism to eliminate the need to worry about duplicate entries.
Spring Integration provides a convenient mechanism to eliminate the need to worry about duplicate entries.
...
@@ -73,7 +73,7 @@ Every time a new `Message` is generated and sent, Spring Integration stores the
...
@@ -73,7 +73,7 @@ Every time a new `Message` is generated and sent, Spring Integration stores the
| |The key used to persist the latest published date is the value of the (required) `id` attribute of the feed inbound channel adapter component plus the `feedUrl` (if any) from the adapter’s configuration.|
| |The key used to persist the latest published date is the value of the (required) `id` attribute of the feed inbound channel adapter component plus the `feedUrl` (if any) from the adapter’s configuration.|
Starting with version 5.0, the deprecated `com.rometools.fetcher.FeedFetcher` option has been removed and an overloaded `FeedEntryMessageSource` constructor for an `org.springframework.core.io.Resource` is provided.
Starting with version 5.0, the deprecated `com.rometools.fetcher.FeedFetcher` option has been removed and an overloaded `FeedEntryMessageSource` constructor for an `org.springframework.core.io.Resource` is provided.
This is useful when the feed source is not an HTTP endpoint but is any other resource (such as local or remote on FTP).
This is useful when the feed source is not an HTTP endpoint but is any other resource (such as local or remote on FTP).
...
@@ -83,7 +83,7 @@ You can also inject a customized `SyndFeedInput` (for example, with the `allowDo
...
@@ -83,7 +83,7 @@ You can also inject a customized `SyndFeedInput` (for example, with the `allowDo
| |If the connection to the feed needs some customization, e.g. connection and read timeouts, the `org.springframework.core.io.UrlResource` extension with its `customizeConnection(HttpURLConnection)` override has to be used instead of plain `URL` injection into the `FeedEntryMessageSource`.<br/>For example:<br/><br/>```<br/>@Bean<br/>@InboundChannelAdapter("feedChannel")<br/>FeedEntryMessageSource feedEntrySource() {<br/> UrlResource urlResource =<br/> new UrlResource(url) {<br/><br/> @Override<br/> protected void customizeConnection(HttpURLConnection connection) throws IOException {<br/> super.customizeConnection(connection);<br/> connection.setConnectTimeout(10000);<br/> connection.setReadTimeout(5000);<br/> }<br/> };<br/> return new FeedEntryMessageSource(urlResource, "myKey");<br/>}<br/>```|
| |If the connection to the feed needs some customization, e.g. connection and read timeouts, the `org.springframework.core.io.UrlResource` extension with its `customizeConnection(HttpURLConnection)` override has to be used instead of plain `URL` injection into the `FeedEntryMessageSource`.<br/>For example:<br/><br/>```<br/>@Bean<br/>@InboundChannelAdapter("feedChannel")<br/>FeedEntryMessageSource feedEntrySource() {<br/> UrlResource urlResource =<br/> new UrlResource(url) {<br/><br/> @Override<br/> protected void customizeConnection(HttpURLConnection connection) throws IOException {<br/> super.customizeConnection(connection);<br/> connection.setConnectTimeout(10000);<br/> connection.setReadTimeout(5000);<br/> }<br/> };<br/> return new FeedEntryMessageSource(urlResource, "myKey");<br/>}<br/>```|
Spring Integration’s file support extends the Spring Integration core with a dedicated vocabulary to deal with reading, writing, and transforming files.
Spring Integration’s file support extends the Spring Integration core with a dedicated vocabulary to deal with reading, writing, and transforming files.
...
@@ -28,7 +28,7 @@ This section explains the workings of `FileReadingMessageSource` and `FileWritin
...
@@ -28,7 +28,7 @@ This section explains the workings of `FileReadingMessageSource` and `FileWritin
It also discusses the support for dealing with files through file-specific implementations of `Transformer`.
It also discusses the support for dealing with files through file-specific implementations of `Transformer`.
Finally, it explains the file-specific namespace.
Finally, it explains the file-specific namespace.
### [](#file-reading)Reading Files
### Reading Files
A `FileReadingMessageSource` can be used to consume files from the filesystem.
A `FileReadingMessageSource` can be used to consume files from the filesystem.
This is an implementation of `MessageSource` that creates messages from a file system directory.
This is an implementation of `MessageSource` that creates messages from a file system directory.
...
@@ -153,7 +153,7 @@ The `CompositeFileListFilter` also implements a `DiscardAwareFileListFilter` and
...
@@ -153,7 +153,7 @@ The `CompositeFileListFilter` also implements a `DiscardAwareFileListFilter` and
Starting with version 5.1, the `FileReadingMessageSource` doesn’t check a directory for existence and doesn’t create it until its `start()` is called (typically via wrapping `SourcePollingChannelAdapter`).
Starting with version 5.1, the `FileReadingMessageSource` doesn’t check a directory for existence and doesn’t create it until its `start()` is called (typically via wrapping `SourcePollingChannelAdapter`).
Previously, there was no simple way to prevent an operation system permissions error when referencing the directory, for example from tests, or when permissions are applied later.
Previously, there was no simple way to prevent an operation system permissions error when referencing the directory, for example from tests, or when permissions are applied later.
#### [](#message-headers)Message Headers
#### Message Headers
Starting with version 5.0, the `FileReadingMessageSource` (in addition to the `payload` as a polled `File`) populates the following headers to the outbound `Message`:
Starting with version 5.0, the `FileReadingMessageSource` (in addition to the `payload` as a polled `File`) populates the following headers to the outbound `Message`:
...
@@ -168,7 +168,7 @@ Starting with version 5.0, the `FileReadingMessageSource` (in addition to the `p
...
@@ -168,7 +168,7 @@ Starting with version 5.0, the `FileReadingMessageSource` (in addition to the `p
This header can be useful when the requirement is to restore a source directory hierarchy in the other places.
This header can be useful when the requirement is to restore a source directory hierarchy in the other places.
For this purpose, the `DefaultFileNameGenerator` (see "`[Generating File Names](#file-writing-file-names)) can be configured to use this header.
For this purpose, the `DefaultFileNameGenerator` (see "`[Generating File Names](#file-writing-file-names)) can be configured to use this header.
#### [](#directory-scanning-and-polling)Directory Scanning and Polling
#### Directory Scanning and Polling
The `FileReadingMessageSource` does not produce messages for files from the directory immediately.
The `FileReadingMessageSource` does not produce messages for files from the directory immediately.
It uses an internal queue for 'eligible files' returned by the `scanner`.
It uses an internal queue for 'eligible files' returned by the `scanner`.
...
@@ -193,7 +193,7 @@ See [`AbstractDirectoryAwareFileListFilter`](https://docs.spring.io/spring-integ
...
@@ -193,7 +193,7 @@ See [`AbstractDirectoryAwareFileListFilter`](https://docs.spring.io/spring-integ
| |Starting with version 5.5, the `FileInboundChannelAdapterSpec` of the Java DSL has a convenient `recursive(boolean)` option to use a `RecursiveDirectoryScanner` in the target `FileReadingMessageSource` instead of the default one.|
| |Starting with version 5.5, the `FileInboundChannelAdapterSpec` of the Java DSL has a convenient `recursive(boolean)` option to use a `RecursiveDirectoryScanner` in the target `FileReadingMessageSource` instead of the default one.|
The configuration for file reading can be simplified by using the file-specific namespace.
The configuration for file reading can be simplified by using the file-specific namespace.
To do so, use the following template:
To do so, use the following template:
...
@@ -293,7 +293,7 @@ In other words, if you inject a `scanner` into the `FileReadingMessageSource`, y
...
@@ -293,7 +293,7 @@ In other words, if you inject a `scanner` into the `FileReadingMessageSource`, y
| |By default, the `DefaultDirectoryScanner` uses an `IgnoreHiddenFileListFilter` and an `AcceptOnceFileListFilter`.<br/>To prevent their use, you can configure your own filter (such as `AcceptAllFileListFilter`) or even set it to `null`.|
| |By default, the `DefaultDirectoryScanner` uses an `IgnoreHiddenFileListFilter` and an `AcceptOnceFileListFilter`.<br/>To prevent their use, you can configure your own filter (such as `AcceptAllFileListFilter`) or even set it to `null`.|
You can use a `HeadDirectoryScanner` to limit the number of files retained in memory.
You can use a `HeadDirectoryScanner` to limit the number of files retained in memory.
This can be useful when scanning large directories.
This can be useful when scanning large directories.
...
@@ -348,7 +348,7 @@ Any other filters (including `prevent-duplicates="true"`) overwrote the filter u
...
@@ -348,7 +348,7 @@ Any other filters (including `prevent-duplicates="true"`) overwrote the filter u
| |The use of a `HeadDirectoryScanner` is incompatible with an `AcceptOnceFileListFilter`.<br/>Since all filters are consulted during the poll decision, the `AcceptOnceFileListFilter` does not know that other filters might be temporarily filtering files.<br/>Even if files that were previously filtered by the `HeadDirectoryScanner.HeadFilter` are now available, the `AcceptOnceFileListFilter` filters them.<br/><br/>Generally, instead of using an `AcceptOnceFileListFilter` in this case, you should remove the processed files so that the previously filtered files are available on a future poll.|
| |The use of a `HeadDirectoryScanner` is incompatible with an `AcceptOnceFileListFilter`.<br/>Since all filters are consulted during the poll decision, the `AcceptOnceFileListFilter` does not know that other filters might be temporarily filtering files.<br/>Even if files that were previously filtered by the `HeadDirectoryScanner.HeadFilter` are now available, the `AcceptOnceFileListFilter` filters them.<br/><br/>Generally, instead of using an `AcceptOnceFileListFilter` in this case, you should remove the processed files so that the previously filtered files are available on a future poll.|
#### [](#configuring-with-java-configuration)Configuring with Java Configuration
#### Configuring with Java Configuration
The following Spring Boot application shows an example of how to configure the outbound adapter with Java configuration:
The following Spring Boot application shows an example of how to configure the outbound adapter with Java configuration:
...
@@ -385,7 +385,7 @@ public class FileReadingJavaApplication {
...
@@ -385,7 +385,7 @@ public class FileReadingJavaApplication {
}
}
```
```
#### [](#configuring-with-the-java-dsl)Configuring with the Java DSL
#### Configuring with the Java DSL
The following Spring Boot application shows an example of how to configure the outbound adapter with the Java DSL:
The following Spring Boot application shows an example of how to configure the outbound adapter with the Java DSL:
...
@@ -413,7 +413,7 @@ public class FileReadingJavaApplication {
...
@@ -413,7 +413,7 @@ public class FileReadingJavaApplication {
}
}
```
```
#### [](#file-tailing)'tail’ing Files
#### 'tail’ing Files
Another popular use case is to get 'lines' from the end (or tail) of a file, capturing new lines when they are added.
Another popular use case is to get 'lines' from the end (or tail) of a file, capturing new lines when they are added.
Two implementations are provided.
Two implementations are provided.
...
@@ -524,7 +524,7 @@ The following example creates an Apache `commons-io` `Tailer` adapter that exami
...
@@ -524,7 +524,7 @@ The following example creates an Apache `commons-io` `Tailer` adapter that exami
| |Specifying the `delay`, `end` or `reopen` attributes forces the use of the Apache `commons-io` adapter and makes the `native-options` attribute unavailable.|
| |Specifying the `delay`, `end` or `reopen` attributes forces the use of the Apache `commons-io` adapter and makes the `native-options` attribute unavailable.|
#### [](#file-incomplete)Dealing With Incomplete Data
#### Dealing With Incomplete Data
A common problem in file-transfer scenarios is how to determine that the transfer is complete so that you do not start reading an incomplete file.
A common problem in file-transfer scenarios is how to determine that the transfer is complete so that you do not start reading an incomplete file.
A common technique to solve this problem is to write the file with a temporary name and then atomically rename it to the final name.
A common technique to solve this problem is to write the file with a temporary name and then atomically rename it to the final name.
...
@@ -539,7 +539,7 @@ Implementations are provided for the file system (`FileSystemMarkerFilePresentFi
...
@@ -539,7 +539,7 @@ Implementations are provided for the file system (`FileSystemMarkerFilePresentFi
They are configurable such that the marker file can have any name, although it is usually related to the file being transferred.
They are configurable such that the marker file can have any name, although it is usually related to the file being transferred.
See the [Javadoc](https://docs.spring.io/spring-integration/api/org/springframework/integration/file/filters/FileSystemMarkerFilePresentFileListFilter.html) for more information.
See the [Javadoc](https://docs.spring.io/spring-integration/api/org/springframework/integration/file/filters/FileSystemMarkerFilePresentFileListFilter.html) for more information.
### [](#file-writing)Writing files
### Writing files
To write messages to the file system, you can use a [`FileWritingMessageHandler`](https://docs.spring.io/spring-integration/api/org/springframework/integration/file/FileWritingMessageHandler.html).
To write messages to the file system, you can use a [`FileWritingMessageHandler`](https://docs.spring.io/spring-integration/api/org/springframework/integration/file/FileWritingMessageHandler.html).
This class can deal with the following payload types:
This class can deal with the following payload types:
...
@@ -562,7 +562,7 @@ Starting with version 5.1, you can provide a `BiConsumer<File, Message<?>>` `new
...
@@ -562,7 +562,7 @@ Starting with version 5.1, you can provide a `BiConsumer<File, Message<?>>` `new
This callback receives a newly created file and the message which triggered it.
This callback receives a newly created file and the message which triggered it.
This callback could be used to write a CSV header defined in the message header, for an example.
This callback could be used to write a CSV header defined in the message header, for an example.
In its simplest form, the `FileWritingMessageHandler` requires only a destination directory for writing the files.
In its simplest form, the `FileWritingMessageHandler` requires only a destination directory for writing the files.
The name of the file to be written is determined by the handler’s [`FileNameGenerator`](https://docs.spring.io/spring-integration/api/org/springframework/integration/file/FileNameGenerator.html).
The name of the file to be written is determined by the handler’s [`FileNameGenerator`](https://docs.spring.io/spring-integration/api/org/springframework/integration/file/FileNameGenerator.html).
...
@@ -598,7 +598,7 @@ It is used as a second constructor argument for `File(File parent, String child)
...
@@ -598,7 +598,7 @@ It is used as a second constructor argument for `File(File parent, String child)
However, in the past we did not create (`mkdirs()`) directories for the child path, assuming only the file name.
However, in the past we did not create (`mkdirs()`) directories for the child path, assuming only the file name.
This approach is useful for cases when we need to restore the file system tree to match the source directory — for example, when unzipping the archive and saving all the files in the target directory in the original order.
This approach is useful for cases when we need to restore the file system tree to match the source directory — for example, when unzipping the archive and saving all the files in the target directory in the original order.
#### [](#file-writing-output-directory)Specifying the Output Directory
#### Specifying the Output Directory
Both, the file outbound channel adapter and the file outbound gateway provide two mutually exclusive configuration attributes for specifying the output directory:
Both, the file outbound channel adapter and the file outbound gateway provide two mutually exclusive configuration attributes for specifying the output directory:
...
@@ -609,12 +609,12 @@ Both, the file outbound channel adapter and the file outbound gateway provide tw
...
@@ -609,12 +609,12 @@ Both, the file outbound channel adapter and the file outbound gateway provide tw
| |Spring Integration 2.2 introduced the `directory-expression` attribute.|
| |Spring Integration 2.2 introduced the `directory-expression` attribute.|
##### [](#using-the-directory-attribute)Using the `directory` Attribute
##### Using the `directory` Attribute
When you use the `directory` attribute, the output directory is set to a fixed value, which is set when the `FileWritingMessageHandler` is initialized.
When you use the `directory` attribute, the output directory is set to a fixed value, which is set when the `FileWritingMessageHandler` is initialized.
If you do not specify this attribute, you must use the `directory-expression` attribute.
If you do not specify this attribute, you must use the `directory-expression` attribute.
##### [](#using-the-directory-expression-attribute)Using the `directory-expression` Attribute
##### Using the `directory-expression` Attribute
If you want to have full SpEL support, you can use the `directory-expression` attribute.
If you want to have full SpEL support, you can use the `directory-expression` attribute.
This attribute accepts a SpEL expression that is evaluated for each message being processed.
This attribute accepts a SpEL expression that is evaluated for each message being processed.
...
@@ -625,7 +625,7 @@ The SpEL expression must resolve to either a `String`, `java.io.File` or `org.sp
...
@@ -625,7 +625,7 @@ The SpEL expression must resolve to either a `String`, `java.io.File` or `org.sp
Furthermore, the resulting `String` or `File` must point to a directory.
Furthermore, the resulting `String` or `File` must point to a directory.
If you do not specify the `directory-expression` attribute, then you must set the `directory` attribute.
If you do not specify the `directory-expression` attribute, then you must set the `directory` attribute.
##### [](#using-the-auto-create-directory-attribute)Using the `auto-create-directory` Attribute
##### Using the `auto-create-directory` Attribute
By default, if the destination directory does not exist, the respective destination directory and any non-existing parent directories are automatically created.
By default, if the destination directory does not exist, the respective destination directory and any non-existing parent directories are automatically created.
To prevent that behavior, you can set the `auto-create-directory` attribute to `false`.
To prevent that behavior, you can set the `auto-create-directory` attribute to `false`.
...
@@ -634,7 +634,7 @@ This attribute applies to both the `directory` and the `directory-expression` at
...
@@ -634,7 +634,7 @@ This attribute applies to both the `directory` and the `directory-expression` at
| |When using the `directory` attribute and `auto-create-directory` is `false`, the following change was made starting with Spring Integration 2.2:<br/><br/>Instead of checking for the existence of the destination directory when the adapter is initialized, this check is now performed for each message being processed.<br/><br/>Furthermore, if `auto-create-directory` is `true` and the directory was deleted between the processing of messages, the directory is re-created for each message being processed.|
| |When using the `directory` attribute and `auto-create-directory` is `false`, the following change was made starting with Spring Integration 2.2:<br/><br/>Instead of checking for the existence of the destination directory when the adapter is initialized, this check is now performed for each message being processed.<br/><br/>Furthermore, if `auto-create-directory` is `true` and the directory was deleted between the processing of messages, the directory is re-created for each message being processed.|
#### [](#file-writing-destination-exists)Dealing with Existing Destination Files
#### Dealing with Existing Destination Files
When you write files and the destination file already exists, the default behavior is to overwrite that target file.
When you write files and the destination file already exists, the default behavior is to overwrite that target file.
You can change this behavior by setting the `mode` attribute on the relevant file outbound components.
You can change this behavior by setting the `mode` attribute on the relevant file outbound components.
...
@@ -690,7 +690,7 @@ If the target file exists, the message payload is silently ignored.
...
@@ -690,7 +690,7 @@ If the target file exists, the message payload is silently ignored.
| |When using a temporary file suffix (the default is `.writing`), the `IGNORE` option applies if either the final file name or the temporary file name exists.|
| |When using a temporary file suffix (the default is `.writing`), the `IGNORE` option applies if either the final file name or the temporary file name exists.|
#### [](#file-flushing)Flushing Files When Using `APPEND_NO_FLUSH`
#### Flushing Files When Using `APPEND_NO_FLUSH`
The `APPEND_NO_FLUSH` mode was added in version 4.3.
The `APPEND_NO_FLUSH` mode was added in version 4.3.
Using it can improve performance because the file is not closed after each message.
Using it can improve performance because the file is not closed after each message.
...
@@ -717,19 +717,19 @@ When using `flushInterval`, the interval starts at the last write.
...
@@ -717,19 +717,19 @@ When using `flushInterval`, the interval starts at the last write.
The file is flushed only if it is idle for the interval.
The file is flushed only if it is idle for the interval.
Starting with version 4.3.7, an additional property (`flushWhenIdle`) can be set to `false`, meaning that the interval starts with the first write to a previously flushed (or new) file.
Starting with version 4.3.7, an additional property (`flushWhenIdle`) can be set to `false`, meaning that the interval starts with the first write to a previously flushed (or new) file.
#### [](#file-timestamps)File Timestamps
#### File Timestamps
By default, the destination file’s `lastModified` timestamp is the time when the file was created (except that an in-place rename retains the current timestamp).
By default, the destination file’s `lastModified` timestamp is the time when the file was created (except that an in-place rename retains the current timestamp).
Starting with version 4.3, you can now configure `preserve-timestamp` (or `setPreserveTimestamp(true)` when using Java configuration).
Starting with version 4.3, you can now configure `preserve-timestamp` (or `setPreserveTimestamp(true)` when using Java configuration).
For `File` payloads, this transfers the timestamp from the inbound file to the outbound (regardless of whether a copy was required).
For `File` payloads, this transfers the timestamp from the inbound file to the outbound (regardless of whether a copy was required).
For other payloads, if the `FileHeaders.SET_MODIFIED` header (`file_setModified`) is present, it is used to set the destination file’s `lastModified` timestamp, as long as the header is a `Number`.
For other payloads, if the `FileHeaders.SET_MODIFIED` header (`file_setModified`) is present, it is used to set the destination file’s `lastModified` timestamp, as long as the header is a `Number`.
#### [](#file-permissions)File Permissions
#### File Permissions
Starting with version 5.0, when writing files to a file system that supports Posix permissions, you can specify those permissions on the outbound channel adapter or gateway.
Starting with version 5.0, when writing files to a file system that supports Posix permissions, you can specify those permissions on the outbound channel adapter or gateway.
The property is an integer and is usually supplied in the familiar octal format — for example, `0640`, meaning that the owner has read/write permissions, the group has read-only permission, and others have no access.
The property is an integer and is usually supplied in the familiar octal format — for example, `0640`, meaning that the owner has read/write permissions, the group has read-only permission, and others have no access.
In cases where you want to continue processing messages based on the written file, you can use the `outbound-gateway` instead.
In cases where you want to continue processing messages based on the written file, you can use the `outbound-gateway` instead.
It plays a role similar to that of the `outbound-channel-adapter`.
It plays a role similar to that of the `outbound-channel-adapter`.
...
@@ -791,7 +791,7 @@ See [FileHeaders.ORIGINAL\_FILE](https://docs.spring.io/spring-integration/api/o
...
@@ -791,7 +791,7 @@ See [FileHeaders.ORIGINAL\_FILE](https://docs.spring.io/spring-integration/api/o
If you have more elaborate requirements or need to support additional payload types as input to be converted to file content, you can extend the `FileWritingMessageHandler`, but a much better option is to rely on a [`Transformer`](#file-transforming).
If you have more elaborate requirements or need to support additional payload types as input to be converted to file content, you can extend the `FileWritingMessageHandler`, but a much better option is to rely on a [`Transformer`](#file-transforming).
#### [](#configuring-with-java-configuration-2)Configuring with Java Configuration
#### Configuring with Java Configuration
The following Spring Boot application shows an example of how to configure the inbound adapter with Java configuration:
The following Spring Boot application shows an example of how to configure the inbound adapter with Java configuration:
...
@@ -828,7 +828,7 @@ public class FileWritingJavaApplication {
...
@@ -828,7 +828,7 @@ public class FileWritingJavaApplication {
}
}
```
```
#### [](#configuring-with-the-java-dsl-2)Configuring with the Java DSL
#### Configuring with the Java DSL
The following Spring Boot application shows an example of how to configure the inbound adapter with the Java DSL:
The following Spring Boot application shows an example of how to configure the inbound adapter with the Java DSL:
...
@@ -858,7 +858,7 @@ public class FileWritingJavaApplication {
...
@@ -858,7 +858,7 @@ public class FileWritingJavaApplication {
}
}
```
```
### [](#file-transforming)File Transformers
### File Transformers
To transform data read from the file system to objects and the other way around, you need to do some work.
To transform data read from the file system to objects and the other way around, you need to do some work.
Unlike `FileReadingMessageSource` and to a lesser extent `FileWritingMessageHandler`, you probably need your own mechanism to get the job done.
Unlike `FileReadingMessageSource` and to a lesser extent `FileWritingMessageHandler`, you probably need your own mechanism to get the job done.
...
@@ -889,7 +889,7 @@ To configure file-specific transformers, you can use the appropriate elements fr
...
@@ -889,7 +889,7 @@ To configure file-specific transformers, you can use the appropriate elements fr
The `delete-files` option signals to the transformer that it should delete the inbound file after the transformation is complete.
The `delete-files` option signals to the transformer that it should delete the inbound file after the transformation is complete.
This is in no way a replacement for using an `AcceptOnceFileListFilter` when the `FileReadingMessageSource` is being used in a multi-threaded environment (such as when you use Spring Integration in general).
This is in no way a replacement for using an `AcceptOnceFileListFilter` when the `FileReadingMessageSource` is being used in a multi-threaded environment (such as when you use Spring Integration in general).
### [](#file-splitter)File Splitter
### File Splitter
The `FileSplitter` was added in version 4.1.2, and its namespace support was added in version 4.2.
The `FileSplitter` was added in version 4.1.2, and its namespace support was added in version 4.2.
The `FileSplitter` splits text files into individual lines, based on `BufferedReader.readLine()`.
The `FileSplitter` splits text files into individual lines, based on `BufferedReader.readLine()`.
...
@@ -1029,7 +1029,7 @@ By default (if no header name is set), the first line is considered to be data a
...
@@ -1029,7 +1029,7 @@ By default (if no header name is set), the first line is considered to be data a
If you need more complex logic about header extraction from the file content (not first line, not the whole content of the line, not one particular header, and so on), consider using [header enricher](./content-enrichment.html#header-enricher) ahead of the `FileSplitter`.
If you need more complex logic about header extraction from the file content (not first line, not the whole content of the line, not one particular header, and so on), consider using [header enricher](./content-enrichment.html#header-enricher) ahead of the `FileSplitter`.
Note that the lines that have been moved to the headers might be filtered downstream from the normal content process.
Note that the lines that have been moved to the headers might be filtered downstream from the normal content process.
#### [](#idempotent-file-splitter)Idempotent Downstream Processing a Split File
#### Idempotent Downstream Processing a Split File
When `apply-sequence` is true, the splitter adds the line number in the `SEQUENCE_NUMBER` header (when `markers` is true, the markers are counted as lines).
When `apply-sequence` is true, the splitter adds the line number in the `SEQUENCE_NUMBER` header (when `markers` is true, the markers are counted as lines).
The line number can be used with an [Idempotent Receiver](./handler-advice.html#idempotent-receiver) to avoid reprocessing lines after a restart.
The line number can be used with an [Idempotent Receiver](./handler-advice.html#idempotent-receiver) to avoid reprocessing lines after a restart.
...
@@ -1069,7 +1069,7 @@ public IntegrationFlow flow() {
...
@@ -1069,7 +1069,7 @@ public IntegrationFlow flow() {
}
}
```
```
### [](#file-aggregator)File Aggregator
### File Aggregator
Starting with version 5.5, a `FileAggregator` is introduced to cover other side of `FileSplitter` use-case when START/END markers are enabled.
Starting with version 5.5, a `FileAggregator` is introduced to cover other side of `FileSplitter` use-case when START/END markers are enabled.
For convenience the `FileAggregator` implements all three sequence details strategies:
For convenience the `FileAggregator` implements all three sequence details strategies:
...
@@ -1148,7 +1148,7 @@ XML
...
@@ -1148,7 +1148,7 @@ XML
If default behavior of the `FileAggregator` does not satisfy the target logic, it is recommended to configure an aggregator endpoint with individual strategies.
If default behavior of the `FileAggregator` does not satisfy the target logic, it is recommended to configure an aggregator endpoint with individual strategies.
See `FileAggregator` JavaDocs for more information.
See `FileAggregator` JavaDocs for more information.
### [](#remote-persistent-flf)Remote Persistent File List Filters
### Remote Persistent File List Filters
Inbound and streaming inbound remote file channel adapters (`FTP`, `SFTP`, and other technologies) are configured with corresponding implementations of `AbstractPersistentFileListFilter` by default, configured with an in-memory `MetadataStore`.
Inbound and streaming inbound remote file channel adapters (`FTP`, `SFTP`, and other technologies) are configured with corresponding implementations of `AbstractPersistentFileListFilter` by default, configured with an in-memory `MetadataStore`.
To run in a cluster, these can be replaced with filters using a shared `MetadataStore` (see [Metadata Store](./meta-data-store.html#metadata-store) for more information).
To run in a cluster, these can be replaced with filters using a shared `MetadataStore` (see [Metadata Store](./meta-data-store.html#metadata-store) for more information).
The continuous query inbound channel adapter produces messages on a channel when triggered by a GemFire continuous query or `CqEvent` event.
The continuous query inbound channel adapter produces messages on a channel when triggered by a GemFire continuous query or `CqEvent` event.
In release `1.1`, Spring Data introduced continuous query support, including `ContinuousQueryListenerContainer`, which provides a nice abstraction over the GemFire native API.
In release `1.1`, Spring Data introduced continuous query support, including `ContinuousQueryListenerContainer`, which provides a nice abstraction over the GemFire native API.
...
@@ -132,7 +132,7 @@ This adapter also supports an `error-channel`.
...
@@ -132,7 +132,7 @@ This adapter also supports an `error-channel`.
| |This adapter conforms to Spring Integration conventions.|
| |This adapter conforms to Spring Integration conventions.|
The outbound channel adapter writes cache entries that are mapped from the message payload.
The outbound channel adapter writes cache entries that are mapped from the message payload.
In its simplest form, it expects a payload of type `java.util.Map` and puts the map entries into its configured region.
In its simplest form, it expects a payload of type `java.util.Map` and puts the map entries into its configured region.
...
@@ -161,7 +161,7 @@ Note that this can contain arbitrary cache entries (not only those derived from
...
@@ -161,7 +161,7 @@ Note that this can contain arbitrary cache entries (not only those derived from
In the preceding example, if the message sent to `cacheChannel` has a `String` payload with a value `Hello`, two entries (`[HELLO:hello, thing1:thing2]`) are written (either created or updated) in the cache region.
In the preceding example, if the message sent to `cacheChannel` has a `String` payload with a value `Hello`, two entries (`[HELLO:hello, thing1:thing2]`) are written (either created or updated) in the cache region.
This adapter also supports the `order` attribute, which may be useful if it is bound to a `PublishSubscribeChannel`.
This adapter also supports the `order` attribute, which may be useful if it is bound to a `PublishSubscribeChannel`.
### [](#gemfire-message-store)Gemfire Message Store
### Gemfire Message Store
As described in EIP, a [message store](https://www.enterpriseintegrationpatterns.com/MessageStore.html) lets you persist messages.
As described in EIP, a [message store](https://www.enterpriseintegrationpatterns.com/MessageStore.html) lets you persist messages.
This can be useful when dealing with components that have a capability to buffer messages (`QueueChannel`, `Aggregator`, `Resequencer`, and others) if reliability is a concern.
This can be useful when dealing with components that have a capability to buffer messages (`QueueChannel`, `Aggregator`, `Resequencer`, and others) if reliability is a concern.
...
@@ -213,7 +213,7 @@ The region’s `id` corresponds to a region with the same name in the cache serv
...
@@ -213,7 +213,7 @@ The region’s `id` corresponds to a region with the same name in the cache serv
Starting with version 4.3.12, the `GemfireMessageStore` supports the key `prefix` option to allow distinguishing between instances of the store on the same GemFire region.
Starting with version 4.3.12, the `GemfireMessageStore` supports the key `prefix` option to allow distinguishing between instances of the store on the same GemFire region.
Starting with version 4.0, the `GemfireLockRegistry` is available.
Starting with version 4.0, the `GemfireLockRegistry` is available.
Certain components (for example, the aggregator and the resequencer) use a lock obtained from a `LockRegistry` instance to ensure that only one thread is manipulating a group at any given time.
Certain components (for example, the aggregator and the resequencer) use a lock obtained from a `LockRegistry` instance to ensure that only one thread is manipulating a group at any given time.
...
@@ -224,7 +224,7 @@ When you use a shared `MessageGroupStore` with the `GemfireLockRegistry`, it can
...
@@ -224,7 +224,7 @@ When you use a shared `MessageGroupStore` with the `GemfireLockRegistry`, it can
| |One of the `GemfireLockRegistry` constructors requires a `Region` as an argument.<br/>It is used to obtain a `Lock` from the `getDistributedLock()` method.<br/>This operation requires `GLOBAL` scope for the `Region`.<br/>Another constructor requires a `Cache`, and the `Region` is created with `GLOBAL` scope and with the name, `LockRegistry`.|
| |One of the `GemfireLockRegistry` constructors requires a `Region` as an argument.<br/>It is used to obtain a `Lock` from the `getDistributedLock()` method.<br/>This operation requires `GLOBAL` scope for the `Region`.<br/>Another constructor requires a `Cache`, and the `Region` is created with `GLOBAL` scope and with the name, `LockRegistry`.|
The `javax.servlet:javax.servlet-api` dependency must be provided on the target Servlet container.
The `javax.servlet:javax.servlet-api` dependency must be provided on the target Servlet container.
### [](#http-inbound)Http Inbound Components
### Http Inbound Components
To receive messages over HTTP, you need to use an HTTP inbound channel adapter or an HTTP inbound gateway.
To receive messages over HTTP, you need to use an HTTP inbound channel adapter or an HTTP inbound gateway.
To support the HTTP inbound adapters, they need to be deployed within a servlet container such as [Apache Tomcat](https://tomcat.apache.org/) or [Jetty](https://www.eclipse.org/jetty/).
To support the HTTP inbound adapters, they need to be deployed within a servlet container such as [Apache Tomcat](https://tomcat.apache.org/) or [Jetty](https://www.eclipse.org/jetty/).
...
@@ -107,17 +107,17 @@ The preceding example also shows how to customize the HTTP methods accepted by t
...
@@ -107,17 +107,17 @@ The preceding example also shows how to customize the HTTP methods accepted by t
The reply message is available in the model map.
The reply message is available in the model map.
By default, the key for that map entry is 'reply', but you can override this default by setting the 'replyKey' property on the endpoint’s configuration.
By default, the key for that map entry is 'reply', but you can override this default by setting the 'replyKey' property on the endpoint’s configuration.
#### [](#http-validation)Payload Validation
#### Payload Validation
Starting with version 5.2, the HTTP inbound endpoints can be supplied with a `Validator` to check a payload before sending into the channel.
Starting with version 5.2, the HTTP inbound endpoints can be supplied with a `Validator` to check a payload before sending into the channel.
This payload is already a result of conversion and extraction after `payloadExpression` to narrow a validation scope in regards to the valuable data.
This payload is already a result of conversion and extraction after `payloadExpression` to narrow a validation scope in regards to the valuable data.
The validation failure handling is fully the same what we have in Spring MVC [Error Handling](https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-exceptionhandlers).
The validation failure handling is fully the same what we have in Spring MVC [Error Handling](https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-exceptionhandlers).
### [](#http-outbound)HTTP Outbound Components
### HTTP Outbound Components
This section describes Spring Integration’s HTTP outbound components.
This section describes Spring Integration’s HTTP outbound components.
Basic cookie support is provided by the `transfer-cookies` attribute on the outbound gateway.
Basic cookie support is provided by the `transfer-cookies` attribute on the outbound gateway.
When set to `true` (the default is `false`), a `Set-Cookie` header received from the server in a response is converted to `Cookie` in the reply message.
When set to `true` (the default is `false`), a `Set-Cookie` header received from the server in a response is converted to `Cookie` in the reply message.
...
@@ -169,7 +169,7 @@ If `transfer-cookies` is `false`, any `Set-Cookie` header received remains as `S
...
@@ -169,7 +169,7 @@ If `transfer-cookies` is `false`, any `Set-Cookie` header received remains as `S
Starting with version 5.5, the `HttpRequestExecutingMessageHandler` exposes an `extractResponseBody` flag (which is `true` by default) to return just the response body, or to return the whole `ResponseEntity` as the reply message payload, independently of the provided `expectedResponseType`.
Starting with version 5.5, the `HttpRequestExecutingMessageHandler` exposes an `extractResponseBody` flag (which is `true` by default) to return just the response body, or to return the whole `ResponseEntity` as the reply message payload, independently of the provided `expectedResponseType`.
If a body is not present in the `ResponseEntity`, this flag is ignored and the whole `ResponseEntity` is returned.
If a body is not present in the `ResponseEntity`, this flag is ignored and the whole `ResponseEntity` is returned.
### [](#http-namespace)HTTP Namespace Support
### HTTP Namespace Support
Spring Integration provides an `http` namespace and the corresponding schema definition.
Spring Integration provides an `http` namespace and the corresponding schema definition.
To include it in your configuration, provide the following namespace declaration in your application context configuration file:
To include it in your configuration, provide the following namespace declaration in your application context configuration file:
...
@@ -191,7 +191,7 @@ To include it in your configuration, provide the following namespace declaration
...
@@ -191,7 +191,7 @@ To include it in your configuration, provide the following namespace declaration
</beans>
</beans>
```
```
#### [](#inbound)Inbound
#### Inbound
The XML namespace provides two components for handling HTTP inbound requests: `inbound-channel-adapter` and `inbound-gateway`.
The XML namespace provides two components for handling HTTP inbound requests: `inbound-channel-adapter` and `inbound-gateway`.
In order to process requests without returning a dedicated response, use the `inbound-channel-adapter`.
In order to process requests without returning a dedicated response, use the `inbound-channel-adapter`.
...
@@ -211,7 +211,7 @@ The following example shows how to configure one:
...
@@ -211,7 +211,7 @@ The following example shows how to configure one:
reply-channel="responses"/>
reply-channel="responses"/>
```
```
#### [](#http-request-mapping)Request Mapping Support
#### Request Mapping Support
| |Spring Integration 3.0 improved the REST support by introducing the [`IntegrationRequestMappingHandlerMapping`](https://docs.spring.io/spring-integration/api/org/springframework/integration/http/inbound/IntegrationRequestMappingHandlerMapping.html).<br/>The implementation relies on the enhanced REST support provided by Spring Framework 3.1 or higher.|
| |Spring Integration 3.0 improved the REST support by introducing the [`IntegrationRequestMappingHandlerMapping`](https://docs.spring.io/spring-integration/api/org/springframework/integration/http/inbound/IntegrationRequestMappingHandlerMapping.html).<br/>The implementation relies on the enhanced REST support provided by Spring Framework 3.1 or higher.|
@@ -285,7 +285,7 @@ For more information regarding handler mappings, see [the Spring Framework Web S
...
@@ -285,7 +285,7 @@ For more information regarding handler mappings, see [the Spring Framework Web S
| |The `IntegrationRequestMappingHandlerMapping` extends the Spring MVC `RequestMappingHandlerMapping` class, inheriting most of its logic, especially `handleNoMatch(Set, String, HttpServletRequest)`, which throws a specific `4xx` error for the HTTP response, when mapping doesn’t match for some reason, preventing calls to any remaining mapping handlers in the application context.<br/>For this reason, configuring the same path for both Spring Integration and Spring MVC request mappings (e.g. `POST` in one and `GET` in the other) is not supported; the MVC mapping will not be found..|
| |The `IntegrationRequestMappingHandlerMapping` extends the Spring MVC `RequestMappingHandlerMapping` class, inheriting most of its logic, especially `handleNoMatch(Set, String, HttpServletRequest)`, which throws a specific `4xx` error for the HTTP response, when mapping doesn’t match for some reason, preventing calls to any remaining mapping handlers in the application context.<br/>For this reason, configuring the same path for both Spring Integration and Spring MVC request mappings (e.g. `POST` in one and `GET` in the other) is not supported; the MVC mapping will not be found..|
#### [](#http-cors)Cross-origin Resource Sharing (CORS) Support
#### Support
Starting with version 4.2, you can configure the `<http:inbound-channel-adapter>` and `<http:inbound-gateway>` with a `<cross-origin>` element.
Starting with version 4.2, you can configure the `<http:inbound-channel-adapter>` and `<http:inbound-gateway>` with a `<cross-origin>` element.
It represents the same options as Spring MVC’s `@CrossOrigin` for `@Controller` annotations and allows the configuration of cross-origin resource sharing (CORS) for Spring Integration HTTP endpoints:
It represents the same options as Spring MVC’s `@CrossOrigin` for `@Controller` annotations and allows the configuration of cross-origin resource sharing (CORS) for Spring Integration HTTP endpoints:
...
@@ -319,7 +319,7 @@ It represents the same options as Spring MVC’s `@CrossOrigin` for `@Controller
...
@@ -319,7 +319,7 @@ It represents the same options as Spring MVC’s `@CrossOrigin` for `@Controller
The CORS Java Configuration is represented by the `org.springframework.integration.http.inbound.CrossOrigin` class, instances of which can be injected into the `HttpRequestHandlingEndpointSupport` beans.
The CORS Java Configuration is represented by the `org.springframework.integration.http.inbound.CrossOrigin` class, instances of which can be injected into the `HttpRequestHandlingEndpointSupport` beans.
#### [](#http-response-statuscode)Response Status Code
#### Response Status Code
Starting with version 4.1, you can configure the `<http:inbound-channel-adapter>` with a `status-code-expression` to override the default `200 OK` status.
Starting with version 4.1, you can configure the `<http:inbound-channel-adapter>` with a `status-code-expression` to override the default `200 OK` status.
The expression must return an object that can be converted to an `org.springframework.http.HttpStatus` enum value.
The expression must return an object that can be converted to an `org.springframework.http.HttpStatus` enum value.
...
@@ -417,7 +417,7 @@ The following example configures a transformer that uses an `expression` attribu
...
@@ -417,7 +417,7 @@ The following example configures a transformer that uses an `expression` attribu
requestAttributes.request.queryString"/>
requestAttributes.request.queryString"/>
```
```
#### [](#outbound)Outbound
#### Outbound
To configure the outbound gateway, you can use the namespace support.
To configure the outbound gateway, you can use the namespace support.
The following code snippet shows the available configuration options for an outbound HTTP gateway:
The following code snippet shows the available configuration options for an outbound HTTP gateway:
...
@@ -487,7 +487,7 @@ The configuration looks very similar to the gateway, as the following example sh
...
@@ -487,7 +487,7 @@ The configuration looks very similar to the gateway, as the following example sh
| |To specify the URL, you can use either the 'url' attribute or the 'url-expression' attribute.<br/>The 'url' attribute takes a simple string (with placeholders for URI variables, as described below).<br/>The 'url-expression' is a SpEL expression, with the `Message` as the root object, which enables dynamic urls.<br/>The URL that results from the expression evaluation can still have placeholders for URI variables.<br/><br/>In previous releases, some users used the place holders to replace the entire URL with a URI variable.<br/>Changes in Spring 3.1 can cause some issues with escaped characters, such as '?'.<br/>For this reason, we recommend that, if you wish to generate the URL entirely at runtime, you use the 'url-expression' attribute.|
| |To specify the URL, you can use either the 'url' attribute or the 'url-expression' attribute.<br/>The 'url' attribute takes a simple string (with placeholders for URI variables, as described below).<br/>The 'url-expression' is a SpEL expression, with the `Message` as the root object, which enables dynamic urls.<br/>The URL that results from the expression evaluation can still have placeholders for URI variables.<br/><br/>In previous releases, some users used the place holders to replace the entire URL with a URI variable.<br/>Changes in Spring 3.1 can cause some issues with escaped characters, such as '?'.<br/>For this reason, we recommend that, if you wish to generate the URL entirely at runtime, you use the 'url-expression' attribute.|
#### [](#http-uri-encoding)Controlling URI Encoding
#### Controlling URI Encoding
By default, the URL string is encoded (see [`UriComponentsBuilder`](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/util/UriComponentsBuilder.html)) to the URI object before sending the request.
By default, the URL string is encoded (see [`UriComponentsBuilder`](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/util/UriComponentsBuilder.html)) to the URI object before sending the request.
In some scenarios with a non-standard URI (such as the RabbitMQ REST API), it is undesirable to perform the encoding.
In some scenarios with a non-standard URI (such as the RabbitMQ REST API), it is undesirable to perform the encoding.
...
@@ -611,7 +611,7 @@ With Java DSL this option can be controlled by the `BaseHttpMessageHandlerSpec.e
...
@@ -611,7 +611,7 @@ With Java DSL this option can be controlled by the `BaseHttpMessageHandlerSpec.e
The same configuration applies for similar outbound components in the [WebFlux module](./webflux.html#webflux) and [Web Services module](./ws.html#ws).
The same configuration applies for similar outbound components in the [WebFlux module](./webflux.html#webflux) and [Web Services module](./ws.html#ws).
For much sophisticated scenarios it is recommended to configure an `UriTemplateHandler` on the externally provided `RestTemplate`; or in case of WebFlux - `WebClient` with it `UriBuilderFactory`.
For much sophisticated scenarios it is recommended to configure an `UriTemplateHandler` on the externally provided `RestTemplate`; or in case of WebFlux - `WebClient` with it `UriBuilderFactory`.
### [](#http-java-config)Configuring HTTP Endpoints with Java
### Configuring HTTP Endpoints with Java
The following example shows how to configure an inbound gateway with Java:
The following example shows how to configure an inbound gateway with Java:
...
@@ -683,7 +683,7 @@ public IntegrationFlow outbound() {
...
@@ -683,7 +683,7 @@ public IntegrationFlow outbound() {
}
}
```
```
### [](#http-timeout)Timeout Handling
### Timeout Handling
In the context of HTTP components, there are two timing areas that have to be considered:
In the context of HTTP components, there are two timing areas that have to be considered:
...
@@ -753,7 +753,7 @@ The value of the *sendTimeout* property defaults to "-1" and will be applied to
...
@@ -753,7 +753,7 @@ The value of the *sendTimeout* property defaults to "-1" and will be applied to
This means, that depending on the implementation, the Message Channel’s *send* method may block indefinitely.
This means, that depending on the implementation, the Message Channel’s *send* method may block indefinitely.
Furthermore, the *sendTimeout* property is only used, when the actual MessageChannel implementation has a blocking send (such as 'full' bounded QueueChannel).
Furthermore, the *sendTimeout* property is only used, when the actual MessageChannel implementation has a blocking send (such as 'full' bounded QueueChannel).
For the HTTP inbound gateway, the XML Schema defines the `request-timeout` attribute, which is used to set the `requestTimeout` property on the `HttpRequestHandlingMessagingGateway` class (on the extended `MessagingGatewaySupport` class).
For the HTTP inbound gateway, the XML Schema defines the `request-timeout` attribute, which is used to set the `requestTimeout` property on the `HttpRequestHandlingMessagingGateway` class (on the extended `MessagingGatewaySupport` class).
You can also use the `reply-timeout` attribute to map to the `replyTimeout` property on the same class.
You can also use the `reply-timeout` attribute to map to the `replyTimeout` property on the same class.
...
@@ -765,13 +765,13 @@ The `replyTimeout` property, on the other hand, is used to set the `receiveTimeo
...
@@ -765,13 +765,13 @@ The `replyTimeout` property, on the other hand, is used to set the `receiveTimeo
| |To simulate connection timeouts, you can connect to a non-routable IP address, such as 10.255.255.10.|
| |To simulate connection timeouts, you can connect to a non-routable IP address, such as 10.255.255.10.|
You can set three system properties to configure the proxy settings that are used by the HTTP protocol handler:
You can set three system properties to configure the proxy settings that are used by the HTTP protocol handler:
...
@@ -792,7 +792,7 @@ For HTTPS, the following properties are available:
...
@@ -792,7 +792,7 @@ For HTTPS, the following properties are available:
For more information, see [https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html](https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html)
For more information, see [https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html](https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html)
If you need more explicit control over the proxy configuration, you can use Spring’s `SimpleClientHttpRequestFactory` and configure its 'proxy' property, as the following example shows:
If you need more explicit control over the proxy configuration, you can use Spring’s `SimpleClientHttpRequestFactory` and configure its 'proxy' property, as the following example shows:
...
@@ -815,7 +815,7 @@ If you need more explicit control over the proxy configuration, you can use Spri
...
@@ -815,7 +815,7 @@ If you need more explicit control over the proxy configuration, you can use Spri
</bean>
</bean>
```
```
### [](#http-header-mapping)HTTP Header Mappings
### HTTP Header Mappings
Spring Integration provides support for HTTP header mapping for both HTTP Request and HTTP Responses.
Spring Integration provides support for HTTP header mapping for both HTTP Request and HTTP Responses.
...
@@ -864,16 +864,16 @@ The following example configures a header mapper for an HTTP gateway:
...
@@ -864,16 +864,16 @@ The following example configures a header mapper for an HTTP gateway:
If you need to do something other than what the `DefaultHttpHeaderMapper` supports, you can implement the `HeaderMapper` strategy interface directly and provide a reference to your implementation.
If you need to do something other than what the `DefaultHttpHeaderMapper` supports, you can implement the `HeaderMapper` strategy interface directly and provide a reference to your implementation.
Starting with version 4.3, the HTTP module provides an `@EnableIntegrationGraphController` configuration class annotation and an `<int-http:graph-controller/>` XML element to expose the `IntegrationGraphServer` as a REST service.
Starting with version 4.3, the HTTP module provides an `@EnableIntegrationGraphController` configuration class annotation and an `<int-http:graph-controller/>` XML element to expose the `IntegrationGraphServer` as a REST service.
See [Integration Graph](./graph.html#integration-graph) for more information.
See [Integration Graph](./graph.html#integration-graph) for more information.
### [](#http-samples)HTTP Samples
### HTTP Samples
This section wraps up our coverage of Spring Integration’s HTTP support with a few examples.
This section wraps up our coverage of Spring Integration’s HTTP support with a few examples.
This example shows how simple it is to send a multipart HTTP request with Spring’s `RestTemplate` and receive it with a Spring Integration HTTP inbound adapter.
This example shows how simple it is to send a multipart HTTP request with Spring’s `RestTemplate` and receive it with a Spring Integration HTTP inbound adapter.
We create a `MultiValueMap` and populate it with multipart data.
We create a `MultiValueMap` and populate it with multipart data.
The notification-listening channel adapter requires a JMX `ObjectName` for the MBean that publishes notifications to which this listener should be registered.
The notification-listening channel adapter requires a JMX `ObjectName` for the MBean that publishes notifications to which this listener should be registered.
A very simple configuration might resemble the following:
A very simple configuration might resemble the following:
...
@@ -57,7 +57,7 @@ It does not require any poller configuration.
...
@@ -57,7 +57,7 @@ It does not require any poller configuration.
| |For this component only, the `object-name` attribute can contain an object name pattern (for example,<br/>"org.something:type=MyType,name=\*").<br/>In that case, the adapter receives notifications from all MBeans with object names that match the pattern.<br/>In addition, the `object-name` attribute can contain a SpEL reference to a `<util:list>` of object name patterns, as the following example shows:<br/><br/>```<br/><jmx:notification-listening-channel-adapter id="manyNotificationsAdapter"<br/> channel="manyNotificationsChannel"<br/> object-name="#{patterns}"/><br/><br/><util:list id="patterns"><br/> <value>org.foo:type=Foo,name=*</value><br/> <value>org.foo:type=Bar,name=*</value><br/></util:list><br/>```<br/><br/>The names of the located MBean(s) are logged when DEBUG level logging is enabled.|
| |For this component only, the `object-name` attribute can contain an object name pattern (for example,<br/>"org.something:type=MyType,name=\*").<br/>In that case, the adapter receives notifications from all MBeans with object names that match the pattern.<br/>In addition, the `object-name` attribute can contain a SpEL reference to a `<util:list>` of object name patterns, as the following example shows:<br/><br/>```<br/><jmx:notification-listening-channel-adapter id="manyNotificationsAdapter"<br/> channel="manyNotificationsChannel"<br/> object-name="#{patterns}"/><br/><br/><util:list id="patterns"><br/> <value>org.foo:type=Foo,name=*</value><br/> <value>org.foo:type=Bar,name=*</value><br/></util:list><br/>```<br/><br/>The names of the located MBean(s) are logged when DEBUG level logging is enabled.|
The attribute-polling channel adapter is useful when you need to periodically check on some value that is available through an MBean as a managed attribute.
The attribute-polling channel adapter is useful when you need to periodically check on some value that is available through an MBean as a managed attribute.
You can configured the poller in the same way as any other polling adapter in Spring Integration (or you can rely on the default poller).
You can configured the poller in the same way as any other polling adapter in Spring Integration (or you can rely on the default poller).
...
@@ -109,7 +109,7 @@ The following example shows how to configure an attribute-polling channel adapte
...
@@ -109,7 +109,7 @@ The following example shows how to configure an attribute-polling channel adapte
Similarly to the operation-invoking channel adapter, Spring Integration also provides an operation-invoking outbound gateway, which you can use when dealing with non-void operations when a return value is required.
Similarly to the operation-invoking channel adapter, Spring Integration also provides an operation-invoking outbound gateway, which you can use when dealing with non-void operations when a return value is required.
The return value is sent as the message payload to the `reply-channel` specified by the gateway.
The return value is sent as the message payload to the `reply-channel` specified by the gateway.
...
@@ -175,7 +175,7 @@ If you do not provide the `reply-channel` attribute, the reply message is sent t
...
@@ -175,7 +175,7 @@ If you do not provide the `reply-channel` attribute, the reply message is sent t
That header is typically auto-created by the entry point into a message flow, such as any gateway component.
That header is typically auto-created by the entry point into a message flow, such as any gateway component.
However, if the message flow was started by manually creating a Spring Integration message and sending it directly to a channel, you must specify the message header explicitly or use the `reply-channel` attribute.
However, if the message flow was started by manually creating a Spring Integration message and sending it directly to a channel, you must specify the message header explicitly or use the `reply-channel` attribute.
#### [](#jmx-mbean-exporter)MBean Exporter
#### MBean Exporter
Spring Integration components may themselves be exposed as MBeans when the `IntegrationMBeanExporter` is configured.
Spring Integration components may themselves be exposed as MBeans when the `IntegrationMBeanExporter` is configured.
To create an instance of the `IntegrationMBeanExporter`, define a bean and provide a reference to an `MBeanServer` and a domain name (if desired).
To create an instance of the `IntegrationMBeanExporter`, define a bean and provide a reference to an `MBeanServer` and a domain name (if desired).
...
@@ -213,7 +213,7 @@ public class ContextConfiguration {
...
@@ -213,7 +213,7 @@ public class ContextConfiguration {
If you need to provide more options or have several `IntegrationMBeanExporter` beans (such as
If you need to provide more options or have several `IntegrationMBeanExporter` beans (such as
for different MBean Servers or to avoid conflicts with the standard Spring `MBeanExporter` — such as through`@EnableMBeanExport`), you can configure an `IntegrationMBeanExporter` as a generic bean.
for different MBean Servers or to avoid conflicts with the standard Spring `MBeanExporter` — such as through`@EnableMBeanExport`), you can configure an `IntegrationMBeanExporter` as a generic bean.
##### [](#jmx-mbean-features)MBean Object Names
##### MBean Object Names
All the `MessageChannel`, `MessageHandler`, and `MessageSource` instances in the application are wrapped by the MBean exporter to provide management and monitoring features.
All the `MessageChannel`, `MessageHandler`, and `MessageSource` instances in the application are wrapped by the MBean exporter to provide management and monitoring features.
The generated JMX object names for each component type are listed in the following table:
The generated JMX object names for each component type are listed in the following table:
...
@@ -261,7 +261,7 @@ Doing so also groups the beans under one tree entry under the domain in such too
...
@@ -261,7 +261,7 @@ Doing so also groups the beans under one tree entry under the domain in such too
Starting with version 5.1; any bean names (represented by the `name` key in the object name) will be quoted if they contain any characters that are not allowed in a Java identifier (or period `.`).
Starting with version 5.1; any bean names (represented by the `name` key in the object name) will be quoted if they contain any characters that are not allowed in a Java identifier (or period `.`).
##### [](#jmx-42-improvements)JMX Improvements
##### JMX Improvements
Version 4.2 introduced some important improvements, representing a fairly major overhaul to the JMX support in the framework.
Version 4.2 introduced some important improvements, representing a fairly major overhaul to the JMX support in the framework.
These resulted in a significant performance improvement of the JMX statistics collection and much more control thereof.
These resulted in a significant performance improvement of the JMX statistics collection and much more control thereof.
...
@@ -295,7 +295,7 @@ The `IntegrationMBeanExporter` no longer implements `SmartLifecycle`.
...
@@ -295,7 +295,7 @@ The `IntegrationMBeanExporter` no longer implements `SmartLifecycle`.
This means that `start()` and `stop()` operations are no longer available to register and unregister MBeans.
This means that `start()` and `stop()` operations are no longer available to register and unregister MBeans.
The MBeans are now registered during context initialization and unregistered when the context is destroyed.
The MBeans are now registered during context initialization and unregistered when the context is destroyed.
The Kotlin DSL is a wrapper and extension to [Java DSL](./dsl.html#java-dsl) and aimed to make Spring Integration development on Kotlin as smooth and straightforward as possible with interoperability with the existing Java API and Kotlin language-specific structures.
The Kotlin DSL is a wrapper and extension to [Java DSL](./dsl.html#java-dsl) and aimed to make Spring Integration development on Kotlin as smooth and straightforward as possible with interoperability with the existing Java API and Kotlin language-specific structures.
The definitive source of information about Spring Integration is the [Spring Integration Home](https://projects.spring.io/spring-integration/) at [https://spring.io](https://spring.io).
The definitive source of information about Spring Integration is the [Spring Integration Home](https://projects.spring.io/spring-integration/) at [https://spring.io](https://spring.io).
That site serves as a hub of information and is the best place to find up-to-date announcements about the project as well as links to articles, blogs, and new sample applications.
That site serves as a hub of information and is the best place to find up-to-date announcements about the project as well as links to articles, blogs, and new sample applications.