Get ahead
VMware offers training and certification to turbo-charge your progress.
Learn moreDear Spring community,
We are pleased to announce that the Spring Integration 4.1 Release Candidate is available. Please use the Milestone Repository with Maven or Gradle, or download a distribution archive, to give it a spin.
The release includes many new features and improvements, as well as a number of bug fixes. The GA release is planned in early November.
First of all, thank you all who provided feedback for the 4.1 Milestone 1 and submitted reports (bugs or new features). A special thanks to those who provided contribution via Pull Requests. Here is a summary of major changes since the milestone:
Web Sockets support
This feature was introduced in 4.1 Milestone 1, but several issues have been resolved, and we have now provided a couple of samples to better understand how Web Sockets can be used in Spring Integration applications: Basic and STOMP Chat.
JDK8 Optional<?> consistent handling
If you are using Java 8, you'll be able to use the Optional<?>
container for service method arguments. For example:
public void optionals(@Payload("@myConvert.conv(payload)") Optional<Bar> payload,
@Header(value="foo") Optional<String> header)
In this case, if @myConvert.conv(payload)
returns null
, the payload
variable will contain an Optional.empty()
.
The same thing for header
variables - if there is no foo
header in the request Message<?>
. This can be used
as an alternative to the required
attribute on a @Header
annotation.
Routing Slip pattern
The Routing Slip pattern is now supported. Rather
than a simple static list of channel names
, we have introduced the RoutingSlipRouteStrategy
, which provides
dynamic runtime routing based on the request Message<?>
and reply object
. SpEL is supported too:
<header-enricher input-channel="input" output-channel="process">
<routing-slip value="channel1; request.headers[myRoutingSlipChannel];
routingSlipRoutingStrategy;"/>
</header-enricher>
This pattern is useful in complex, dynamic, cases when it can become difficult to configure multiple routers to determine
message flow. With this enhancement, when a message
arrives at an endpoint that has no output-channel
, the routing slip is consulted to determine the next channel to which
the message will be sent. When the routing slip is exhausted, normal replyChannel
processing resumes.
Idempotent Receiver pattern
With this release we have implemented the
Idempotent Receiver as a first class feature.
Previously, users would have to implement this pattern, by using a custom MessageSelector
in a <filter/>
, for example.
The framework now supports this capability as an Advice
component that can be applied to any consuming endpoint:
<idempotent-receiver endpoint="endpoint1, foo*"
metadata-store="store"
discard-channel="duplicates"
key-expression="payload.invoiceNumber"/>
This creates an AOP IdempotentReceiverInterceptor
which is applied to the MessageHandler#handleMessage
within endpoints
where the id
matches one of the provided endpoint
patterns.
If the discard-channel
is omitted, a duplicate message is still sent to the message handler, but it will contain a
duplicateMessage
header, allowing user code to take further action.
For JavaConfig, the @IdempotentReceiver
annotation is provided, however the IdempotentReceiverInterceptor
@Bean
must
be configured too:
@Bean
public IdempotentReceiverInterceptor idempotentReceiverInterceptor() {
return new IdempotentReceiverInterceptor(new MetadataStoreSelector(m ->
m.getPayload().toString()));
}
@Bean
@ServiceActivator(inputChannel = "input", outputChannel = "output")
@IdempotentReceiver("idempotentReceiverInterceptor")
public MessageHandler myService() {
....
}
For more information, please, read IdempotentReceiverInterceptor
JavaDocs.
Scatter-Gather pattern
The Scatter-Gather Enterprise Integration Pattern is now provided:
<!--Auction scenario-->
<scatter-gather input-channel="inputAuction" output-channel="output"
scatter-channel="auctionChannel">
<gatherer release-strategy-expression="^[payload gt 5] != null or size() == 3"/>
</scatter-gather>
<!--Distribution scenario-->
<scatter-gather input-channel="inputDistribution" output-channel="output"
gather-channel="gatherChannel">
<scatterer apply-sequence="true">
<recipient channel="distribution1Channel"/>
<recipient channel="distribution2Channel"/>
<recipient channel="distribution3Channel"/>
</scatterer>
<gatherer release-strategy-expression="^[payload gt 5] != null or size() == 3"/>
</scatter-gather>
It is a compound endpoint, which combines publish-subscribe
logic and an aggregation
function.
Of course, it could previously be implemented as an integration flow using the existing publish-subscribe-channel
,
or recipient-list-router
, together with an aggregator
component, but this new feature provides for a cleaner implementation of scenarios such as best quote
.
Redis Queue Gateways
A pair of request-reply
(inbound and outbound) gateway components based on Redis List
s have been added to the Redis
module:
<int-redis:queue-outbound-gateway request-channel="sendChannel" queue="foo"/>
<int-redis:queue-inbound-gateway request-channel="requestChannel" queue="foo"/>
Reactor's PersistentQueue
The QueueChannel
has been changed to allow inject any Queue<?>
implementation. This was done to allow the
use of the Chronicle-Queue implementation in the [Reactor]
(http://reactor.github.io/reactor/) project:
@Bean QueueChannel queueChannel() {
return new QueueChannel(new PersistentQueueSpec<Message<?>>()
.codec(new JavaSerializationCodec<>())
.basePath("/usr/queuePath")
.get());
}
Skipping Polls
When using polling endpoints, it is sometimes necessary to "skip" polls, perhaps because some downstream condition might
cause a failure or, say, a task executor pool has no available threads. This release adds the PollSkipAdvice
that
can be inserted in the poller's advice chain, with the skip logic based on user-supplied code.
Notes
Conclusion
See the Release Notes for this release and the Project Page for more information. For a complete list of "What's new" in the 4.1 release, see the reference documentation. Users upgrading from earlier releases should consult the various migration guides.
As always, we very much welcome contributions.