Spring Integration 4.1 RC1 Released

Releases | Artem Bilan | October 27, 2014 | ...

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:

@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] (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

  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.

Get the Spring newsletter

Thank you for your interest. Someone will get back to you shortly.

Get ahead

VMware offers training and certification to turbo-charge your progress.

Learn more

Get support

Tanzu Spring Runtime offers support and binaries for OpenJDK™, Spring, and Apache Tomcat® in one simple subscription.

Learn more

Upcoming events

Check out all the upcoming events in the Spring community.

View all