Engineering
Releases
News and Events

Spring Integration 4.1 RC1 Released

Dear 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:
````java
@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 Lists 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 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

  1. Spring Integration 4.1 requires Spring Framework 4.1
  2. While JDK8 is now required to build Spring Integration, the framework remains compatible with Java 6 at runtime.
  3. We expect to announce the availability of the Spring Integration Java DSL release candidate later this week.

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.

comments powered by Disqus