From cab4d9e3417d54d93075ee418c392cdd0986a4ff Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Mon, 15 Feb 2021 16:12:12 +0100 Subject: [PATCH] GH-648 Fix Kotlin functions bootstrap Resolves #648 --- spring-cloud-function-kotlin/pom.xml | 15 +++++++++ ...tlinLambdaToFunctionAutoConfiguration.java | 23 +++++++------ ...onCatalogAutoConfigurationKotlinTests.java | 7 ++++ .../kotlin/KotlinLambdasConfiguration.kt | 15 ++++++--- .../cloud/function/kotlin/Person.kt | 33 +++++++++++++++++++ 5 files changed, 78 insertions(+), 15 deletions(-) create mode 100644 spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/Person.kt diff --git a/spring-cloud-function-kotlin/pom.xml b/spring-cloud-function-kotlin/pom.xml index ae57578f5..067674cbd 100644 --- a/spring-cloud-function-kotlin/pom.xml +++ b/spring-cloud-function-kotlin/pom.xml @@ -42,6 +42,14 @@ kotlin-maven-plugin org.jetbrains.kotlin 1.4.21 + + + -Xjsr305=strict + + + spring + + compile @@ -68,6 +76,13 @@ + + + org.jetbrains.kotlin + kotlin-maven-allopen + 1.4.21 + + org.apache.maven.plugins diff --git a/spring-cloud-function-kotlin/src/main/java/org/springframework/cloud/function/context/config/KotlinLambdaToFunctionAutoConfiguration.java b/spring-cloud-function-kotlin/src/main/java/org/springframework/cloud/function/context/config/KotlinLambdaToFunctionAutoConfiguration.java index 739dc0420..5e9371007 100644 --- a/spring-cloud-function-kotlin/src/main/java/org/springframework/cloud/function/context/config/KotlinLambdaToFunctionAutoConfiguration.java +++ b/spring-cloud-function-kotlin/src/main/java/org/springframework/cloud/function/context/config/KotlinLambdaToFunctionAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2021 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. @@ -36,6 +36,7 @@ import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; @@ -62,7 +63,6 @@ public class KotlinLambdaToFunctionAutoConfiguration { protected final Log logger = LogFactory.getLog(getClass()); - /** * Will transform all discovered Kotlin's Function lambdas to java * Supplier, Function and Consumer, retaining the original Kotlin type @@ -71,7 +71,7 @@ public class KotlinLambdaToFunctionAutoConfiguration { * @return the bean factory post processor */ @Bean - public BeanFactoryPostProcessor kotlinToFunctionTransformer() { + public BeanFactoryPostProcessor kotlinToFunctionTransformerOld() { return new BeanFactoryPostProcessor() { @Override @@ -82,14 +82,17 @@ public class KotlinLambdaToFunctionAutoConfiguration { for (String beanDefinitionName : beanDefinitionNames) { BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanDefinitionName); - ResolvableType rt = beanDefinition.getResolvableType(); - if (rt.getType().getTypeName().startsWith("kotlin.jvm.functions.Function")) { - RootBeanDefinition cbd = new RootBeanDefinition(KotlinFunctionWrapper.class); - ConstructorArgumentValues ca = new ConstructorArgumentValues(); - ca.addGenericArgumentValue(beanDefinition); - cbd.setConstructorArgumentValues(ca); - ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition(beanDefinitionName + FunctionRegistration.REGISTRATION_NAME_SUFFIX, cbd); + if (beanDefinition instanceof AnnotatedBeanDefinition && ((AnnotatedBeanDefinition) beanDefinition).getFactoryMethodMetadata() != null) { + String typeName = ((AnnotatedBeanDefinition) beanDefinition).getFactoryMethodMetadata().getReturnTypeName(); + if (typeName.startsWith("kotlin.jvm.functions.Function")) { + RootBeanDefinition cbd = new RootBeanDefinition(KotlinFunctionWrapper.class); + ConstructorArgumentValues ca = new ConstructorArgumentValues(); + ca.addGenericArgumentValue(beanDefinition); + cbd.setConstructorArgumentValues(ca); + ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition(beanDefinitionName + FunctionRegistration.REGISTRATION_NAME_SUFFIX, cbd); + } } + } } }; diff --git a/spring-cloud-function-kotlin/src/test/java/org/springframework/cloud/function/kotlin/ContextFunctionCatalogAutoConfigurationKotlinTests.java b/spring-cloud-function-kotlin/src/test/java/org/springframework/cloud/function/kotlin/ContextFunctionCatalogAutoConfigurationKotlinTests.java index ac2819dc9..6198842d0 100644 --- a/spring-cloud-function-kotlin/src/test/java/org/springframework/cloud/function/kotlin/ContextFunctionCatalogAutoConfigurationKotlinTests.java +++ b/spring-cloud-function-kotlin/src/test/java/org/springframework/cloud/function/kotlin/ContextFunctionCatalogAutoConfigurationKotlinTests.java @@ -76,6 +76,13 @@ public class ContextFunctionCatalogAutoConfigurationKotlinTests { assertThat(functionType.getRawType().getTypeName()).isEqualTo(Supplier.class.getName()); assertThat(functionType.getActualTypeArguments().length).isEqualTo(1); assertThat(functionType.getActualTypeArguments()[0].getTypeName()).isEqualTo(String.class.getName()); + + function = this.context.getBean("kotlinPojoFunction"); + functionType = (ParameterizedType) FunctionTypeUtils.discoverFunctionType(function, "kotlinPojoFunction", this.context); + assertThat(functionType.getRawType().getTypeName()).isEqualTo(Function.class.getName()); + assertThat(functionType.getActualTypeArguments().length).isEqualTo(2); + assertThat(functionType.getActualTypeArguments()[0].getTypeName()).isEqualTo(Person.class.getName()); + assertThat(functionType.getActualTypeArguments()[1].getTypeName()).isEqualTo(String.class.getName()); } @Test diff --git a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinLambdasConfiguration.kt b/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinLambdasConfiguration.kt index a8271a1e7..6c9063f3c 100644 --- a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinLambdasConfiguration.kt +++ b/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/KotlinLambdasConfiguration.kt @@ -27,24 +27,29 @@ import java.util.function.Function */ @EnableAutoConfiguration @Configuration -open class KotlinLambdasConfiguration { +class KotlinLambdasConfiguration { @Bean - open fun kotlinFunction(): (String) -> String { + fun kotlinFunction(): (String) -> String { return { it.toUpperCase() } } + + @Bean + fun kotlinPojoFunction(): (Person) -> String { + return { it.name.toString()} + } @Bean - open fun kotlinConsumer(): (String) -> Unit { + fun kotlinConsumer(): (String) -> Unit { return { println(it) } } @Bean - open fun kotlinSupplier(): () -> String { + fun kotlinSupplier(): () -> String { return { "Hello" } } @Bean - open fun javaFunction(): Function { + fun javaFunction(): Function { return Function { x -> x } } } diff --git a/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/Person.kt b/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/Person.kt new file mode 100644 index 000000000..130b07f5a --- /dev/null +++ b/spring-cloud-function-kotlin/src/test/kotlin/org/springframework/cloud/function/kotlin/Person.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2012-2021 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.function.kotlin + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import java.util.function.Function + +/** + * @author Oleg Zhurakousky + * + */ +class Person { + + var name:String? = null; + + +}