From 0fb64f1762f6eed0de4c53ebe98c18d57b3bbfe6 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Mon, 13 Sep 2021 13:04:57 -0400 Subject: [PATCH] Upgrade to Kotlin 1.5 * To align with the rest of Spring portfolio, based on Spring Framework 5.3.x generation, it is better to upgrade to the Kotlin version supported by SF * Fix `ClassUtils.isLambda()` to treat `$inlined$` classes as Kotlin lambdas and let Java DSL to delegate to the `LambdaMessageProcessor` for better expected type handling. Looks like Kotlin does not carry type info in its lambdas anymore (at least for functions). * Add `-parameters` to the compiler args for possible method argument names discovery. Essentially realign with the rest of portfolio * Fix Kotlin tests for deprecated API --- build.gradle | 9 +++++---- .../org/springframework/integration/util/ClassUtils.java | 9 +++++---- .../springframework/integration/dsl/KotlinDslTests.kt | 4 ++-- .../integration/function/FunctionsTests.kt | 6 +++--- .../kotlin/file/aggregator/KotlinFileAggregatorTests.kt | 3 ++- .../integration/kafka/dsl/kotlin/KafkaDslKotlinTests.kt | 8 ++++---- 6 files changed, 21 insertions(+), 18 deletions(-) diff --git a/build.gradle b/build.gradle index 85d75855b4..166557e30f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlinVersion = '1.4.32' + ext.kotlinVersion = '1.5.30' repositories { mavenCentral() maven { url 'https://plugins.gradle.org/m2' } @@ -199,12 +199,13 @@ configure(javaProjects) { subproject -> compileTestJava { sourceCompatibility = 11 + targetCompatibility = 11 options.encoding = 'UTF-8' } compileKotlin { kotlinOptions { - languageVersion = '1.3' + apiVersion = '1.3' jvmTarget = '1.8' freeCompilerArgs = ['-Xjsr305=strict'] // allWarningsAsErrors = true TODO bring it back after upgrading to Kotlin 1.5 language version @@ -212,7 +213,7 @@ configure(javaProjects) { subproject -> } compileTestKotlin { kotlinOptions { - jvmTarget = '1.8' + jvmTarget = '11' } } @@ -263,7 +264,7 @@ configure(javaProjects) { subproject -> // enable all compiler warnings; individual projects may customize further ext.xLintArg = '-Xlint:all,-options,-processing' - [compileJava, compileTestJava]*.options*.compilerArgs = [xLintArg] + [compileJava, compileTestJava]*.options*.compilerArgs = [xLintArg, '-parameters'] task updateCopyrights { onlyIf { !System.getenv('GITHUB_ACTION') && !System.getenv('bamboo_buildKey') } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/util/ClassUtils.java b/spring-integration-core/src/main/java/org/springframework/integration/util/ClassUtils.java index 85dda3b067..974aff9eaa 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/util/ClassUtils.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/util/ClassUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-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. @@ -235,13 +235,14 @@ public abstract class ClassUtils { } /** - * Check if class is Java lambda. + * Check if class is Java or Kotlin lambda. * @param aClass the {@link Class} to check. - * @return true if class is a Java lambda. + * @return true if class is a Java or Kotlin lambda. * @since 5.2 */ public static boolean isLambda(Class aClass) { - return aClass.isSynthetic() && !aClass.isAnonymousClass() && !aClass.isLocalClass(); + return (aClass.isSynthetic() && !aClass.isAnonymousClass() && !aClass.isLocalClass()) + || aClass.getName().contains("$inlined$"); // for Kotlin lambdas } /** diff --git a/spring-integration-core/src/test/kotlin/org/springframework/integration/dsl/KotlinDslTests.kt b/spring-integration-core/src/test/kotlin/org/springframework/integration/dsl/KotlinDslTests.kt index df5f8643d8..cc55bf31db 100644 --- a/spring-integration-core/src/test/kotlin/org/springframework/integration/dsl/KotlinDslTests.kt +++ b/spring-integration-core/src/test/kotlin/org/springframework/integration/dsl/KotlinDslTests.kt @@ -245,7 +245,7 @@ class KotlinDslTests { fun functionFlow() = integrationFlow>({ beanName("functionGateway") }) { transform(Transformers.objectToString()) { id("objectToStringTransformer") } - transform { it.toUpperCase() } + transform { it.uppercase() } split> { it.payload } split({ it }) { id("splitterEndpoint") } resequence() @@ -312,7 +312,7 @@ class KotlinDslTests { channel { queue("wireTapChannel") } } delay("delayGroup") { defaultDelay(100) } - transform { it.toUpperCase() } + transform { it.uppercase() } } diff --git a/spring-integration-core/src/test/kotlin/org/springframework/integration/function/FunctionsTests.kt b/spring-integration-core/src/test/kotlin/org/springframework/integration/function/FunctionsTests.kt index bb19b26c4c..323b047e40 100644 --- a/spring-integration-core/src/test/kotlin/org/springframework/integration/function/FunctionsTests.kt +++ b/spring-integration-core/src/test/kotlin/org/springframework/integration/function/FunctionsTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-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. @@ -154,7 +154,7 @@ class FunctionsTests { @Bean @Transformer(inputChannel = "functionServiceChannel") fun kotlinFunction(): (String) -> String { - return { it.toUpperCase() } + return { it.uppercase() } } @Bean @@ -187,7 +187,7 @@ class FunctionsTests { @Bean fun monoFunctionGateway() = integrationFlow({ proxyDefaultMethods(true) }) { - handle({ p, _ -> Mono.just(p).map(String::toUpperCase) }) { async(true) } + handle({ p, _ -> Mono.just(p).map(String::uppercase) }) { async(true) } } } diff --git a/spring-integration-file/src/test/kotlin/org/springframework/integration/kotlin/file/aggregator/KotlinFileAggregatorTests.kt b/spring-integration-file/src/test/kotlin/org/springframework/integration/kotlin/file/aggregator/KotlinFileAggregatorTests.kt index 8878f6624e..aabc676625 100644 --- a/spring-integration-file/src/test/kotlin/org/springframework/integration/kotlin/file/aggregator/KotlinFileAggregatorTests.kt +++ b/spring-integration-file/src/test/kotlin/org/springframework/integration/kotlin/file/aggregator/KotlinFileAggregatorTests.kt @@ -42,6 +42,7 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig import org.springframework.util.FileCopyUtils import java.io.File import java.io.FileOutputStream +import java.util.* /** * @author Artem Bilan @@ -106,7 +107,7 @@ class KotlinFileAggregatorTests { split(Files.splitter().markers().firstLineAsHeader("firstLine")) channel { executor(taskExecutor) } filter({ it !is FileMarker }) { discardChannel("aggregatorChannel") } - transform(String::toUpperCase) + transform(String::uppercase) channel("aggregatorChannel") aggregate(FileAggregator()) channel { queue("resultChannel") } diff --git a/spring-integration-kafka/src/test/kotlin/org/springframework/integration/kafka/dsl/kotlin/KafkaDslKotlinTests.kt b/spring-integration-kafka/src/test/kotlin/org/springframework/integration/kafka/dsl/kotlin/KafkaDslKotlinTests.kt index 45f87141c6..975c4591ff 100644 --- a/spring-integration-kafka/src/test/kotlin/org/springframework/integration/kafka/dsl/kotlin/KafkaDslKotlinTests.kt +++ b/spring-integration-kafka/src/test/kotlin/org/springframework/integration/kafka/dsl/kotlin/KafkaDslKotlinTests.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-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. @@ -254,7 +254,7 @@ class KafkaDslKotlinTests { .retryTemplate(RetryTemplate()) .filterInRetry(true)) { filter>({ m -> (m.headers[KafkaHeaders.RECEIVED_MESSAGE_KEY] as Int) < 101 }) { throwExceptionOnRejection(true) } - transform { it.toUpperCase() } + transform { it.uppercase() } channel { queue("listeningFromKafkaResults1") } } @@ -269,7 +269,7 @@ class KafkaDslKotlinTests { .retryTemplate(RetryTemplate()) .filterInRetry(true)) { filter>({ m -> (m.headers[KafkaHeaders.RECEIVED_MESSAGE_KEY] as Int) < 101 }) { throwExceptionOnRejection(true) } - transform { it.toUpperCase() } + transform { it.uppercase() } channel { queue("listeningFromKafkaResults2") } } @@ -355,7 +355,7 @@ class KafkaDslKotlinTests { @Bean fun serverGateway() = integrationFlow(Kafka.inboundGateway(consumerFactory(), containerProperties(), producerFactory())) { - transform { it.toUpperCase() } + transform { it.uppercase() } } private fun containerProperties() =