Skip to content

Commit 070c1c6

Browse files
authored
GH-8626: Provide cleaner transform() DSL (#8653)
* GH-8626: Provide cleaner `transform()` DSL Fixes #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
1 parent ceb3dae commit 070c1c6

File tree

20 files changed

+593
-61
lines changed

20 files changed

+593
-61
lines changed

spring-integration-core/src/main/java/org/springframework/integration/dsl/BaseIntegrationFlowDefinition.java

+67-7
Original file line numberDiff line numberDiff line change
@@ -538,12 +538,18 @@ public B controlBus(@Nullable Consumer<GenericEndpointSpec<ServiceActivatingHand
538538
/**
539539
* Populate the {@code Transformer} EI Pattern specific {@link MessageHandler} implementation
540540
* for the SpEL {@link Expression}.
541+
* Shortcut for:
542+
* <pre class="code">
543+
* {@code
544+
* .transformWith((transformerSpec) -> transformerSpec.expression(expression))
545+
* }
546+
* </pre>
541547
* @param expression the {@code Transformer} {@link Expression}.
542548
* @return the current {@link BaseIntegrationFlowDefinition}.
543549
* @see ExpressionEvaluatingTransformer
544550
*/
545551
public B transform(String expression) {
546-
return transform(expression, (Consumer<GenericEndpointSpec<MessageTransformingHandler>>) null);
552+
return transformWith((transformerSpec) -> transformerSpec.expression(expression));
547553
}
548554

549555
/**
@@ -552,8 +558,10 @@ public B transform(String expression) {
552558
* @param expression the {@code Transformer} {@link Expression}.
553559
* @param endpointConfigurer the {@link Consumer} to provide integration endpoint options.
554560
* @return the current {@link BaseIntegrationFlowDefinition}.
561+
* @deprecated since 6.2 in favor of {@link #transformWith(Consumer)}.
555562
* @see ExpressionEvaluatingTransformer
556563
*/
564+
@Deprecated(since = "6.2", forRemoval = true)
557565
public B transform(String expression,
558566
@Nullable Consumer<GenericEndpointSpec<MessageTransformingHandler>> endpointConfigurer) {
559567

@@ -566,9 +574,15 @@ public B transform(String expression,
566574
/**
567575
* Populate the {@code MessageTransformingHandler} for the {@link MethodInvokingTransformer}
568576
* to invoke the discovered service method at runtime.
577+
* Shortcut for:
578+
* <pre class="code">
579+
* {@code
580+
* .transformWith((transformerSpec) -> transformerSpec.ref(service))
581+
* }
582+
* </pre>
569583
* @param service the service to use.
570584
* @return the current {@link BaseIntegrationFlowDefinition}.
571-
* @see ExpressionEvaluatingTransformer
585+
* @see MethodInvokingTransformer
572586
*/
573587
public B transform(Object service) {
574588
return transform(service, null);
@@ -577,13 +591,36 @@ public B transform(Object service) {
577591
/**
578592
* Populate the {@code MessageTransformingHandler} for the {@link MethodInvokingTransformer}
579593
* to invoke the service method at runtime.
594+
* <pre class="code">
595+
* {@code
596+
* .transformWith((transformerSpec) -> transformerSpec.ref(service).method(methodName))
597+
* }
598+
* </pre>
580599
* @param service the service to use.
581600
* @param methodName the method to invoke.
582601
* @return the current {@link BaseIntegrationFlowDefinition}.
583602
* @see MethodInvokingTransformer
584603
*/
585604
public B transform(Object service, @Nullable String methodName) {
586-
return transform(service, methodName, null);
605+
return transformWith((transformerSpec) -> transformerSpec.ref(service).method(methodName));
606+
}
607+
608+
/**
609+
* Populate the {@code MessageTransformingHandler} for the {@link MethodInvokingTransformer}
610+
* to invoke the bean method at runtime.
611+
* <pre class="code">
612+
* {@code
613+
* .transformWith((transformerSpec) -> transformerSpec.refName(beanName).method(methodName))
614+
* }
615+
* </pre>
616+
* @param beanName the name for bean to resolve lazily.
617+
* @param methodName the method to invoke.
618+
* @return the current {@link BaseIntegrationFlowDefinition}.
619+
* @since 6.2
620+
* @see MethodInvokingTransformer
621+
*/
622+
public B transform(String beanName, @Nullable String methodName) {
623+
return transformWith((transformerSpec) -> transformerSpec.refName(beanName).method(methodName));
587624
}
588625

589626
/**
@@ -593,8 +630,10 @@ public B transform(Object service, @Nullable String methodName) {
593630
* @param methodName the method to invoke.
594631
* @param endpointConfigurer the {@link Consumer} to provide integration endpoint options.
595632
* @return the current {@link BaseIntegrationFlowDefinition}.
596-
* @see ExpressionEvaluatingTransformer
633+
* @deprecated since 6.2 in favor of {@link #transformWith(Consumer)}.
634+
* @see MethodInvokingTransformer
597635
*/
636+
@Deprecated(since = "6.2", forRemoval = true)
598637
public B transform(Object service, @Nullable String methodName,
599638
@Nullable Consumer<GenericEndpointSpec<MessageTransformingHandler>> endpointConfigurer) {
600639

@@ -617,12 +656,18 @@ public B transform(Object service, @Nullable String methodName,
617656
* .transform(Scripts.script("classpath:myScript.py").variable("foo", bar()))
618657
* }
619658
* </pre>
659+
* Shortcut for:
660+
* <pre class="code">
661+
* {@code
662+
* .transformWith((transformerSpec) -> transformerSpec.processor(messageProcessorSpec))
663+
* }
664+
* </pre>
620665
* @param messageProcessorSpec the {@link MessageProcessorSpec} to use.
621666
* @return the current {@link BaseIntegrationFlowDefinition}.
622667
* @see MethodInvokingTransformer
623668
*/
624669
public B transform(MessageProcessorSpec<?> messageProcessorSpec) {
625-
return transform(messageProcessorSpec, (Consumer<GenericEndpointSpec<MessageTransformingHandler>>) null);
670+
return transformWith((transformerSpec) -> transformerSpec.processor(messageProcessorSpec));
626671
}
627672

628673
/**
@@ -638,8 +683,10 @@ public B transform(MessageProcessorSpec<?> messageProcessorSpec) {
638683
* @param messageProcessorSpec the {@link MessageProcessorSpec} to use.
639684
* @param endpointConfigurer the {@link Consumer} to provide integration endpoint options.
640685
* @return the current {@link BaseIntegrationFlowDefinition}.
686+
* @deprecated since 6.2 in favor of {@link #transformWith(Consumer)}.
641687
* @see MethodInvokingTransformer
642688
*/
689+
@Deprecated(since = "6.2", forRemoval = true)
643690
public B transform(MessageProcessorSpec<?> messageProcessorSpec,
644691
@Nullable Consumer<GenericEndpointSpec<MessageTransformingHandler>> endpointConfigurer) {
645692

@@ -679,7 +726,8 @@ public <P> B convert(Class<P> payloadType) {
679726
* @see LambdaMessageProcessor
680727
*/
681728
public <P, T> B transform(@Nullable Class<P> expectedType, GenericTransformer<P, T> genericTransformer) {
682-
return transform(expectedType, genericTransformer, null);
729+
return transformWith((transformerSpec) ->
730+
transformerSpec.transformer(genericTransformer).expectedType(expectedType));
683731
}
684732

685733
/**
@@ -714,10 +762,12 @@ public <P> B convert(Class<P> payloadType,
714762
* @param <P> the payload type - 'transform from', or {@code Message.class}.
715763
* @param <T> the target type - 'transform to'.
716764
* @return the current {@link BaseIntegrationFlowDefinition}.
765+
* @deprecated since 6.2 in favor of {@link #transformWith(Consumer)}
717766
* @see MethodInvokingTransformer
718767
* @see LambdaMessageProcessor
719768
* @see GenericEndpointSpec
720769
*/
770+
@Deprecated(since = "6.2", forRemoval = true)
721771
public <P, T> B transform(@Nullable Class<P> expectedType, GenericTransformer<P, T> genericTransformer,
722772
@Nullable Consumer<GenericEndpointSpec<MessageTransformingHandler>> endpointConfigurer) {
723773

@@ -730,6 +780,16 @@ public <P, T> B transform(@Nullable Class<P> expectedType, GenericTransformer<P,
730780
.handle(new MessageTransformingHandler(transformer), endpointConfigurer);
731781
}
732782

783+
/**
784+
* Populate a {@link MessageTransformingHandler} into the endpoint with provided {@link TransformerEndpointSpec} options.
785+
* One of the 'expression', 'ref', 'refName', 'processor' or 'function' must be provided.
786+
* @return the current {@link BaseIntegrationFlowDefinition}.
787+
* @since 6.2
788+
*/
789+
public B transformWith(Consumer<TransformerEndpointSpec> transformerConfigurer) {
790+
return register(new TransformerEndpointSpec(), transformerConfigurer);
791+
}
792+
733793
/**
734794
* Populate a {@link MessageFilter} with {@link MessageSelector} for the provided SpEL expression.
735795
* @param expression the SpEL expression.
@@ -2787,7 +2847,7 @@ protected <T> Publisher<Message<T>> toReactivePublisher(boolean autoStartOnSubsc
27872847
}
27882848

27892849
protected <S extends ConsumerEndpointSpec<? super S, ? extends MessageHandler>> B register(S endpointSpec,
2790-
@Nullable Consumer<S> endpointConfigurer) {
2850+
@Nullable Consumer<? super S> endpointConfigurer) {
27912851

27922852
if (endpointConfigurer != null) {
27932853
endpointConfigurer.accept(endpointSpec);

spring-integration-core/src/main/java/org/springframework/integration/dsl/IntegrationFlowDefinition.java

+15-6
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ public abstract class IntegrationFlowDefinition<B extends IntegrationFlowDefinit
5050
* Populate the {@link MessageTransformingHandler} instance for the provided
5151
* {@link GenericTransformer}. Use {@link #transform(Class, GenericTransformer)} if
5252
* you need to access the entire message.
53+
* Shortcut for:
54+
* <pre class="code">
55+
* {@code
56+
* .transformWith((transformerSpec) -> transformerSpec.function(genericTransformer))
57+
* }
58+
* </pre>
5359
* @param genericTransformer the {@link GenericTransformer} to populate.
5460
* @param <S> the source type - 'transform from'.
5561
* @param <T> the target type - 'transform to'.
@@ -58,26 +64,29 @@ public abstract class IntegrationFlowDefinition<B extends IntegrationFlowDefinit
5864
* @see org.springframework.integration.handler.LambdaMessageProcessor
5965
*/
6066
public <S, T> B transform(GenericTransformer<S, T> genericTransformer) {
61-
return transform(null, genericTransformer);
67+
return transformWith((transformerSpec) -> transformerSpec.transformer(genericTransformer));
6268
}
6369

6470

6571
/**
6672
* Populate the {@link MessageTransformingHandler} instance for the provided
6773
* {@link GenericTransformer}. In addition, accept options for the integration endpoint
6874
* using {@link GenericEndpointSpec}. Use
69-
* {@link #transform(Class, GenericTransformer, Consumer)} if you need to access the
70-
* entire message.
75+
* {@code .transform((transformerSpec) -> transformerSpec.function(genericTransformer).expectedType(Message.class))}
76+
* if you need to access the entire message.
7177
* @param genericTransformer the {@link GenericTransformer} to populate.
7278
* @param endpointConfigurer the {@link Consumer} to provide integration endpoint
7379
* options.
7480
* @param <S> the source type - 'transform from'.
7581
* @param <T> the target type - 'transform to'.
7682
* @return the current {@link IntegrationFlowDefinition}.
83+
* @deprecated since 6.2 in favor of {@link #transformWith(Consumer)}
7784
* @see org.springframework.integration.transformer.MethodInvokingTransformer
7885
* @see org.springframework.integration.handler.LambdaMessageProcessor
7986
* @see GenericEndpointSpec
8087
*/
88+
@Deprecated(since = "6.2", forRemoval = true)
89+
@SuppressWarnings("removal")
8190
public <S, T> B transform(GenericTransformer<S, T> genericTransformer,
8291
Consumer<GenericEndpointSpec<MessageTransformingHandler>> endpointConfigurer) {
8392

@@ -108,7 +117,7 @@ public <P> B filter(GenericSelector<P> genericSelector) {
108117
* Populate a {@link org.springframework.integration.filter.MessageFilter}
109118
* with {@link org.springframework.integration.filter.MethodInvokingSelector}
110119
* for the provided {@link GenericSelector}.
111-
* In addition accept options for the integration endpoint using {@link FilterEndpointSpec}.
120+
* In addition, accept options for the integration endpoint using {@link FilterEndpointSpec}.
112121
* Typically used with a Java 8 Lambda expression:
113122
* <pre class="code">
114123
* {@code
@@ -152,7 +161,7 @@ public <P> B handle(GenericHandler<P> handler) {
152161
* Populate a {@link ServiceActivatingHandler} for the
153162
* {@link org.springframework.integration.handler.MethodInvokingMessageProcessor}
154163
* to invoke the provided {@link GenericHandler} at runtime.
155-
* In addition accept options for the integration endpoint using {@link GenericEndpointSpec}.
164+
* In addition, accept options for the integration endpoint using {@link GenericEndpointSpec}.
156165
* Typically used with a Java 8 Lambda expression:
157166
* <pre class="code">
158167
* {@code
@@ -177,7 +186,7 @@ public <P> B handle(GenericHandler<P> handler,
177186
/**
178187
* Populate the {@link MethodInvokingSplitter} to evaluate the provided
179188
* {@link Function} at runtime.
180-
* In addition accept options for the integration endpoint using {@link GenericEndpointSpec}.
189+
* In addition, accept options for the integration endpoint using {@link GenericEndpointSpec}.
181190
* Typically used with a Java 8 Lambda expression:
182191
* <pre class="code">
183192
* {@code

0 commit comments

Comments
 (0)