Skip to content

Commit 3849d6a

Browse files
committed
Fix Kotlin DSL inconsistency & ambiguity
1 parent e0660f9 commit 3849d6a

File tree

5 files changed

+211
-48
lines changed

5 files changed

+211
-48
lines changed

spring-integration-core/src/main/kotlin/org/springframework/integration/dsl/KotlinConsumerEndpointSpec.kt

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 the original author or authors.
2+
* Copyright 2023-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -37,75 +37,74 @@ import reactor.core.publisher.Mono
3737
*
3838
* @since 5.5.19
3939
*/
40-
abstract class KotlinConsumerEndpointSpec<S : ConsumerEndpointSpec<S, H>, H : MessageHandler>(open val delegate: S)
41-
: ConsumerEndpointSpec<S, H>(delegate.handler) {
40+
abstract class KotlinConsumerEndpointSpec<S : ConsumerEndpointSpec<S, H>, H : MessageHandler>(open val delegate: S) {
4241

43-
override fun phase(phase: Int): S {
44-
return this.delegate.phase(phase)
42+
fun phase(phase: Int) {
43+
this.delegate.phase(phase)
4544
}
4645

47-
override fun autoStartup(autoStartup: Boolean): S {
48-
return this.delegate.autoStartup(autoStartup)
46+
fun autoStartup(autoStartup: Boolean) {
47+
this.delegate.autoStartup(autoStartup)
4948
}
5049

51-
override fun poller(pollerMetadata: PollerMetadata): S {
52-
return this.delegate.poller(pollerMetadata)
50+
fun poller(pollerMetadata: PollerMetadata) {
51+
this.delegate.poller(pollerMetadata)
5352
}
5453

55-
override fun reactive(): S {
56-
return this.delegate.reactive()
54+
fun reactive() {
55+
this.delegate.reactive()
5756
}
5857

5958
fun reactive(reactiveCustomizer: (Flux<Message<*>>) -> Publisher<Message<*>>) {
6059
this.delegate.reactive(reactiveCustomizer)
6160
}
6261

63-
override fun role(role: String): S {
64-
return this.delegate.role(role)
62+
fun role(role: String) {
63+
this.delegate.role(role)
6564
}
6665

67-
override fun taskScheduler(taskScheduler: TaskScheduler): S {
68-
return this.delegate.taskScheduler(taskScheduler)
66+
fun taskScheduler(taskScheduler: TaskScheduler) {
67+
this.delegate.taskScheduler(taskScheduler)
6968
}
7069

71-
override fun handleMessageAdvice(vararg interceptors: MethodInterceptor?): S {
72-
return this.delegate.handleMessageAdvice(*interceptors)
70+
fun handleMessageAdvice(vararg interceptors: MethodInterceptor?) {
71+
this.delegate.handleMessageAdvice(*interceptors)
7372
}
7473

75-
override fun advice(vararg advice: Advice?): S {
76-
return this.delegate.advice(*advice)
74+
fun advice(vararg advice: Advice?) {
75+
this.delegate.advice(*advice)
7776
}
7877

79-
override fun transactional(transactionManager: TransactionManager): S {
80-
return this.delegate.transactional(transactionManager)
78+
fun transactional(transactionManager: TransactionManager) {
79+
this.delegate.transactional(transactionManager)
8180
}
8281

83-
override fun transactional(transactionManager: TransactionManager, handleMessageAdvice: Boolean): S {
84-
return this.delegate.transactional(transactionManager, handleMessageAdvice)
82+
fun transactional(transactionManager: TransactionManager, handleMessageAdvice: Boolean) {
83+
this.delegate.transactional(transactionManager, handleMessageAdvice)
8584
}
8685

87-
override fun transactional(transactionInterceptor: TransactionInterceptor): S {
88-
return this.delegate.transactional(transactionInterceptor)
86+
fun transactional(transactionInterceptor: TransactionInterceptor) {
87+
this.delegate.transactional(transactionInterceptor)
8988
}
9089

91-
override fun transactional(): S {
92-
return this.delegate.transactional()
90+
fun transactional() {
91+
this.delegate.transactional()
9392
}
9493

95-
override fun transactional(handleMessageAdvice: Boolean): S {
96-
return this.delegate.transactional(handleMessageAdvice)
94+
fun transactional(handleMessageAdvice: Boolean) {
95+
this.delegate.transactional(handleMessageAdvice)
9796
}
9897

9998
fun <T : Any?, V : Any?> customizeMonoReply(replyCustomizer: (Message<*>, Mono<T>) -> Publisher<V>) {
10099
this.delegate.customizeMonoReply(replyCustomizer)
101100
}
102101

103-
override fun id(id: String?): S {
104-
return this.delegate.id(id)
102+
fun id(id: String?) {
103+
this.delegate.id(id)
105104
}
106105

107-
override fun poller(pollerMetadataSpec: PollerSpec): S {
108-
return this.delegate.poller(pollerMetadataSpec)
106+
fun poller(pollerMetadataSpec: PollerSpec) {
107+
this.delegate.poller(pollerMetadataSpec)
109108
}
110109

111110
fun poller(pollers: (PollerFactory) -> PollerSpec) {

spring-integration-core/src/main/kotlin/org/springframework/integration/dsl/KotlinIntegrationFlowDefinition.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ class KotlinIntegrationFlowDefinition(@PublishedApi internal val delegate: Integ
9393
* Populate a transformer endpoint.
9494
* @since 6.2
9595
*/
96-
fun transformWith(configurer: KotlinTransformerEndpointSpec.() -> Unit) {
97-
this.delegate.register(KotlinTransformerEndpointSpec(), configurer)
96+
fun transformWith(transformerConfigurer: KotlinTransformerEndpointSpec.() -> Unit) {
97+
this.delegate.transformWith { transformerConfigurer(KotlinTransformerEndpointSpec(it)) }
9898
}
9999

100100
/**
@@ -109,8 +109,8 @@ class KotlinIntegrationFlowDefinition(@PublishedApi internal val delegate: Integ
109109
* Populate a splitter endpoint.
110110
* @since 6.2
111111
*/
112-
fun splitWith(configurer: KotlinSplitterSpec.() -> Unit) {
113-
this.delegate.register(KotlinSplitterSpec(), configurer)
112+
fun splitWith(splitterConfigurer: KotlinSplitterSpec.() -> Unit) {
113+
this.delegate.splitWith { splitterConfigurer(KotlinSplitterSpec(it)) }
114114
}
115115

116116
/**

spring-integration-core/src/main/kotlin/org/springframework/integration/dsl/KotlinSplitterSpec.kt

Lines changed: 104 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 the original author or authors.
2+
* Copyright 2023-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,14 +16,23 @@
1616

1717
package org.springframework.integration.dsl
1818

19+
import org.springframework.expression.Expression
20+
import org.springframework.integration.handler.BeanNameMessageProcessor
21+
import org.springframework.integration.splitter.AbstractMessageSplitter
22+
import org.springframework.integration.splitter.DefaultMessageSplitter
23+
import org.springframework.integration.splitter.ExpressionEvaluatingSplitter
24+
import org.springframework.integration.splitter.MethodInvokingSplitter
25+
import org.springframework.messaging.MessageChannel
26+
1927
/**
2028
* A [SplitterSpec] wrapped for Kotlin DSL.
2129
*
2230
* @author Artem Bilan
2331
*
2432
* @since 6.2
2533
*/
26-
class KotlinSplitterSpec : SplitterSpec() {
34+
class KotlinSplitterSpec(override val delegate: SplitterSpec)
35+
: KotlinConsumerEndpointSpec<SplitterSpec, AbstractMessageSplitter>(delegate) {
2736

2837
/**
2938
* Provide a Kotlin function as a direct delegate for
@@ -32,12 +41,102 @@ class KotlinSplitterSpec : SplitterSpec() {
3241
* @param <P> the input type.
3342
*/
3443
inline fun <reified P> function(crossinline function: (P) -> Any) {
35-
expectedType(P::class.java)
36-
function<P> { function(it) }
44+
this.delegate.expectedType(P::class.java)
45+
this.delegate.function<P> { function(it) }
46+
}
47+
48+
/**
49+
* Set delimiters to tokenize String values. The default is
50+
* `null` indicating that no tokenizing should occur.
51+
* If delimiters are provided, they will be applied to any String payload.
52+
* Only applied if provided `splitter` is instance of [DefaultMessageSplitter].
53+
* @param delimiters The delimiters.
54+
*/
55+
fun delimiters(delimiters: String) {
56+
this.delegate.delimiters(delimiters)
57+
}
58+
59+
/**
60+
* Provide an expression to use an [ExpressionEvaluatingSplitter] for the target handler.
61+
* @param expression the SpEL expression to use.
62+
*/
63+
fun expression(expression: String){
64+
this.delegate.expression(expression)
65+
}
66+
67+
/**
68+
* Provide an expression to use an [ExpressionEvaluatingSplitter] for the target handler.
69+
* @param expression the SpEL expression to use.
70+
*/
71+
fun expression(expression: Expression) {
72+
this.delegate.expression(expression)
73+
}
74+
75+
/**
76+
* Provide a service to use a [MethodInvokingSplitter] for the target handler.
77+
* This option can be set to an [AbstractMessageSplitter] implementation,
78+
* a [MessageHandlerSpec] providing an [AbstractMessageSplitter],
79+
* or [MessageProcessorSpec].
80+
* @param ref the service to call as a splitter POJO.
81+
*/
82+
fun ref(ref: Any) {
83+
this.delegate.ref(ref)
3784
}
3885

86+
/**
87+
* Provide a bean name to use a [MethodInvokingSplitter]
88+
* (based on [BeanNameMessageProcessor]) for the target handler.
89+
* @param refName the bean name for service to call as a splitter POJO.
90+
*/
91+
fun refName(refName: String) {
92+
this.delegate.refName(refName)
93+
}
94+
95+
/**
96+
* Provide a service method name to call. Optional.
97+
* Use only together with [.ref] or [.refName].
98+
* @param method the service method name to call.
99+
*/
100+
fun method(method: String?) {
101+
this.delegate.method(method)
102+
}
103+
104+
/**
105+
* Set the applySequence flag to the specified value. Defaults to `true`.
106+
* @param applySequence the applySequence.
107+
*/
108+
fun applySequence(applySequence: Boolean) {
109+
this.delegate.applySequence(applySequence)
110+
}
111+
112+
/**
113+
* Specify a channel where rejected Messages should be sent. If the discard
114+
* channel is null (the default), rejected Messages will be dropped.
115+
* A "Rejected Message" means that split function has returned an empty result (but not null):
116+
* no items to iterate for sending.
117+
* @param discardChannel The discard channel.
118+
*/
119+
fun discardChannel(discardChannel: MessageChannel) {
120+
this.delegate.discardChannel(discardChannel)
121+
}
122+
123+
/**
124+
* Specify a channel bean name where rejected Messages should be sent. If the discard
125+
* channel is null (the default), rejected Messages will be dropped.
126+
* A "Rejected Message" means that split function has returned an empty result (but not null):
127+
* no items to iterate for sending.
128+
* @param discardChannelName The discard channel bean name.
129+
*/
130+
fun discardChannel(discardChannelName: String) {
131+
this.delegate.discardChannel(discardChannelName)
132+
}
133+
134+
/**
135+
* Configure a subflow to run for discarded messages instead of a [discardChannel].
136+
* @param discardFlow the discard flow.
137+
*/
39138
fun discardFlow(discardFlow: KotlinIntegrationFlowDefinition.() -> Unit) {
40-
discardFlow {definition -> discardFlow(KotlinIntegrationFlowDefinition(definition)) }
139+
this.delegate.discardFlow {definition -> discardFlow(KotlinIntegrationFlowDefinition(definition)) }
41140
}
42141

43142
}

spring-integration-core/src/main/kotlin/org/springframework/integration/dsl/KotlinTransformerEndpointSpec.kt

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 the original author or authors.
2+
* Copyright 2023-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,7 +16,12 @@
1616

1717
package org.springframework.integration.dsl
1818

19+
import org.springframework.expression.Expression
20+
import org.springframework.integration.core.GenericTransformer
21+
import org.springframework.integration.handler.BeanNameMessageProcessor
22+
import org.springframework.integration.transformer.ExpressionEvaluatingTransformer
1923
import org.springframework.integration.transformer.MessageTransformingHandler
24+
import org.springframework.integration.transformer.MethodInvokingTransformer
2025

2126
/**
2227
* A [TransformerEndpointSpec] wrapped for Kotlin DSL.
@@ -27,16 +32,77 @@ import org.springframework.integration.transformer.MessageTransformingHandler
2732
*
2833
* @since 6.2
2934
*/
30-
class KotlinTransformerEndpointSpec : TransformerEndpointSpec() {
35+
class KotlinTransformerEndpointSpec(override val delegate: TransformerEndpointSpec)
36+
: KotlinConsumerEndpointSpec<TransformerEndpointSpec, MessageTransformingHandler>(delegate) {
3137

3238
/**
3339
* Provide a Kotlin function as a direct delegate for [MessageTransformingHandler].
3440
* @param function the function instance to use.
3541
* @param <P> the input type.
3642
*/
3743
inline fun <reified P> transformer(crossinline function: (P) -> Any) {
38-
expectedType(P::class.java)
39-
transformer<P, Any> { function(it) }
44+
this.delegate.expectedType(P::class.java)
45+
this.delegate.transformer<P, Any> { function(it) }
46+
}
47+
48+
/**
49+
* Provide a [GenericTransformer] as a direct delegate for [MessageTransformingHandler].
50+
* @param transformer the [GenericTransformer] instance to use.
51+
* @param <P> the input type.
52+
* @param <T> the output type.
53+
*/
54+
fun <P, T> transformer(transformer: GenericTransformer<P, T>) {
55+
this.delegate.transformer(transformer)
56+
}
57+
58+
/**
59+
* Provide an expression to use an [ExpressionEvaluatingTransformer] for the target handler.
60+
* @param expression the SpEL expression to use.
61+
*/
62+
fun expression(expression: String) {
63+
this.delegate.expression(expression)
64+
}
65+
66+
/**
67+
* Provide an expression to use an [ExpressionEvaluatingTransformer] for the target handler.
68+
* @param expression the SpEL expression to use.
69+
*/
70+
fun expression(expression: Expression) {
71+
this.delegate.expression(expression)
72+
}
73+
74+
/**
75+
* Provide a service to use a [MethodInvokingTransformer] for the target handler.
76+
* @param ref the service to call as a transformer POJO.
77+
*/
78+
fun ref(ref: Any) {
79+
this.delegate.ref(ref)
80+
}
81+
82+
/**
83+
* Provide a bean name to use a [MethodInvokingTransformer]
84+
* (based on [BeanNameMessageProcessor]) for the target handler.
85+
* @param refName the bean name for service to call as a transformer POJO.
86+
*/
87+
fun refName(refName: String) {
88+
this.delegate.refName(refName)
89+
}
90+
91+
/**
92+
* Provide a service method name to call. Optional.
93+
* Use only together with [.ref] or [.refName].
94+
* @param method the service method name to call.
95+
*/
96+
fun method(method: String?) {
97+
this.delegate.method(method)
98+
}
99+
100+
/**
101+
* Provide a [MessageProcessorSpec] as a factory for [MethodInvokingTransformer] delegate.
102+
* @param processor the [MessageProcessorSpec] to use.
103+
*/
104+
fun processor(processor: MessageProcessorSpec<*>) {
105+
this.delegate.processor(processor)
40106
}
41107

42108
}

spring-integration-core/src/test/kotlin/org/springframework/integration/dsl/KotlinDslTests.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2023 the original author or authors.
2+
* Copyright 2020-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -214,7 +214,6 @@ class KotlinDslTests {
214214
.build()
215215
this.scatterGatherFlowInput.send(request)
216216
val bestQuoteMessage = replyChannel.receive(10000)
217-
assertThat(bestQuoteMessage).isNotNull()
218217
val payload = bestQuoteMessage!!.payload
219218
assertThat(payload).isInstanceOf(List::class.java).size().isGreaterThanOrEqualTo(1)
220219
}

0 commit comments

Comments
 (0)