For the latest stable version, please use Spring Integration 6.3.4! |
For the latest stable version, please use Spring Integration 6.3.4! |
Starting with version 5.1, Spring Integration provides direct support for interfaces in the java.util.function
package.
All messaging endpoints, (Service Activator, Transformer, Filter, etc.) can now refer to Function
(or Consumer
) beans.
The Messaging Annotations can be applied directly on these beans similar to regular MessageHandler
definitions.
For example if you have this Function
bean definition:
@Configuration
public class FunctionConfiguration {
@Bean
public Function<String, String> functionAsService() {
return String::toUpperCase;
}
}
You can use it as a simple reference in an XML configuration file:
<service-activator input-channel="processorViaFunctionChannel" ref="functionAsService"/>
When we configure our flow with Messaging Annotations, the code is straightforward:
@Bean
@Transformer(inputChannel = "functionServiceChannel")
public Function<String, String> functionAsService() {
return String::toUpperCase;
}
When the function returns an array, Collection
(essentially, any Iterable
), Stream
or Reactor Flux
, @Splitter
can be used on such a bean to perform iteration over the result content.
The java.util.function.Consumer
interface can be used for an <int:outbound-channel-adapter>
or, together with the @ServiceActivator
annotation, to perform the final step of a flow:
@Bean
@ServiceActivator(inputChannel = "messageConsumerServiceChannel")
public Consumer<Message<?>> messageConsumerAsService() {
// Has to be an anonymous class for proper type inference
return new Consumer<Message<?>>() {
@Override
public void accept(Message<?> e) {
collector().add(e);
}
};
}
Also, pay attention to the comment in the code snippet above: if you would like to deal with the whole message in your Function
/Consumer
you cannot use a lambda definition.
Because of Java type erasure we cannot determine the target type for the apply()/accept()
method call.
The java.util.function.Supplier
interface can simply be used together with the @InboundChannelAdapter
annotation, or as a ref
in an <int:inbound-channel-adapter>
:
@Bean
@InboundChannelAdapter(value = "inputChannel", poller = @Poller(fixedDelay = "1000"))
public Supplier<String> pojoSupplier() {
return () -> "foo";
}
With the Java DSL we just need to use a reference to the function bean in the endpoint definitions.
Meanwhile, an implementation of the Supplier
interface can be used as regular MessageSource
definition:
@Bean
public Function<String, String> toUpperCaseFunction() {
return String::toUpperCase;
}
@Bean
public Supplier<String> stringSupplier() {
return () -> "foo";
}
@Bean
public IntegrationFlow supplierFlow() {
return IntegrationFlow.from(stringSupplier())
.transform(toUpperCaseFunction())
.channel("suppliedChannel")
.get();
}
This function support is useful when used together with the Spring Cloud Function framework, where we have a function catalog and can refer to its member functions from an integration flow definition.