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:
@@ -47,6 +47,7 @@ import org.springframework.integration.dsl.ResequencerSpec
|
||||
import org.springframework.integration.dsl.RouterSpec
|
||||
import org.springframework.integration.dsl.ScatterGatherSpec
|
||||
import org.springframework.integration.dsl.SplitterEndpointSpec
|
||||
import org.springframework.integration.dsl.TransformerEndpointSpec
|
||||
import org.springframework.integration.dsl.WireTapSpec
|
||||
import org.springframework.integration.filter.MethodInvokingSelector
|
||||
import org.springframework.integration.handler.BridgeHandler
|
||||
@@ -289,8 +290,10 @@ class GroovyIntegrationFlowDefinition {
|
||||
* for the SpEL {@link org.springframework.expression.Expression}.
|
||||
* @param expression the {@code Transformer} {@link org.springframework.expression.Expression}.
|
||||
* @param endpointConfigurer the {@link Consumer} to provide integration endpoint options.
|
||||
* @param endpointConfigurer the {@link Consumer} to provide integration endpoint options.
|
||||
* @see org.springframework.integration.transformer.ExpressionEvaluatingTransformer
|
||||
*/
|
||||
@Deprecated(since = '6.2', forRemoval = true)
|
||||
GroovyIntegrationFlowDefinition transform(
|
||||
String expression,
|
||||
@DelegatesTo(value = GenericEndpointSpec<MessageTransformingHandler>, strategy = Closure.DELEGATE_FIRST)
|
||||
@@ -308,8 +311,10 @@ class GroovyIntegrationFlowDefinition {
|
||||
* @param service the service to use.
|
||||
* @param methodName the method to invoke.
|
||||
* @param endpointConfigurer the {@link Consumer} to provide integration endpoint options.
|
||||
* @deprecated since 6.2 in favor of {@link #transform(Closure)}
|
||||
* @see ExpressionEvaluatingTransformer
|
||||
*/
|
||||
@Deprecated(since = '6.2', forRemoval = true)
|
||||
GroovyIntegrationFlowDefinition transform(
|
||||
Object service, String methodName = null,
|
||||
@DelegatesTo(value = GenericEndpointSpec<MessageTransformingHandler>, strategy = Closure.DELEGATE_FIRST)
|
||||
@@ -326,8 +331,10 @@ class GroovyIntegrationFlowDefinition {
|
||||
* In addition accept options for the integration endpoint using {@link GenericEndpointSpec}.
|
||||
* @param messageProcessorSpec the {@link MessageProcessorSpec} to use.
|
||||
* @param endpointConfigurer the {@link Consumer} to provide integration endpoint options.
|
||||
* @deprecated since 6.2 in favor of {@link #transform(Closure)}
|
||||
* @see MethodInvokingTransformer
|
||||
*/
|
||||
@Deprecated(since = '6.2', forRemoval = true)
|
||||
GroovyIntegrationFlowDefinition transform(
|
||||
MessageProcessorSpec<?> messageProcessorSpec,
|
||||
@DelegatesTo(value = GenericEndpointSpec<MessageTransformingHandler>, strategy = Closure.DELEGATE_FIRST)
|
||||
@@ -338,6 +345,24 @@ class GroovyIntegrationFlowDefinition {
|
||||
this
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the {@link MessageTransformingHandler} instance for the
|
||||
* {@link org.springframework.integration.handler.MessageProcessor} from provided {@link MessageProcessorSpec}.
|
||||
* In addition accept options for the integration endpoint using {@link GenericEndpointSpec}.
|
||||
* @param messageProcessorSpec the {@link MessageProcessorSpec} to use.
|
||||
* @param transformerConfigurer the {@link Consumer} to provide integration endpoint options.
|
||||
* @see MethodInvokingTransformer
|
||||
* @since 6.2
|
||||
*/
|
||||
GroovyIntegrationFlowDefinition transform(
|
||||
@DelegatesTo(value = TransformerEndpointSpec, strategy = Closure.DELEGATE_FIRST)
|
||||
@ClosureParams(value = SimpleType.class, options = 'org.springframework.integration.dsl.TransformerEndpointSpec')
|
||||
Closure<?> transformerConfigurer) {
|
||||
|
||||
this.delegate.transformWith createConfigurerIfAny(transformerConfigurer)
|
||||
this
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the {@link MessageTransformingHandler} instance
|
||||
* for the provided {@code payloadType} to convert at runtime.
|
||||
@@ -367,7 +392,9 @@ class GroovyIntegrationFlowDefinition {
|
||||
* @param endpointConfigurer the {@link Consumer} to provide integration endpoint options.
|
||||
* @param < P > the payload type - 'transform from', or {@code Message.class}.
|
||||
* @param < T > the target type - 'transform to'.
|
||||
* @deprecated since 6.2 in favor of {@link #transform(Closure)}
|
||||
*/
|
||||
@Deprecated(since = '6.2', forRemoval = true)
|
||||
<P, T> GroovyIntegrationFlowDefinition transform(
|
||||
GenericTransformer<P, T> genericTransformer,
|
||||
@DelegatesTo(value = GenericEndpointSpec<MessageTransformingHandler>, strategy = Closure.DELEGATE_FIRST)
|
||||
@@ -389,7 +416,9 @@ class GroovyIntegrationFlowDefinition {
|
||||
* @param endpointConfigurer the {@link Consumer} to provide integration endpoint options.
|
||||
* @param < P > the payload type - 'transform from', or {@code Message.class}.
|
||||
* @param < T > the target type - 'transform to'.
|
||||
* @deprecated since 6.2 in favor of {@link #transform(Closure)}
|
||||
*/
|
||||
@Deprecated(since = '6.2', forRemoval = true)
|
||||
<P, T> GroovyIntegrationFlowDefinition transform(
|
||||
Class<P> expectedType,
|
||||
GenericTransformer<P, T> genericTransformer,
|
||||
@@ -1336,7 +1365,7 @@ class GroovyIntegrationFlowDefinition {
|
||||
return {
|
||||
closure.delegate = it
|
||||
closure.resolveStrategy = Closure.DELEGATE_FIRST
|
||||
closure()
|
||||
closure(it)
|
||||
} as Consumer<T>
|
||||
}
|
||||
null
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022 the original author or authors.
|
||||
* Copyright 2022-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -130,11 +130,14 @@ class GroovyDslTests {
|
||||
def publisher = Flux.just(2, 3).map { new GenericMessage<>(it) }
|
||||
|
||||
def integrationFlow =
|
||||
integrationFlow(publisher)
|
||||
{
|
||||
transform Message<Integer>, { it.payload * 2 }, { id 'foo' }
|
||||
channel fluxChannel
|
||||
}
|
||||
integrationFlow(publisher) {
|
||||
transform {
|
||||
it.<Message<Integer>, Integer>transformer { it.payload * 2 }
|
||||
expectedType Message<Integer>
|
||||
id 'foo'
|
||||
}
|
||||
channel fluxChannel
|
||||
}
|
||||
|
||||
def registration = this.integrationFlowContext.registration(integrationFlow).register()
|
||||
|
||||
@@ -217,7 +220,7 @@ class GroovyDslTests {
|
||||
assert groovyTestService.result.get() == 'TEST'
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableIntegration
|
||||
static class Config {
|
||||
|
||||
@@ -240,7 +243,9 @@ class GroovyDslTests {
|
||||
requestReplyFlow() {
|
||||
integrationFlow {
|
||||
fluxTransform { it.map { it } }
|
||||
transform String, { it.toUpperCase() }
|
||||
transform {
|
||||
transformer { it.toUpperCase() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,8 +262,13 @@ class GroovyDslTests {
|
||||
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() }
|
||||
}
|
||||
split Message<?>, { it.payload }
|
||||
split Object, { it }, { id 'splitterEndpoint' }
|
||||
resequence()
|
||||
@@ -314,11 +324,13 @@ class GroovyDslTests {
|
||||
wireTap integrationFlow {
|
||||
channel { queue 'wireTapChannel' }
|
||||
}
|
||||
delay {
|
||||
delay {
|
||||
messageGroupId 'delayGroup'
|
||||
defaultDelay 100
|
||||
}
|
||||
transform String, { it.toUpperCase() }
|
||||
transform {
|
||||
transformer { it.toUpperCase() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user