GH-3623: Deprecarte an IntegrationFlows
Fixes https://github.com/spring-projects/spring-integration/issues/3623 * `IntegrationFlow` refactoring * Apply several code style improvements and good practices * Code style: no empty lines for methods javadocs * make deprecated implementation reuse actual one instead of the copy-paste approach * add whats-new comments * Fix whats-new page according to standards
This commit is contained in:
committed by
GitHub
parent
63759d76b9
commit
53dd050c5b
@@ -52,7 +52,7 @@ The following listing shows the possible configuration options for an AMQP Inbou
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow amqpInbound(ConnectionFactory connectionFactory) {
|
||||
return IntegrationFlows.from(Amqp.inboundAdapter(connectionFactory, "aName"))
|
||||
return IntegrationFlow.from(Amqp.inboundAdapter(connectionFactory, "aName"))
|
||||
.handle(m -> System.out.println(m.getPayload()))
|
||||
.get();
|
||||
}
|
||||
@@ -283,7 +283,7 @@ The following example shows how to configure an `AmqpMessageSource`:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow flow() {
|
||||
return IntegrationFlows.from(Amqp.inboundPolledAdapter(connectionFactory(), DSL_QUEUE),
|
||||
return IntegrationFlow.from(Amqp.inboundPolledAdapter(connectionFactory(), DSL_QUEUE),
|
||||
e -> e.poller(Pollers.fixedDelay(1_000)).autoStartup(false))
|
||||
.handle(p -> {
|
||||
...
|
||||
@@ -328,7 +328,7 @@ The following listing shows the available attributes:
|
||||
----
|
||||
@Bean // return the upper cased payload
|
||||
public IntegrationFlow amqpInboundGateway(ConnectionFactory connectionFactory) {
|
||||
return IntegrationFlows.from(Amqp.inboundGateway(connectionFactory, "foo"))
|
||||
return IntegrationFlow.from(Amqp.inboundGateway(connectionFactory, "foo"))
|
||||
.transform(String.class, String::toUpperCase)
|
||||
.get();
|
||||
}
|
||||
@@ -490,7 +490,7 @@ The following example shows the available properties for an AMQP outbound channe
|
||||
@Bean
|
||||
public IntegrationFlow amqpOutbound(AmqpTemplate amqpTemplate,
|
||||
MessageChannel amqpOutboundChannel) {
|
||||
return IntegrationFlows.from(amqpOutboundChannel)
|
||||
return IntegrationFlow.from(amqpOutboundChannel)
|
||||
.handle(Amqp.outboundAdapter(amqpTemplate)
|
||||
.routingKey("queue1")) // default exchange - route to queue 'queue1'
|
||||
.get();
|
||||
@@ -1214,7 +1214,7 @@ The following example shows how to configure the channels with the Java DSL:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow pollableInFlow(ConnectionFactory connectionFactory) {
|
||||
return IntegrationFlows.from(...)
|
||||
return IntegrationFlow.from(...)
|
||||
...
|
||||
.channel(Amqp.pollableChannel(connectionFactory)
|
||||
.queueName("foo"))
|
||||
@@ -1224,7 +1224,7 @@ public IntegrationFlow pollableInFlow(ConnectionFactory connectionFactory) {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow messageDrivenInFow(ConnectionFactory connectionFactory) {
|
||||
return IntegrationFlows.from(...)
|
||||
return IntegrationFlow.from(...)
|
||||
...
|
||||
.channel(Amqp.channel(connectionFactory)
|
||||
.queueName("bar"))
|
||||
@@ -1234,7 +1234,7 @@ public IntegrationFlow messageDrivenInFow(ConnectionFactory connectionFactory) {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow pubSubInFlow(ConnectionFactory connectionFactory) {
|
||||
return IntegrationFlows.from(...)
|
||||
return IntegrationFlow.from(...)
|
||||
...
|
||||
.channel(Amqp.publishSubscribeChannel(connectionFactory)
|
||||
.queueName("baz"))
|
||||
@@ -1361,7 +1361,7 @@ Consider the following integration flow:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow flow(RabbitTemplate template) {
|
||||
return IntegrationFlows.from(Gateway.class)
|
||||
return IntegrationFlow.from(Gateway.class)
|
||||
.split(s -> s.delimiters(","))
|
||||
.<String, String>transform(String::toUpperCase)
|
||||
.handle(Amqp.outboundAdapter(template).routingKey("rk"))
|
||||
@@ -1385,7 +1385,7 @@ The following example shows how to use `BoundRabbitChannelAdvice`:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow flow(RabbitTemplate template) {
|
||||
return IntegrationFlows.from(Gateway.class)
|
||||
return IntegrationFlow.from(Gateway.class)
|
||||
.split(s -> s.delimiters(",")
|
||||
.advice(new BoundRabbitChannelAdvice(template, Duration.ofSeconds(10))))
|
||||
.<String, String>transform(String::toUpperCase)
|
||||
|
||||
@@ -119,7 +119,7 @@ You can use the Java Domain Specific Language (DSL) to configure a bridge, as th
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow bridgeFlow() {
|
||||
return IntegrationFlows.from("polled")
|
||||
return IntegrationFlow.from("polled")
|
||||
.bridge(e -> e.poller(Pollers.fixedDelay(5000).maxMessagesPerPoll(10)))
|
||||
.channel("direct")
|
||||
.get();
|
||||
|
||||
@@ -23,7 +23,7 @@ The following example defines two `inbound-channel-adapter` instances:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow source1() {
|
||||
return IntegrationFlows.from(() -> new GenericMessage<>(...),
|
||||
return IntegrationFlow.from(() -> new GenericMessage<>(...),
|
||||
e -> e.poller(p -> p.fixedRate(5000)))
|
||||
...
|
||||
.get();
|
||||
@@ -31,7 +31,7 @@ public IntegrationFlow source1() {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow source2() {
|
||||
return IntegrationFlows.from(() -> new GenericMessage<>(...),
|
||||
return IntegrationFlow.from(() -> new GenericMessage<>(...),
|
||||
e -> e.poller(p -> p.cron("30 * 9-17 * * MON-FRI")))
|
||||
...
|
||||
.get();
|
||||
|
||||
@@ -687,7 +687,7 @@ public PollableChannel priorityQueue(BasicMessageGroupStore mongoDbChannelMessag
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow priorityFlow(PriorityCapableChannelMessageStore mongoDbChannelMessageStore) {
|
||||
return IntegrationFlows.from((Channels c) ->
|
||||
return IntegrationFlow.from((Channels c) ->
|
||||
c.priority("priorityChannel", mongoDbChannelMessageStore, "priorityGroup"))
|
||||
....
|
||||
.get();
|
||||
|
||||
@@ -58,7 +58,7 @@ Similarly, you can configure Java DSL flow definitions as follows:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow controlBusFlow() {
|
||||
return IntegrationFlows.from("controlBus")
|
||||
return IntegrationFlow.from("controlBus")
|
||||
.controlBus()
|
||||
.get();
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ If you need to determine the delay for each message, you can also provide the Sp
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow flow() {
|
||||
return IntegrationFlows.from("input")
|
||||
return IntegrationFlow.from("input")
|
||||
.delay("delayer.messageGroupId", d -> d
|
||||
.defaultDelay(3_000L)
|
||||
.delayExpression("headers['delay']"))
|
||||
|
||||
@@ -11,7 +11,7 @@ We also use and support lambdas (available with Java 8) to further simplify Java
|
||||
|
||||
The https://github.com/spring-projects/spring-integration-samples/tree/main/dsl/cafe-dsl[cafe] offers a good example of using the DSL.
|
||||
|
||||
The DSL is presented by the `IntegrationFlows` factory for the `IntegrationFlowBuilder`.
|
||||
The DSL is presented by the `IntegrationFlow` fluent API (see `IntegrationFlowBuilder`).
|
||||
This produces the `IntegrationFlow` component, which should be registered as a Spring bean (by using the `@Bean` annotation).
|
||||
The builder pattern is used to express arbitrarily complex structures as a hierarchy of methods that can accept lambdas as arguments.
|
||||
|
||||
@@ -38,7 +38,7 @@ public class MyConfiguration {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow myFlow() {
|
||||
return IntegrationFlows.fromSupplier(integerSource()::getAndIncrement,
|
||||
return IntegrationFlow.fromSupplier(integerSource()::getAndIncrement,
|
||||
c -> c.poller(Pollers.fixedRate(100)))
|
||||
.channel("inputChannel")
|
||||
.filter((Integer p) -> p > 0)
|
||||
@@ -76,14 +76,14 @@ Conceptually, integration processes are constructed by composing these endpoints
|
||||
Note that EIP does not formally define the term 'message flow', but it is useful to think of it as a unit of work that uses well known messaging patterns.
|
||||
The DSL provides an `IntegrationFlow` component to define a composition of channels and endpoints between them, but now `IntegrationFlow` plays only the configuration role to populate real beans in the application context and is not used at runtime.
|
||||
However, the bean for `IntegrationFlow` can be autowired as a `Lifecycle` to control `start()` and `stop()` for the whole flow which is delegated to all the Spring Integration components associated with this `IntegrationFlow`.
|
||||
The following example uses the `IntegrationFlows` factory to define an `IntegrationFlow` bean by using EIP-methods from `IntegrationFlowBuilder`:
|
||||
The following example uses the `IntegrationFlow` fluent API to define an `IntegrationFlow` bean by using EIP-methods from `IntegrationFlowBuilder`:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow integerFlow() {
|
||||
return IntegrationFlows.from("input")
|
||||
return IntegrationFlow.from("input")
|
||||
.<String, Integer>transform(Integer::parseInt)
|
||||
.get();
|
||||
}
|
||||
@@ -102,7 +102,7 @@ Consider another example:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow myFlow() {
|
||||
return IntegrationFlows.from("input")
|
||||
return IntegrationFlow.from("input")
|
||||
.filter("World"::equals)
|
||||
.transform("Hello "::concat)
|
||||
.handle(System.out::println)
|
||||
@@ -190,7 +190,7 @@ public MessageChannel publishSubscribe() {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow channelFlow() {
|
||||
return IntegrationFlows.from("input")
|
||||
return IntegrationFlow.from("input")
|
||||
.fixedSubscriberChannel()
|
||||
.channel("queueChannel")
|
||||
.channel(publishSubscribe())
|
||||
@@ -217,7 +217,7 @@ The following example is wrong:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow startFlow() {
|
||||
return IntegrationFlows.from("input")
|
||||
return IntegrationFlow.from("input")
|
||||
.transform(...)
|
||||
.channel(MessageChannels.queue("queueChannel"))
|
||||
.get();
|
||||
@@ -225,7 +225,7 @@ public IntegrationFlow startFlow() {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow endFlow() {
|
||||
return IntegrationFlows.from(MessageChannels.queue("queueChannel"))
|
||||
return IntegrationFlow.from(MessageChannels.queue("queueChannel"))
|
||||
.handle(...)
|
||||
.get();
|
||||
}
|
||||
@@ -276,7 +276,7 @@ The following example demonstrates how to change the publishing thread from the
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow reactiveEndpointFlow() {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from("inputChannel")
|
||||
.<String, Integer>transform(Integer::parseInt,
|
||||
e -> e.reactive(flux -> flux.publishOn(Schedulers.parallel())))
|
||||
@@ -298,7 +298,7 @@ Each of them has generic arguments, so it lets you configure an endpoint and eve
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow flow2() {
|
||||
return IntegrationFlows.from(this.inputChannel)
|
||||
return IntegrationFlow.from(this.inputChannel)
|
||||
.transform(new PayloadSerializingTransformer(),
|
||||
c -> c.autoStartup(false).id("payloadSerializingTransformer"))
|
||||
.transform((Integer p) -> p * 2, c -> c.advice(this.expressionAdvice()))
|
||||
@@ -342,7 +342,7 @@ The following example shows how to use it:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow transformFlow() {
|
||||
return IntegrationFlows.from("input")
|
||||
return IntegrationFlow.from("input")
|
||||
.transform(Transformers.fromJson(MyPojo.class))
|
||||
.transform(Transformers.serializer())
|
||||
.get();
|
||||
@@ -364,9 +364,9 @@ Also see <<java-dsl-class-cast>>.
|
||||
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.
|
||||
Java DSL allows for starting `IntegrationFlow` from a `MessageSource<?>`, too.
|
||||
For this purpose, the `IntegrationFlows` builder factory provides an overloaded `IntegrationFlows.from(MessageSource<?> messageSource)` method.
|
||||
For this purpose, the `IntegrationFlow` fluent API provides an overloaded `IntegrationFlow.from(MessageSource<?> messageSource)` method.
|
||||
You can configure the `MessageSource<?>` as a bean and provide it as an argument for that method.
|
||||
The second parameter of `IntegrationFlows.from()` is a `Consumer<SourcePollingChannelAdapterSpec>` lambda that lets you provide options (such as `PollerMetadata` or `SmartLifecycle`) for the `SourcePollingChannelAdapter`.
|
||||
The second parameter of `IntegrationFlow.from()` is a `Consumer<SourcePollingChannelAdapterSpec>` lambda that lets you provide options (such as `PollerMetadata` or `SmartLifecycle`) for the `SourcePollingChannelAdapter`.
|
||||
The following example shows how to use the fluent API and a lambda to create an `IntegrationFlow`:
|
||||
|
||||
====
|
||||
@@ -379,7 +379,7 @@ public MessageSource<Object> jdbcMessageSource() {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow pollingFlow() {
|
||||
return IntegrationFlows.from(jdbcMessageSource(),
|
||||
return IntegrationFlow.from(jdbcMessageSource(),
|
||||
c -> c.poller(Pollers.fixedRate(100).maxMessagesPerPoll(1)))
|
||||
.transform(Transformers.toJson())
|
||||
.channel("furtherProcessChannel")
|
||||
@@ -388,7 +388,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 `IntegrationFlow.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`).
|
||||
|
||||
[[java-dsl-routers]]
|
||||
@@ -411,7 +411,7 @@ The fluent API also provides `AbstractMappingMessageRouter` options such as `cha
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow routeFlowByLambda() {
|
||||
return IntegrationFlows.from("routerInput")
|
||||
return IntegrationFlow.from("routerInput")
|
||||
.<Integer, Boolean>route(p -> p % 2 == 0,
|
||||
m -> m.suffix("Channel")
|
||||
.channelMapping(true, "even")
|
||||
@@ -429,7 +429,7 @@ The following example shows a simple expression-based router:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow routeFlowByExpression() {
|
||||
return IntegrationFlows.from("routerInput")
|
||||
return IntegrationFlow.from("routerInput")
|
||||
.route("headers['destChannel']")
|
||||
.get();
|
||||
}
|
||||
@@ -443,7 +443,7 @@ The `routeToRecipients()` method takes a `Consumer<RecipientListRouterSpec>`, as
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow recipientListFlow() {
|
||||
return IntegrationFlows.from("recipientListInput")
|
||||
return IntegrationFlow.from("recipientListInput")
|
||||
.<String, String>transform(p -> p.replaceFirst("Payload", ""))
|
||||
.routeToRecipients(r -> r
|
||||
.recipient("thing1-channel", "'thing1' == payload")
|
||||
@@ -482,7 +482,7 @@ The following example shows how to use the `split()` method by providing a lambd
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow splitFlow() {
|
||||
return IntegrationFlows.from("splitInput")
|
||||
return IntegrationFlow.from("splitInput")
|
||||
.split(s -> s.applySequence(false).delimiters(","))
|
||||
.channel(MessageChannels.executor(taskExecutor()))
|
||||
.get();
|
||||
@@ -506,7 +506,7 @@ The following example shows a canonical example of the splitter-aggregator patte
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow splitAggregateFlow() {
|
||||
return IntegrationFlows.from("splitAggregateInput")
|
||||
return IntegrationFlow.from("splitAggregateInput")
|
||||
.split()
|
||||
.channel(MessageChannels.executor(this.taskExecutor()))
|
||||
.resequence()
|
||||
@@ -550,7 +550,7 @@ Having that, we can define a flow as follows:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow myFlow() {
|
||||
return IntegrationFlows.from("flow3Input")
|
||||
return IntegrationFlow.from("flow3Input")
|
||||
.<Integer>handle((p, h) -> p * 2)
|
||||
.get();
|
||||
}
|
||||
@@ -569,7 +569,7 @@ The following example shows what the resulting `IntegrationFlow` might look like
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow integerFlow() {
|
||||
return IntegrationFlows.from("input")
|
||||
return IntegrationFlow.from("input")
|
||||
.<byte[], String>transform(p - > new String(p, "UTF-8"))
|
||||
.handle(Integer.class, (p, h) -> p * 2)
|
||||
.get();
|
||||
@@ -590,7 +590,7 @@ public BytesToIntegerConverter bytesToIntegerConverter() {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow integerFlow() {
|
||||
return IntegrationFlows.from("input")
|
||||
return IntegrationFlow.from("input")
|
||||
.handle(Integer.class, (p, h) -> p * 2)
|
||||
.get();
|
||||
}
|
||||
@@ -619,7 +619,7 @@ Also, the `IntegrationFlow`-based methods allows calling existing `IntegrationFl
|
||||
----
|
||||
@Bean
|
||||
IntegrationFlow someFlow() {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(...)
|
||||
.gateway(subFlow())
|
||||
.handle(...)
|
||||
@@ -971,7 +971,7 @@ The following example shows how to use three of them (`Amqp`, `Jms`, and `Mail`)
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow amqpFlow() {
|
||||
return IntegrationFlows.from(Amqp.inboundGateway(this.rabbitConnectionFactory, queue()))
|
||||
return IntegrationFlow.from(Amqp.inboundGateway(this.rabbitConnectionFactory, queue()))
|
||||
.transform("hello "::concat)
|
||||
.transform(String.class, String::toUpperCase)
|
||||
.get();
|
||||
@@ -979,7 +979,7 @@ public IntegrationFlow amqpFlow() {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow jmsOutboundGatewayFlow() {
|
||||
return IntegrationFlows.from("jmsOutboundGatewayChannel")
|
||||
return IntegrationFlow.from("jmsOutboundGatewayChannel")
|
||||
.handle(Jms.outboundGateway(this.jmsConnectionFactory)
|
||||
.replyContainer(c ->
|
||||
c.concurrentConsumers(3)
|
||||
@@ -990,7 +990,7 @@ public IntegrationFlow jmsOutboundGatewayFlow() {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow sendMailFlow() {
|
||||
return IntegrationFlows.from("sendMailChannel")
|
||||
return IntegrationFlow.from("sendMailChannel")
|
||||
.handle(Mail.outboundAdapter("localhost")
|
||||
.port(smtpPort)
|
||||
.credentials("user", "pw")
|
||||
@@ -1024,7 +1024,7 @@ public QueueChannelSpec wrongMessagesChannel() {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow xpathFlow(MessageChannel wrongMessagesChannel) {
|
||||
return IntegrationFlows.from("inputChannel")
|
||||
return IntegrationFlow.from("inputChannel")
|
||||
.filter(new StringValueTestXPathMessageSelector("namespace-uri(/*)", "my:namespace"),
|
||||
e -> e.discardChannel(wrongMessagesChannel))
|
||||
.log(LoggingHandler.Level.ERROR, "test.category", m -> m.getHeaders().getId())
|
||||
@@ -1200,7 +1200,7 @@ Flux<Message<?>> messageFlux =
|
||||
QueueChannel resultChannel = new QueueChannel();
|
||||
|
||||
IntegrationFlow integrationFlow =
|
||||
IntegrationFlows.from(messageFlux)
|
||||
IntegrationFlow.from(messageFlux)
|
||||
.<Integer, Integer>transform(p -> p * 2)
|
||||
.channel(resultChannel)
|
||||
.get();
|
||||
@@ -1274,7 +1274,7 @@ public interface ControlBusGateway {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow controlBusFlow() {
|
||||
return IntegrationFlows.from(ControlBusGateway.class)
|
||||
return IntegrationFlow.from(ControlBusGateway.class)
|
||||
.controlBus()
|
||||
.get();
|
||||
}
|
||||
@@ -1287,7 +1287,7 @@ Nevertheless, the `requestChannel` is ignored and overridden with that internal
|
||||
Otherwise, creating such a configuration by using `IntegrationFlow` does not make sense.
|
||||
|
||||
By default, a `GatewayProxyFactoryBean` gets a conventional bean name, such as `[FLOW_BEAN_NAME.gateway]`.
|
||||
You can change that ID by using the `@MessagingGateway.name()` attribute or the overloaded `IntegrationFlows.from(Class<?> serviceInterface, Consumer<GatewayProxySpec> endpointConfigurer)` factory method.
|
||||
You can change that ID by using the `@MessagingGateway.name()` attribute or the overloaded `IntegrationFlow.from(Class<?> serviceInterface, Consumer<GatewayProxySpec> endpointConfigurer)` factory method.
|
||||
Also, all the attributes from the `@MessagingGateway` annotation on the interface are applied to the target `GatewayProxyFactoryBean`.
|
||||
When annotation configuration is not applicable, the `Consumer<GatewayProxySpec>` variant can be used for providing appropriate option for the target proxy.
|
||||
This DSL method is available starting with version 5.2.
|
||||
@@ -1299,7 +1299,7 @@ With Java 8, you can even create an integration gateway with the `java.util.func
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow errorRecovererFlow() {
|
||||
return IntegrationFlows.from(Function.class, (gateway) -> gateway.beanName("errorRecovererFunction"))
|
||||
return IntegrationFlow.from(Function.class, (gateway) -> gateway.beanName("errorRecovererFunction"))
|
||||
.handle((GenericHandler<?>) (p, h) -> {
|
||||
throw new RuntimeException("intentional");
|
||||
}, e -> e.advice(retryAdvice()))
|
||||
@@ -1387,21 +1387,21 @@ The input channel of any endpoint in the flow can be used to send messages from
|
||||
Furthermore, with a `@MessagingGateway` contract, Content Enricher components, composite endpoints like a `<chain>`, and now with `IntegrationFlow` beans (e.g. `IntegrationFlowAdapter`), it is straightforward enough to distribute the business logic between shorter, reusable parts.
|
||||
All that is needed for the final composition is knowledge about a `MessageChannel` to send to or receive from.
|
||||
|
||||
Starting with version `5.5.4`, to abstract more from `MessageChannel` and hide implementation details from the end-user, the `IntegrationFlows` introduces the `from(IntegrationFlow)` factory method to allow starting the current `IntegrationFlow` from the output of an existing flow:
|
||||
Starting with version `5.5.4`, to abstract more from `MessageChannel` and hide implementation details from the end-user, the `IntegrationFlow` introduces the `from(IntegrationFlow)` factory method to allow starting the current `IntegrationFlow` from the output of an existing flow:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
IntegrationFlow templateSourceFlow() {
|
||||
return IntegrationFlows.fromSupplier(() -> "test data")
|
||||
return IntegrationFlow.fromSupplier(() -> "test data")
|
||||
.channel("sourceChannel")
|
||||
.get();
|
||||
}
|
||||
|
||||
@Bean
|
||||
IntegrationFlow compositionMainFlow(IntegrationFlow templateSourceFlow) {
|
||||
return IntegrationFlows.from(templateSourceFlow)
|
||||
return IntegrationFlow.from(templateSourceFlow)
|
||||
.<String, String>transform(String::toUpperCase)
|
||||
.channel(c -> c.queue("compositionMainFlowResult"))
|
||||
.get();
|
||||
|
||||
@@ -339,7 +339,7 @@ public PollerMetadata defaultPoller() {
|
||||
// No 'poller' attribute because there is a default global poller
|
||||
@Bean
|
||||
public IntegrationFlow transformFlow(MyTransformer transformer) {
|
||||
return IntegrationFlows.from(MessageChannels.queue("pollable"))
|
||||
return IntegrationFlow.from(MessageChannels.queue("pollable"))
|
||||
.transform(transformer) // No 'poller' attribute because there is a default global poller
|
||||
.channel("output")
|
||||
.get();
|
||||
|
||||
@@ -91,7 +91,7 @@ public ApplicationEventListeningMessageProducer eventsAdapter() {
|
||||
public IntegrationFlow eventFlow(ApplicationEventListeningMessageProducer eventsAdapter,
|
||||
MessageChannel eventErrorChannel) {
|
||||
|
||||
return IntegrationFlows.from(eventsAdapter, e -> e.errorChannel(eventErrorChannel))
|
||||
return IntegrationFlow.from(eventsAdapter, e -> e.errorChannel(eventErrorChannel))
|
||||
.handle(...)
|
||||
...
|
||||
.get();
|
||||
|
||||
@@ -58,7 +58,7 @@ public class ContextConfiguration {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow feedFlow() {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(Feed.inboundAdapter(this.feedResource, "feedTest")
|
||||
.preserveWireFeed(true),
|
||||
e -> e.poller(p -> p.fixedDelay(100)))
|
||||
|
||||
@@ -462,7 +462,7 @@ public class FileReadingJavaApplication {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow fileReadingFlow() {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(Files.inboundAdapter(new File(INBOUND_PATH))
|
||||
.patternFilter("*.txt"),
|
||||
e -> e.poller(Pollers.fixedDelay(1000)))
|
||||
@@ -929,7 +929,7 @@ public class FileWritingJavaApplication {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow fileWritingFlow() {
|
||||
return IntegrationFlows.from("fileWritingInput")
|
||||
return IntegrationFlow.from("fileWritingInput")
|
||||
.enrichHeaders(h -> h.header(FileHeaders.FILENAME, "foo.txt")
|
||||
.header("directory", new File(tmpDir.getRoot(), "fileWritingFlow")))
|
||||
.handle(Files.outboundGateway(m -> m.getHeaders().get("directory")))
|
||||
@@ -1006,7 +1006,7 @@ public class FileSplitterApplication {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow fileSplitterFlow() {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(Files.inboundAdapter(tmpDir.getRoot())
|
||||
.filter(new ChainFileListFilter<File>()
|
||||
.addFilter(new AcceptOnceFileListFilter<>())
|
||||
|
||||
@@ -559,7 +559,7 @@ public class FtpJavaApplication {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow ftpInboundFlow() {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(Ftp.inboundAdapter(this.ftpSessionFactory)
|
||||
.preserveTimestamp(true)
|
||||
.remoteDirectory("foo")
|
||||
@@ -772,7 +772,7 @@ This allows files retrieved from different directories to be downloaded to simil
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow flow() {
|
||||
return IntegrationFlows.from(Ftp.inboundAdapter(sf())
|
||||
return IntegrationFlow.from(Ftp.inboundAdapter(sf())
|
||||
.filter(new FtpPersistentAcceptOnceFileListFilter(new SimpleMetadataStore(), "rotate"))
|
||||
.localDirectory(new File(tmpDir))
|
||||
.localFilenameExpression("#remoteDirectory + T(java.io.File).separator + #root")
|
||||
@@ -979,7 +979,7 @@ public class FtpJavaApplication {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow ftpOutboundFlow() {
|
||||
return IntegrationFlows.from("toFtpChannel")
|
||||
return IntegrationFlow.from("toFtpChannel")
|
||||
.handle(Ftp.outboundAdapter(ftpSessionFactory(), FileExistsMode.FAIL)
|
||||
.useTemporaryFileName(false)
|
||||
.fileNameExpression("headers['" + FileHeaders.FILENAME + "']")
|
||||
|
||||
@@ -101,7 +101,7 @@ public Supplier<String> stringSupplier() {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow supplierFlow() {
|
||||
return IntegrationFlows.from(stringSupplier())
|
||||
return IntegrationFlow.from(stringSupplier())
|
||||
.transform(toUpperCaseFunction())
|
||||
.channel("suppliedChannel")
|
||||
.get();
|
||||
|
||||
@@ -893,4 +893,4 @@ At that time, the calling thread starts waiting for the reply.
|
||||
If the flow was completely synchronous, the reply is immediately available.
|
||||
For asynchronous flows, the thread waits for up to this time.
|
||||
|
||||
See <<./dsl.adoc#integration-flow-as-gateway,`IntegrationFlow` as Gateway>> in the Java DSL chapter for options to define gateways through `IntegrationFlows`.
|
||||
See <<./dsl.adoc#integration-flow-as-gateway,`IntegrationFlow` as Gateway>> in the Java DSL chapter for options to define gateways through `IntegrationFlow`.
|
||||
|
||||
@@ -61,7 +61,7 @@ GraphQlMessageHandler handler(ExecutionGraphQlService graphQlService) {
|
||||
|
||||
@Bean
|
||||
IntegrationFlow graphqlQueryMessageHandlerFlow(GraphQlMessageHandler handler) {
|
||||
return IntegrationFlows.from(MessageChannels.flux("inputChannel"))
|
||||
return IntegrationFlow.from(MessageChannels.flux("inputChannel"))
|
||||
.handle(handler)
|
||||
.channel(c -> c.flux("resultChannel"))
|
||||
.get();
|
||||
|
||||
@@ -775,7 +775,7 @@ The following example shows how to configure an inbound gateway with the Java DS
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow inbound() {
|
||||
return IntegrationFlows.from(Http.inboundGateway("/foo")
|
||||
return IntegrationFlow.from(Http.inboundGateway("/foo")
|
||||
.requestMapping(m -> m.methods(HttpMethod.POST))
|
||||
.requestPayloadType(String.class))
|
||||
.channel("httpRequest")
|
||||
@@ -810,7 +810,7 @@ The following example shows how to configure an outbound gateway with the Java D
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow outbound() {
|
||||
return IntegrationFlows.from("httpOutRequest")
|
||||
return IntegrationFlow.from("httpOutRequest")
|
||||
.handle(Http.outboundGateway("http://localhost:8080/foo")
|
||||
.httpMethod(HttpMethod.POST)
|
||||
.expectedResponseType(String.class))
|
||||
|
||||
@@ -228,7 +228,7 @@ The following example shows how to configure an inbound UDP adapter with the Jav
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow udpIn() {
|
||||
return IntegrationFlows.from(Udp.inboundAdapter(11111))
|
||||
return IntegrationFlow.from(Udp.inboundAdapter(11111))
|
||||
.channel("udpChannel")
|
||||
.get();
|
||||
}
|
||||
@@ -283,7 +283,7 @@ The following example shows the equivalent configuration with the Java DSL:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow udpEchoUpcaseServer() {
|
||||
return IntegrationFlows.from(Udp.inboundAdapter(11111).id("udpIn"))
|
||||
return IntegrationFlow.from(Udp.inboundAdapter(11111).id("udpIn"))
|
||||
.<byte[], String>transform(p -> new String(p).toUpperCase())
|
||||
.handle(Udp.outboundAdapter("headers['ip_packetAddress']")
|
||||
.socketExpression("@udpIn.socket"))
|
||||
@@ -2266,7 +2266,7 @@ Here are some examples of using the DSL to configure flows using the DSL.
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow server() {
|
||||
return IntegrationFlows.from(Tcp.inboundAdapter(Tcp.netServer(1234)
|
||||
return IntegrationFlow.from(Tcp.inboundAdapter(Tcp.netServer(1234)
|
||||
.deserializer(TcpCodecs.lengthHeader1())
|
||||
.backlog(30))
|
||||
.errorChannel("tcpIn.errorChannel")
|
||||
@@ -2296,7 +2296,7 @@ public IntegrationFlow client() {
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow server() {
|
||||
return IntegrationFlows.from(Tcp.inboundGateway(Tcp.netServer(1234)
|
||||
return IntegrationFlow.from(Tcp.inboundGateway(Tcp.netServer(1234)
|
||||
.deserializer(TcpCodecs.lengthHeader1())
|
||||
.serializer(TcpCodecs.lengthHeader1())
|
||||
.backlog(30))
|
||||
|
||||
@@ -56,7 +56,7 @@ The following example defines an inbound channel adapter with a `Destination` re
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow jmsInbound(ConnectionFactory connectionFactory) {
|
||||
return IntegrationFlows.from(
|
||||
return IntegrationFlow.from(
|
||||
Jms.inboundAdapter(connectionFactory)
|
||||
.destination("inQueue"),
|
||||
e -> e.poller(poller -> poller.fixedRate(30000)))
|
||||
@@ -148,7 +148,7 @@ The following example defines a message-driven channel adapter with a `Destinati
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow jmsMessageDrivenRedeliveryFlow() {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(Jms.messageDrivenChannelAdapter(jmsConnectionFactory())
|
||||
.destination("inQueue"))
|
||||
.channel("exampleChannel")
|
||||
|
||||
@@ -445,7 +445,7 @@ public class JpaJavaApplication {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow pollingAdapterFlow() {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(Jpa.inboundAdapter(this.entityManagerFactory)
|
||||
.entityClass(StudentDomain.class)
|
||||
.maxResults(1)
|
||||
|
||||
@@ -239,7 +239,7 @@ The following example shows how to configure a message-driven channel adapter:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow topic1ListenerFromKafkaFlow() {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(Kafka.messageDrivenChannelAdapter(consumerFactory(),
|
||||
KafkaMessageDrivenChannelAdapter.ListenerMode.record, TEST_TOPIC1)
|
||||
.configureListenerContainer(c ->
|
||||
@@ -332,7 +332,7 @@ The following example shows how to do so:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow topic2ListenerFromKafkaFlow() {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(Kafka.messageDrivenChannelAdapter(kafkaListenerContainerFactory().createContainer(TEST_TOPIC2),
|
||||
KafkaMessageDrivenChannelAdapter.ListenerMode.record)
|
||||
.id("topic2Adapter"))
|
||||
@@ -360,7 +360,7 @@ The `KafkaMessageSource` provides a pollable channel adapter implementation.
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow flow(ConsumerFactory<String, String> cf) {
|
||||
return IntegrationFlows.from(Kafka.inboundChannelAdapter(cf, "myTopic")
|
||||
return IntegrationFlow.from(Kafka.inboundChannelAdapter(cf, "myTopic")
|
||||
.groupId("myDslGroupId"), e -> e.poller(Pollers.fixedDelay(5000)))
|
||||
.handle(System.out::println)
|
||||
.get();
|
||||
@@ -437,7 +437,7 @@ The following example shows how to configure a gateway:
|
||||
public IntegrationFlow outboundGateFlow(
|
||||
ReplyingKafkaTemplate<String, String, String> kafkaTemplate) {
|
||||
|
||||
return IntegrationFlows.from("kafkaRequests")
|
||||
return IntegrationFlow.from("kafkaRequests")
|
||||
.handle(Kafka.outboundGateway(kafkaTemplate))
|
||||
.channel("kafkaReplies")
|
||||
.get();
|
||||
@@ -497,7 +497,7 @@ Alternatively, you can also use a configuration similar to the following bean:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow outboundGateFlow() {
|
||||
return IntegrationFlows.from("kafkaRequests")
|
||||
return IntegrationFlow.from("kafkaRequests")
|
||||
.handle(Kafka.outboundGateway(producerFactory(), replyContainer())
|
||||
.configureKafkaTemplate(t -> t.replyTimeout(30_000)))
|
||||
.channel("kafkaReplies")
|
||||
@@ -524,7 +524,7 @@ The following example shows how to configure an inbound gateway:
|
||||
public IntegrationFlow serverGateway(
|
||||
ConcurrentMessageListenerContainer<Integer, String> container,
|
||||
KafkaTemplate<Integer, String> replyTemplate) {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(Kafka.inboundGateway(container, replyTemplate)
|
||||
.replyTimeout(30_000))
|
||||
.<String, String>transform(String::toUpperCase)
|
||||
@@ -589,7 +589,7 @@ Alternatively, you could configure an upper-case converter by using code similar
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow serverGateway() {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(Kafka.inboundGateway(consumerFactory(), containerProperties(),
|
||||
producerFactory())
|
||||
.replyTimeout(30_000))
|
||||
@@ -619,7 +619,7 @@ Each channel requires a `KafkaTemplate` for the sending side and either a listen
|
||||
public IntegrationFlow flowWithSubscribable(KafkaTemplate<Integer, String> template,
|
||||
ConcurrentKafkaListenerContainerFactory<Integer, String> containerFactory) {
|
||||
|
||||
return IntegrationFlows.from(...)
|
||||
return IntegrationFlow.from(...)
|
||||
...
|
||||
.channel(Kafka.channel(template, containerFactory, "someTopic1").groupId("group1"))
|
||||
...
|
||||
@@ -630,7 +630,7 @@ public IntegrationFlow flowWithSubscribable(KafkaTemplate<Integer, String> templ
|
||||
public IntegrationFlow flowWithPubSub(KafkaTemplate<Integer, String> template,
|
||||
ConcurrentKafkaListenerContainerFactory<Integer, String> containerFactory) {
|
||||
|
||||
return IntegrationFlows.from(...)
|
||||
return IntegrationFlow.from(...)
|
||||
...
|
||||
.publishSubscribeChannel(pubSub(template, containerFactory),
|
||||
pubsub -> pubsub
|
||||
@@ -652,7 +652,7 @@ public BroadcastCapableChannel pubSub(KafkaTemplate<Integer, String> template,
|
||||
public IntegrationFlow flowWithPollable(KafkaTemplate<Integer, String> template,
|
||||
KafkaMessageSource<Integer, String> source) {
|
||||
|
||||
return IntegrationFlows.from(...)
|
||||
return IntegrationFlow.from(...)
|
||||
...
|
||||
.channel(Kafka.pollableChannel(template, source, "someTopic3").groupId("group3"))
|
||||
.handle(..., e -> e.poller(...))
|
||||
@@ -821,7 +821,7 @@ public MessagingTransformer<byte[], byte[], String> transformer(
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow flow() {
|
||||
return IntegrationFlows.from(MessagingFunction.class)
|
||||
return IntegrationFlow.from(MessagingFunction.class)
|
||||
...
|
||||
.get();
|
||||
}
|
||||
@@ -856,7 +856,7 @@ public class FuturesChannelApplication {
|
||||
|
||||
@Bean
|
||||
IntegrationFlow inbound(ConsumerFactory<String, String> consumerFactory, Handler handler) {
|
||||
return IntegrationFlows.from(Kafka.messageDrivenChannelAdapter(consumerFactory,
|
||||
return IntegrationFlow.from(Kafka.messageDrivenChannelAdapter(consumerFactory,
|
||||
ListenerMode.batch, "inTopic"))
|
||||
.handle(handler)
|
||||
.get();
|
||||
@@ -864,7 +864,7 @@ public class FuturesChannelApplication {
|
||||
|
||||
@Bean
|
||||
IntegrationFlow outbound(KafkaTemplate<String, String> kafkaTemplate) {
|
||||
return IntegrationFlows.from(Gate.class)
|
||||
return IntegrationFlow.from(Gate.class)
|
||||
.enrichHeaders(h -> h
|
||||
.header(KafkaHeaders.TOPIC, "outTopic")
|
||||
.headerExpression(KafkaIntegrationHeaders.FUTURE_TOKEN, "headers[id]"))
|
||||
|
||||
@@ -41,22 +41,22 @@ Such a global `integrationFlow()` function expects a lambda in builder style for
|
||||
See more overloaded `integrationFlow()` variants below.
|
||||
|
||||
Many other scenarios require an `IntegrationFlow` to be started from source of data (e.g. `JdbcPollingChannelAdapter`, `JmsInboundGateway` or just an existing `MessageChannel`).
|
||||
For this purpose, the Spring Integration Java DSL provides an `IntegrationFlows` factory with its large number of overloaded `from()` methods.
|
||||
This factory can be used in Kotlin as well:
|
||||
For this purpose, the Spring Integration Java DSL provides an `IntegrationFlow` fluent API with its large number of overloaded `from()` methods.
|
||||
This API can be used in Kotlin as well:
|
||||
|
||||
====
|
||||
[source, kotlin]
|
||||
----
|
||||
@Bean
|
||||
fun flowFromSupplier() =
|
||||
IntegrationFlows.from<String>({ "bar" }) { e -> e.poller { p -> p.fixedDelay(10).maxMessagesPerPoll(1) } }
|
||||
IntegrationFlow.from<String>({ "bar" }) { e -> e.poller { p -> p.fixedDelay(10).maxMessagesPerPoll(1) } }
|
||||
.channel { c -> c.queue("fromSupplierQueue") }
|
||||
.get()
|
||||
----
|
||||
====
|
||||
|
||||
But unfortunately not all `from()` methods are compatible with Kotlin structures.
|
||||
To fix the gap, this project provides a Kotlin DSL around an `IntegrationFlows` factory.
|
||||
To fix the gap, this project provides a Kotlin DSL around an `IntegrationFlow` fluent API.
|
||||
It is implemented as a set of overloaded `integrationFlow()` functions.
|
||||
With a consumer for a `KotlinIntegrationFlowDefinition` to declare the rest of the flow as an `IntegrationFlow` lambda to reuse the mentioned above experience and also avoid `get()` call in the end.
|
||||
For example:
|
||||
|
||||
@@ -98,7 +98,7 @@ public class LoggingJavaApplication {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow loggingFlow() {
|
||||
return IntegrationFlows.from(MyGateway.class)
|
||||
return IntegrationFlow.from(MyGateway.class)
|
||||
.log(LoggingHandler.Level.DEBUG, "TEST_LOGGER",
|
||||
m -> m.getHeaders().getId() + ": " + m.getPayload());
|
||||
}
|
||||
|
||||
@@ -612,7 +612,7 @@ public class MailApplication {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow imapMailFlow() {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(Mail.imapInboundAdapter("imap://user:pw@host:port/INBOX")
|
||||
.searchTermStrategy(this::fromAndNotSeenTerm)
|
||||
.userFlag("testSIUserFlag")
|
||||
@@ -626,7 +626,7 @@ public class MailApplication {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow sendMailFlow() {
|
||||
return IntegrationFlows.from("sendMailChannel")
|
||||
return IntegrationFlow.from("sendMailChannel")
|
||||
.enrichHeaders(Mail.headers()
|
||||
.subjectFunction(m -> "foo")
|
||||
.from("foo@bar")
|
||||
|
||||
@@ -364,7 +364,7 @@ The Java DSL configuration for this channel adapter may look like this:
|
||||
----
|
||||
@Bean
|
||||
IntegrationFlow changeStreamFlow(ReactiveMongoOperations mongoTemplate) {
|
||||
return IntegrationFlows.from(
|
||||
return IntegrationFlow.from(
|
||||
MongoDb.changeStreamInboundChannelAdapter(mongoTemplate)
|
||||
.domainType(Person.class)
|
||||
.collection("person")
|
||||
@@ -602,7 +602,7 @@ With Java DSL such a channel adapter could be configured like:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow reactiveMongoDbFlow(ReactiveMongoDatabaseFactory mongoDbFactory) {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(MongoDb.reactiveInboundChannelAdapter(mongoDbFactory, "{'name' : 'Name'}")
|
||||
.entityClass(Person.class),
|
||||
c -> c.poller(Pollers.fixedDelay(1000)))
|
||||
|
||||
@@ -237,7 +237,7 @@ public class MqttJavaApplication {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow mqttInbound() {
|
||||
return IntegrationFlows.from(
|
||||
return IntegrationFlow.from(
|
||||
new MqttPahoMessageDrivenChannelAdapter("tcp://localhost:1883",
|
||||
"testClient", "topic1", "topic2");)
|
||||
.handle(m -> System.out.println(m.getPayload()))
|
||||
@@ -488,7 +488,7 @@ public IntegrationFlow mqttInFlow() {
|
||||
messageProducer.setMessageConverter(mqttStringToBytesConverter());
|
||||
messageProducer.setManualAcks(true);
|
||||
|
||||
return IntegrationFlows.from(messageProducer)
|
||||
return IntegrationFlow.from(messageProducer)
|
||||
.channel(c -> c.queue("fromMqttChannel"))
|
||||
.get();
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ With Java DSL a configuration for this channel adapter is like this:
|
||||
----
|
||||
@Bean
|
||||
IntegrationFlow r2dbcDslFlow(R2dbcEntityTemplate r2dbcEntityTemplate) {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(R2dbc.inboundChannelAdapter(r2dbcEntityTemplate,
|
||||
(selectCreator) ->
|
||||
selectCreator.createSelect("person")
|
||||
|
||||
@@ -122,7 +122,7 @@ See <<./splitter.adoc#split-stream-and-flux,Stream and Flux Splitting>> and <<./
|
||||
|
||||
=== Java DSL
|
||||
|
||||
An `IntegrationFlow` in Java DSL can start from any `Publisher` instance (see `IntegrationFlows.from(Publisher<Message<T>>)`).
|
||||
An `IntegrationFlow` in Java DSL can start from any `Publisher` instance (see `IntegrationFlow.from(Publisher<Message<T>>)`).
|
||||
Also, with an `IntegrationFlowBuilder.toReactivePublisher()` operator, the `IntegrationFlow` can be turned into a reactive hot source.
|
||||
A `FluxMessageChannel` is used internally in both cases; it can subscribe to an inbound `Publisher` according to its `ReactiveStreamsSubscribableChannel` contract and it is a `Publisher<Message<?>>` by itself for downstream subscribers.
|
||||
With a dynamic `IntegrationFlow` registration we can implement a powerful logic combining Reactive Streams with this integration flow bridging to/from `Publisher`.
|
||||
@@ -205,7 +205,7 @@ public class MainFlow {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow buildFlow() {
|
||||
return IntegrationFlows.from(customReactiveMessageProducer)
|
||||
return IntegrationFlow.from(customReactiveMessageProducer)
|
||||
.channel(outputChannel)
|
||||
.get();
|
||||
}
|
||||
@@ -221,7 +221,7 @@ Or in a declarative way:
|
||||
public class MainFlow {
|
||||
@Bean
|
||||
public IntegrationFlow buildFlow() {
|
||||
return IntegrationFlows.from(new CustomReactiveMessageProducer(new CustomReactiveSource()))
|
||||
return IntegrationFlow.from(new CustomReactiveMessageProducer(new CustomReactiveSource()))
|
||||
.handle(outputChannel)
|
||||
.get();
|
||||
}
|
||||
@@ -243,7 +243,7 @@ public class MainFlow {
|
||||
.withPayload(event.getBody())
|
||||
.setHeader(MyReactiveHeaders.SOURCE_NAME, event.getSourceName())
|
||||
.build());
|
||||
return IntegrationFlows.from(myFlux)
|
||||
return IntegrationFlow.from(myFlux)
|
||||
.handle(outputChannel)
|
||||
.get();
|
||||
}
|
||||
@@ -317,7 +317,7 @@ public class MainFlow {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow buildFlow() {
|
||||
return IntegrationFlows.from(customReactiveMessageProducer)
|
||||
return IntegrationFlow.from(customReactiveMessageProducer)
|
||||
.transform(someOperation)
|
||||
.handle(customReactiveMessageHandler)
|
||||
.get();
|
||||
|
||||
@@ -464,7 +464,7 @@ First, you can define the router object as shown in the preceding example:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow routerFlow1() {
|
||||
return IntegrationFlows.from("routingChannel")
|
||||
return IntegrationFlow.from("routingChannel")
|
||||
.route(router())
|
||||
.get();
|
||||
}
|
||||
@@ -487,7 +487,7 @@ Second, you can define the routing function within the DSL flow itself, as the f
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow routerFlow2() {
|
||||
return IntegrationFlows.from("routingChannel")
|
||||
return IntegrationFlow.from("routingChannel")
|
||||
.<Object, Class<?>>route(Object::getClass, m -> m
|
||||
.channelMapping(String.class, "stringChannel")
|
||||
.channelMapping(Integer.class, "integerChannel"))
|
||||
@@ -555,7 +555,7 @@ First, you can define the router object as shown in the preceding example:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow routerFlow1() {
|
||||
return IntegrationFlows.from("routingChannel")
|
||||
return IntegrationFlow.from("routingChannel")
|
||||
.route(router())
|
||||
.get();
|
||||
}
|
||||
@@ -579,7 +579,7 @@ Second, you can define the routing function within the DSL flow itself, as the f
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow routerFlow2() {
|
||||
return IntegrationFlows.from("routingChannel")
|
||||
return IntegrationFlow.from("routingChannel")
|
||||
.route(Message.class, m -> m.getHeaders().get("testHeader", String.class),
|
||||
m -> m
|
||||
.channelMapping("someHeaderValue", "channelA")
|
||||
@@ -673,7 +673,7 @@ The following example shows the equivalent router configured by using the Java D
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow routerFlow() {
|
||||
return IntegrationFlows.from("routingChannel")
|
||||
return IntegrationFlow.from("routingChannel")
|
||||
.routeToRecipients(r -> r
|
||||
.applySequence(true)
|
||||
.ignoreSendFailures(true)
|
||||
@@ -861,7 +861,7 @@ The following example shows the equivalent router configured by using the Java D
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow routerFlow() {
|
||||
return IntegrationFlows.from("routingChannel")
|
||||
return IntegrationFlow.from("routingChannel")
|
||||
.route(myCustomRouter())
|
||||
.get();
|
||||
}
|
||||
@@ -886,7 +886,7 @@ Alternately, you can route on data from the message payload, as the following ex
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow routerFlow() {
|
||||
return IntegrationFlows.from("routingChannel")
|
||||
return IntegrationFlow.from("routingChannel")
|
||||
.route(String.class, p -> p.contains("foo") ? "fooChannel" : "barChannel")
|
||||
.get();
|
||||
}
|
||||
@@ -938,7 +938,7 @@ The following example shows the equivalent router configured in the Java DSL:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow routerFlow() {
|
||||
return IntegrationFlows.from("routingChannel")
|
||||
return IntegrationFlow.from("routingChannel")
|
||||
.route("payload.paymentType", r -> r
|
||||
.channelMapping("CASH", "cashPaymentChannel")
|
||||
.channelMapping("CREDIT", "authorizePaymentChannel")
|
||||
|
||||
@@ -290,7 +290,7 @@ The following example shows how to configure a RSocket inbound gateway with the
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow rsocketUpperCaseFlow() {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(RSockets.inboundGateway("/uppercase")
|
||||
.interactionModels(RSocketInteractionModel.requestChannel))
|
||||
.<Flux<String>, Mono<String>>transform((flux) -> flux.next().map(String::toUpperCase))
|
||||
@@ -332,7 +332,7 @@ The following example shows how to configure a RSocket outbound gateway with the
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow rsocketUpperCaseRequestFlow(ClientRSocketConnector clientRSocketConnector) {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(Function.class)
|
||||
.handle(RSockets.outboundGateway("/uppercase")
|
||||
.interactionModel(RSocketInteractionModel.requestResponse)
|
||||
|
||||
@@ -552,7 +552,7 @@ public class SftpJavaApplication {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow sftpInboundFlow() {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(Sftp.inboundAdapter(this.sftpSessionFactory)
|
||||
.preserveTimestamp(true)
|
||||
.remoteDirectory("foo")
|
||||
@@ -763,7 +763,7 @@ This allows files retrieved from different directories to be downloaded to simil
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow flow() {
|
||||
return IntegrationFlows.from(Sftp.inboundAdapter(sf())
|
||||
return IntegrationFlow.from(Sftp.inboundAdapter(sf())
|
||||
.filter(new SftpPersistentAcceptOnceFileListFilter(new SimpleMetadataStore(), "rotate"))
|
||||
.localDirectory(new File(tmpDir))
|
||||
.localFilenameExpression("#remoteDirectory + T(java.io.File).separator + #root")
|
||||
@@ -952,7 +952,7 @@ public class SftpJavaApplication {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow sftpOutboundFlow() {
|
||||
return IntegrationFlows.from("toSftpChannel")
|
||||
return IntegrationFlow.from("toSftpChannel")
|
||||
.handle(Sftp.outboundAdapter(this.sftpSessionFactory, FileExistsMode.FAIL)
|
||||
.useTemporaryFileName(false)
|
||||
.remoteDirectory("/foo")
|
||||
@@ -1310,7 +1310,7 @@ public class SftpJavaApplication {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow sftpMGetFlow() {
|
||||
return IntegrationFlows.from("sftpMgetInputChannel")
|
||||
return IntegrationFlow.from("sftpMgetInputChannel")
|
||||
.handle(Sftp.outboundGateway(sftpSessionFactory(),
|
||||
AbstractRemoteFileOutboundGateway.Command.MGET, "payload")
|
||||
.options(AbstractRemoteFileOutboundGateway.Option.RECURSIVE)
|
||||
|
||||
@@ -169,7 +169,7 @@ public class SmbJavaApplication {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow smbInboundFlow() {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(Smb.inboundAdapter(smbSessionFactory())
|
||||
.preserveTimestamp(true)
|
||||
.remoteDirectory("smbSource")
|
||||
@@ -375,7 +375,7 @@ public class SmbJavaApplication {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow smbOutboundFlow() {
|
||||
return IntegrationFlows.from("toSmbChannel")
|
||||
return IntegrationFlow.from("toSmbChannel")
|
||||
.handle(Smb.outboundAdapter(smbSessionFactory(), FileExistsMode.REPLACE)
|
||||
.useTemporaryFileName(false)
|
||||
.fileNameExpression("headers['" + FileHeaders.FILENAME + "']")
|
||||
|
||||
@@ -288,7 +288,7 @@ public MessageSource<Integer> testingMessageSource() {
|
||||
return MockIntegration.mockMessageSource(1, 2, 3);
|
||||
}
|
||||
...
|
||||
StandardIntegrationFlow flow = IntegrationFlows
|
||||
StandardIntegrationFlow flow = IntegrationFlow
|
||||
.from(MockIntegration.mockMessageSource("foo", "bar", "baz"))
|
||||
.<String, String>transform(String::toUpperCase)
|
||||
.channel(out)
|
||||
|
||||
@@ -415,7 +415,7 @@ WebSocketInboundChannelAdapter webSocketInboundChannelAdapter =
|
||||
QueueChannel dynamicRequestsChannel = new QueueChannel();
|
||||
|
||||
IntegrationFlow serverFlow =
|
||||
IntegrationFlows.from(webSocketInboundChannelAdapter)
|
||||
IntegrationFlow.from(webSocketInboundChannelAdapter)
|
||||
.channel(dynamicRequestsChannel)
|
||||
.get();
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ The following example shows a simple implementation of a WebFlux endpoint:
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow inboundChannelAdapterFlow() {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(WebFlux.inboundChannelAdapter("/reactivePost")
|
||||
.requestMapping(m -> m.methods(HttpMethod.POST))
|
||||
.requestPayloadType(ResolvableType.forClassWithGenerics(Flux.class, String.class))
|
||||
@@ -142,7 +142,7 @@ This way, we can implement https://en.wikipedia.org/wiki/Server-sent_events[Serv
|
||||
----
|
||||
@Bean
|
||||
public IntegrationFlow sseFlow() {
|
||||
return IntegrationFlows
|
||||
return IntegrationFlow
|
||||
.from(WebFlux.inboundGateway("/sse")
|
||||
.requestMapping(m -> m.produces(MediaType.TEXT_EVENT_STREAM_VALUE)))
|
||||
.handle((p, h) -> Flux.just("foo", "bar", "baz"))
|
||||
|
||||
@@ -47,6 +47,9 @@ The `AggregatingMessageHandler` now does not split a `Collection<Message<?>>` re
|
||||
|
||||
See <<./aggregator.adoc#aggregator,Aggregator>> for more information.
|
||||
|
||||
The `IntegrationFlows` factory is now marked as deprecated in favor of the fluent API available in the `IntegrationFlow` interface itself.
|
||||
The factory class will be removed in the future releases.
|
||||
|
||||
[[x6.0-http]]
|
||||
=== HTTP Changes
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ The equivalent configuration for the gateways shown in <<webservices-namespace>>
|
||||
----
|
||||
@Bean
|
||||
IntegrationFlow inbound() {
|
||||
return IntegrationFlows.from(Ws.simpleInboundGateway()
|
||||
return IntegrationFlow.from(Ws.simpleInboundGateway()
|
||||
.id("simpleGateway"))
|
||||
...
|
||||
.get();
|
||||
@@ -205,7 +205,7 @@ IntegrationFlow outboundMarshalled() {
|
||||
----
|
||||
@Bean
|
||||
IntegrationFlow inboundMarshalled() {
|
||||
return IntegrationFlows.from(Ws.marshallingInboundGateway()
|
||||
return IntegrationFlow.from(Ws.marshallingInboundGateway()
|
||||
.marshaller(someMarshaller())
|
||||
.unmarshaller(someUnmarshalller())
|
||||
.id("marshallingGateway"))
|
||||
|
||||
@@ -193,7 +193,7 @@ The Inbound Channel Adapter for ZeroMQ Java DSL is:
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
IntegrationFlows.from(
|
||||
IntegrationFlow.from(
|
||||
ZeroMq.inboundChannelAdapter(this.context, SocketType.SUB)
|
||||
.connectUrl("tcp://localhost:9000")
|
||||
.topics("someTopic")
|
||||
|
||||
Reference in New Issue
Block a user