GH-8626: Provide cleaner transform() DSL (#8653)
* GH-8626: Provide cleaner `transform()` DSL Fixes https://github.com/spring-projects/spring-integration/issues/8626 * Add missed `transform(String beanName, @Nullable String methodName)` API * Introduce a `TransformerSpec` to expose a strict API to configure transformer variants. * Introduce `transformWith(Consumer<TransformerSpec>)` as a single point of all possible transformer and its endpoint options * Deprecate those `IntegrationFlowDefinition.transform()` variants which are harder to configure as several lambda arguments This change will make Kotlin & Groovy DSL more readable and straightforward * * Use new `transformWith()` in tests where a deprecated API still used * Add JavaDocs to `TransformerSpec` * Fix generic types for `BaseIntegrationFlowDefinition.transformWith()` - they make sense exactly on the `TransformerSpec.transformer()` only * Apply `transformWith()` for Groovy DSL * Introduce a new `ClassUtils.isLambda(Object candidate)` and add a check for Groovy `Closure` * Fix `GroovyIntegrationFlowDefinition.createConfigurerIfAny()` to propagate a `Consumer` argument down to the `Closure` * * Rename `TransformerSpec -> TransformerEndpointSpec` for better context meaning of the class * Introduce `KotlinTransformerEndpointSpec` as an extension of the `TransformerEndpointSpec` to have an `inline fun <reified P> transformer(crossinline function: (P) -> Any)` for Kotlin style * Add `KotlinIntegrationFlowDefinition.transformWith(KotlinTransformerEndpointSpec)` * Deprecate Kotlin methods which are covered by the mentioned `transformWith()` * Fix tests to use new API * Mentioned the change in the doc
This commit is contained in:
@@ -283,8 +283,10 @@ The following example demonstrates how to change the publishing thread from the
|
||||
public IntegrationFlow reactiveEndpointFlow() {
|
||||
return IntegrationFlow
|
||||
.from("inputChannel")
|
||||
.<String, Integer>transform(Integer::parseInt,
|
||||
e -> e.reactive(flux -> flux.publishOn(Schedulers.parallel())))
|
||||
.transformWith(t -> t
|
||||
.<String, Integer>transformer(Integer::parseInt)
|
||||
.reactive(flux -> flux.publishOn(Schedulers.parallel()))
|
||||
)
|
||||
.get();
|
||||
}
|
||||
----
|
||||
@@ -304,9 +306,13 @@ Each of them has generic arguments, so it lets you configure an endpoint and eve
|
||||
@Bean
|
||||
public IntegrationFlow flow2() {
|
||||
return IntegrationFlow.from(this.inputChannel)
|
||||
.transform(new PayloadSerializingTransformer(),
|
||||
c -> c.autoStartup(false).id("payloadSerializingTransformer"))
|
||||
.transform((Integer p) -> p * 2, c -> c.advice(this.expressionAdvice()))
|
||||
.transformWith(t -> t
|
||||
.transformer(new PayloadSerializingTransformer())
|
||||
.autoStartup(false)
|
||||
.id("payloadSerializingTransformer"))
|
||||
.transformWith(t -> t
|
||||
.transformer((Integer p) -> p * 2)
|
||||
.advice(expressionAdvice()))
|
||||
.get();
|
||||
}
|
||||
----
|
||||
@@ -361,6 +367,10 @@ Nevertheless, the DSL parser takes care of bean declarations for inline objects,
|
||||
|
||||
See https://docs.spring.io/spring-integration/api/org/springframework/integration/dsl/Transformers.html[Transformers] in the Javadoc for more information and supported factory methods.
|
||||
|
||||
Starting with version 6.2, a `transformWith(Consumer<TransformerEndpointSpec>)` variant has been introduced to have all the transformer and its endpoint options to be configured via single builder argument.
|
||||
This style gives DSL more readability and increases developer experience while modifying code.
|
||||
This also make Groovy and Kotlin DSLs more straightforward.
|
||||
|
||||
Also see <<java-dsl-class-cast>>.
|
||||
|
||||
[[java-dsl-inbound-adapters]]
|
||||
@@ -1428,4 +1438,4 @@ IntegrationFlow otherFlow() {
|
||||
|
||||
The composition in the middle of the flow is simply achievable with an existing `gateway(IntegrationFlow)` EIP-method.
|
||||
This way we can build flows with any complexity by composing them from simpler, reusable logical blocks.
|
||||
For example, you may add a library of `IntegrationFlow` beans as a dependency and it is just enough to have their configuration classes imported to the final project and autowired for your `IntegrationFlow` definitions.
|
||||
For example, you may add a library of `IntegrationFlow` beans as a dependency, and it is just enough to have their configuration classes imported to the final project and autowired for your `IntegrationFlow` definitions.
|
||||
|
||||
@@ -39,7 +39,10 @@ flowLambda() {
|
||||
messageGroupId 'delayGroup'
|
||||
defaultDelay 100
|
||||
}
|
||||
transform String, { it.toUpperCase() }
|
||||
transform {
|
||||
transformer { it.toUpperCase() }
|
||||
expectedType String
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -78,8 +81,14 @@ functionFlow() {
|
||||
integrationFlow Function<byte[], String>,
|
||||
{ beanName 'functionGateway' },
|
||||
{
|
||||
transform Transformers.objectToString(), { id 'objectToStringTransformer' }
|
||||
transform String, { it.toUpperCase() }
|
||||
transform {
|
||||
transformer Transformers.objectToString()
|
||||
id 'objectToStringTransformer'
|
||||
}
|
||||
transform {
|
||||
transformer { it.toUpperCase() }
|
||||
expectedType String
|
||||
}
|
||||
split Message<?>, { it.payload }
|
||||
split Object, { it }, { id 'splitterEndpoint' }
|
||||
resequence()
|
||||
|
||||
@@ -32,7 +32,7 @@ fun flowLambda() =
|
||||
wireTap {
|
||||
handle { println(it.payload) }
|
||||
}
|
||||
transform<String, String> { it.toUpperCase() }
|
||||
transform<String> { it.toUpperCase() }
|
||||
}
|
||||
----
|
||||
====
|
||||
@@ -67,7 +67,7 @@ For example:
|
||||
@Bean
|
||||
fun functionFlow() =
|
||||
integrationFlow<Function<String, String>>({ beanName("functionGateway") }) {
|
||||
transform<String, String> { it.toUpperCase() }
|
||||
transform<String> { it.toUpperCase() }
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -28,3 +28,6 @@ See <<./debezium.adoc#debezium, Debezium Support>> for more information.
|
||||
|
||||
- The XML configuration for `<poller>` and `@Poller` annotation now support ISO 8601 duration format for `fixed-delay`, `fixed-rate` and `initial-delay` options.
|
||||
See <<./endpoint.adoc#endpoint-pollingconsumer, Polling Consumer>> for more information.
|
||||
|
||||
- Java, Groovy and Kotlin DSLs have now context-specific methods in the `IntegationFlowDefinition` with a single `Consumer` argument to configure an endpoint and its handler with one builder and readable options.
|
||||
See, for example, `transformWith()` in <<./dsl.adoc#java-dsl, Java DSL Chapter>>.
|
||||
|
||||
Reference in New Issue
Block a user