Skip to content

Commit 7db4efe

Browse files
AdrienAdrien
authored andcommitted
Feat: Enhance Kotlin arity handling in function context
This commit refactors the `spring-cloud-function-context` to comprehensively handle all combinations of possible declarations for Kotlin functions, consumers, and suppliers. This improves the framework's ability to correctly interpret and manage different Kotlin functional styles. Signed-off-by: Adrien <[email protected]>
1 parent 36d1947 commit 7db4efe

26 files changed

+1830
-349
lines changed

spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/FunctionRegistration.java

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
import org.springframework.beans.factory.BeanNameAware;
3333
import org.springframework.cloud.function.context.catalog.FunctionTypeUtils;
34-
import org.springframework.cloud.function.context.config.KotlinLambdaToFunctionAutoConfiguration;
34+
import org.springframework.cloud.function.context.wrapper.KotlinFunctionWrapper;
3535
import org.springframework.core.KotlinDetector;
3636
import org.springframework.util.Assert;
3737
import org.springframework.util.CollectionUtils;
@@ -118,7 +118,7 @@ public FunctionRegistration<T> properties(Map<String, String> properties) {
118118

119119
public FunctionRegistration<T> type(Type type) {
120120
this.type = type;
121-
if (KotlinDetector.isKotlinPresent() && this.target instanceof KotlinLambdaToFunctionAutoConfiguration.KotlinFunctionWrapper) {
121+
if (KotlinDetector.isKotlinPresent() && this.target instanceof KotlinFunctionWrapper) {
122122
return this;
123123
}
124124
Type discoveredFunctionType = type; //FunctionTypeUtils.discoverFunctionTypeFromClass(this.target.getClass());
@@ -174,15 +174,6 @@ public FunctionRegistration<T> names(String... names) {
174174
return this.names(Arrays.asList(names));
175175
}
176176

177-
/**
178-
* Transforms (wraps) function identified by the 'target' to its {@code Flux}
179-
* equivalent unless it already is. For example, {@code Function<String, String>}
180-
* becomes {@code Function<Flux<String>, Flux<String>>}
181-
* @param <S> the expected target type of the function (e.g., FluxFunction)
182-
* @return {@code FunctionRegistration} with the appropriately wrapped target.
183-
*
184-
*/
185-
186177
@Override
187178
public void setBeanName(String name) {
188179
if (CollectionUtils.isEmpty(this.names)) {

spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/BeanFactoryAwareFunctionRegistry.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,12 @@
3636
import org.springframework.beans.BeansException;
3737
import org.springframework.beans.factory.BeanFactory;
3838
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
39+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
3940
import org.springframework.cloud.function.context.FunctionProperties;
4041
import org.springframework.cloud.function.context.FunctionRegistration;
4142
import org.springframework.cloud.function.context.FunctionRegistry;
4243
import org.springframework.cloud.function.context.config.FunctionContextUtils;
43-
import org.springframework.cloud.function.context.config.KotlinLambdaToFunctionAutoConfiguration;
44+
import org.springframework.cloud.function.context.config.KotlinLambdaToFunctionFactory;
4445
import org.springframework.cloud.function.context.config.RoutingFunction;
4546
import org.springframework.cloud.function.core.FunctionInvocationHelper;
4647
import org.springframework.cloud.function.json.JsonMapper;
@@ -120,7 +121,8 @@ public <T> T lookup(Class<?> type, String functionDefinition, String... expected
120121
functionDefinition = StringUtils.hasText(functionDefinition)
121122
? functionDefinition
122123
: this.applicationContext.getEnvironment().getProperty(FunctionProperties.FUNCTION_DEFINITION, "");
123-
if (!this.applicationContext.containsBean(functionDefinition) || !KotlinUtils.isKotlinType(this.applicationContext.getBean(functionDefinition))) {
124+
125+
if (!this.applicationContext.containsBean(functionDefinition) || !isKotlinType(functionDefinition)) {
124126
functionDefinition = this.normalizeFunctionDefinition(functionDefinition);
125127
}
126128
if (!isFunctionDefinitionEligible(functionDefinition)) {
@@ -160,12 +162,9 @@ public <T> T lookup(Class<?> type, String functionDefinition, String... expected
160162
else if (functionCandidate instanceof BiFunction || functionCandidate instanceof BiConsumer) {
161163
functionRegistration = this.registerMessagingBiFunction(functionCandidate, functionName);
162164
}
163-
else if (KotlinUtils.isKotlinType(functionCandidate)) {
164-
KotlinLambdaToFunctionAutoConfiguration.KotlinFunctionWrapper wrapper =
165-
new KotlinLambdaToFunctionAutoConfiguration.KotlinFunctionWrapper(functionCandidate);
166-
wrapper.setName(functionName);
167-
wrapper.setBeanFactory(this.applicationContext.getBeanFactory());
168-
functionRegistration = wrapper.getFunctionRegistration();
165+
else if (isKotlinType(functionName, functionCandidate)) {
166+
KotlinLambdaToFunctionFactory kotlinFactory = new KotlinLambdaToFunctionFactory(functionCandidate, this.applicationContext.getBeanFactory());
167+
functionRegistration = kotlinFactory.getFunctionRegistration(functionName);
169168
}
170169
else if (this.isFunctionPojo(functionCandidate, functionName)) {
171170
Method functionalMethod = FunctionTypeUtils.discoverFunctionalMethod(functionCandidate.getClass());
@@ -203,6 +202,17 @@ else if (this.isSpecialFunctionRegistration(functionNames, functionName)) {
203202
return (T) function;
204203
}
205204

205+
private boolean isKotlinType(String functionDefinition) {
206+
Object fonctionBean = this.applicationContext.getBean(functionDefinition);
207+
return isKotlinType(functionDefinition, fonctionBean);
208+
}
209+
210+
private boolean isKotlinType(String functionDefinition, Object fonctionBean) {
211+
ConfigurableListableBeanFactory beanFactory = this.applicationContext.getBeanFactory();
212+
Type functionType = FunctionContextUtils.findType(functionDefinition, beanFactory);
213+
return KotlinUtils.isKotlinType(fonctionBean, functionType);
214+
}
215+
206216
@SuppressWarnings({ "rawtypes", "unchecked" })
207217
private FunctionRegistration registerMessagingBiFunction(Object userFunction, String functionName) {
208218
Type biFunctionType = FunctionContextUtils.findType(this.applicationContext.getBeanFactory(), functionName);

spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/catalog/FunctionTypeUtils.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import com.fasterxml.jackson.databind.JsonNode;
4949
import kotlin.jvm.functions.Function0;
5050
import kotlin.jvm.functions.Function1;
51+
import kotlin.jvm.functions.Function2;
5152
import org.apache.commons.logging.Log;
5253
import org.apache.commons.logging.LogFactory;
5354
import org.reactivestreams.Publisher;
@@ -234,6 +235,10 @@ else if (Function0.class.isAssignableFrom(functionalClass)) {
234235
ResolvableType kotlinType = ResolvableType.forClass(functionalClass).as(Function0.class);
235236
return GenericTypeResolver.resolveType(kotlinType.getType(), functionalClass);
236237
}
238+
else if (Function2.class.isAssignableFrom(functionalClass)) {
239+
ResolvableType kotlinType = ResolvableType.forClass(functionalClass).as(Function2.class);
240+
return GenericTypeResolver.resolveType(kotlinType.getType(), functionalClass);
241+
}
237242
}
238243
Type typeToReturn = null;
239244
if (Function.class.isAssignableFrom(functionalClass)) {

spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/KotlinLambdaToFunctionAutoConfiguration.java

Lines changed: 0 additions & 247 deletions
This file was deleted.

0 commit comments

Comments
 (0)