diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index f6018245..5761c0ee 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: ['17'] + java: ['17', '21'] env: GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} GRADLE_ENTERPRISE_CACHE_USERNAME: ${{ secrets.GRADLE_ENTERPRISE_CACHE_USERNAME }} diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 0d901c94..81408424 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -8,6 +8,9 @@ repositories { } dependencies { - implementation("io.micronaut.gradle:micronaut-gradle-plugin:4.1.1") - implementation("io.micronaut.gradle:micronaut-crac-plugin:4.1.1") + implementation(libs.micronaut.gradle.plugin) + implementation(libs.micronaut.crac.plugin) + implementation(libs.kotlin.gradle.plugin) + implementation(libs.kotlin.gradle.allopen) + implementation(libs.kotlin.gradle.ksp) } diff --git a/buildSrc/settings.gradle b/buildSrc/settings.gradle new file mode 100644 index 00000000..6f31e6ef --- /dev/null +++ b/buildSrc/settings.gradle @@ -0,0 +1,7 @@ +dependencyResolutionManagement { + versionCatalogs { + libs { + from(files("../gradle/libs.versions.toml")) + } + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5bfc9d51..a9414c56 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,6 +4,7 @@ micronaut = "4.1.6" micronaut-cache = "4.0.2" micronaut-data = "4.1.4" micronaut-docs = "2.0.0" +micronaut-gradle-plugin = "4.1.1" micronaut-platform = "4.1.3" micronaut-redis = "6.0.2" micronaut-serialization = "2.2.5" @@ -11,6 +12,8 @@ micronaut-sql = "5.0.3" micronaut-test = "4.0.1" groovy = "4.0.13" +kotlin = '1.9.10' +ksp = '1.9.10-1.0.13' spock = "2.3-groovy-4.0" managed-crac = "1.4.0" @@ -33,3 +36,9 @@ micronaut-sql = { module = "io.micronaut.sql:micronaut-sql-bom", version.ref = " managed-crac = { module = "org.crac:crac", version.ref = "managed-crac" } testcontainers = { module = "org.testcontainers:testcontainers", version.ref = "testcontainers" } + +micronaut-gradle-plugin = { module = "io.micronaut.gradle:micronaut-gradle-plugin", version.ref = 'micronaut-gradle-plugin' } +micronaut-crac-plugin = { module = "io.micronaut.gradle:micronaut-crac-plugin", version.ref = 'micronaut-gradle-plugin' } +kotlin-gradle-plugin = { module = 'org.jetbrains.kotlin:kotlin-gradle-plugin', version.ref = 'kotlin' } +kotlin-gradle-allopen = { module = 'org.jetbrains.kotlin:kotlin-allopen', version.ref = 'kotlin' } +kotlin-gradle-ksp = { module = 'com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin', version.ref = 'ksp' } diff --git a/settings.gradle b/settings.gradle index fe44cc6f..84927813 100644 --- a/settings.gradle +++ b/settings.gradle @@ -21,7 +21,10 @@ include 'test-suite-dbcp-jooq' include 'test-suite-docker' include 'test-suite-groovy' include 'test-suite-hikari-jooq' -include 'test-suite-kotlin' +if (JavaVersion.current() < JavaVersion.VERSION_21) { + include 'test-suite-kotlin' +} +include 'test-suite-kotlin-ksp' include 'test-suite-redis' micronautBuild { diff --git a/test-suite-docker/build.gradle.kts b/test-suite-docker/build.gradle.kts index 5c0a9fa8..afca6358 100644 --- a/test-suite-docker/build.gradle.kts +++ b/test-suite-docker/build.gradle.kts @@ -33,4 +33,7 @@ micronaut { importMicronautPlatform.set(false) runtime("netty") testRuntime("spock") + crac { + this.javaVersion.set(JavaLanguageVersion.of(JavaVersion.current().majorVersion)) + } } diff --git a/test-suite-kotlin-ksp/build.gradle.kts b/test-suite-kotlin-ksp/build.gradle.kts new file mode 100644 index 00000000..afbc4a56 --- /dev/null +++ b/test-suite-kotlin-ksp/build.gradle.kts @@ -0,0 +1,25 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + id("org.jetbrains.kotlin.jvm") + id("com.google.devtools.ksp") + id("io.micronaut.build.internal.crac-test-suite") +} + +dependencies { + ksp(mn.micronaut.inject.kotlin) + + testImplementation(projects.micronautCrac) + testImplementation(mnTest.micronaut.test.junit5) + + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") +} + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +tasks.withType { + kotlinOptions.jvmTarget = "17" +} diff --git a/test-suite-kotlin-ksp/src/test/kotlin/io/micronaut/crac/EagerHttpClientCreationTest.kt b/test-suite-kotlin-ksp/src/test/kotlin/io/micronaut/crac/EagerHttpClientCreationTest.kt new file mode 100644 index 00000000..50d8c892 --- /dev/null +++ b/test-suite-kotlin-ksp/src/test/kotlin/io/micronaut/crac/EagerHttpClientCreationTest.kt @@ -0,0 +1,49 @@ +package io.micronaut.crac + +import io.micronaut.context.DefaultApplicationContextBuilder +import io.micronaut.context.annotation.Property +import io.micronaut.context.annotation.Requires +import io.micronaut.core.annotation.Introspected +import io.micronaut.http.annotation.Controller +import io.micronaut.http.annotation.Get +import io.micronaut.http.client.HttpClient +import io.micronaut.runtime.server.EmbeddedServer +import io.micronaut.test.extensions.junit5.annotation.MicronautTest +import jakarta.inject.Inject +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +@MicronautTest(contextBuilder = [EagerHttpClientCreationTest.EagerSingletons::class]) +@Property(name = "spec.name", value = "EagerHttpClientCreationTest") +class EagerHttpClientCreationTest { + + //tag::test[] + @field:Inject + lateinit var server: EmbeddedServer // <1> + + val client by lazy { + server.applicationContext.createBean(HttpClient::class.java, server.url) // <2> + } + + @Test + fun testClient() { + assertEquals("ok", client.toBlocking().retrieve("/eager")) // <3> + } + //end::test[] + + @Requires(property = "spec.name", value = "EagerHttpClientCreationTest") + @Controller("/eager") + internal class EagerController { + @Get + fun test(): String { + return "ok" + } + } + + @Introspected + internal class EagerSingletons : DefaultApplicationContextBuilder() { + init { + eagerInitSingletons(true) + } + } +} diff --git a/test-suite-kotlin-ksp/src/test/kotlin/io/micronaut/crac/OrderedResourceCheckpointSimulatorTest.kt b/test-suite-kotlin-ksp/src/test/kotlin/io/micronaut/crac/OrderedResourceCheckpointSimulatorTest.kt new file mode 100644 index 00000000..2231b8cf --- /dev/null +++ b/test-suite-kotlin-ksp/src/test/kotlin/io/micronaut/crac/OrderedResourceCheckpointSimulatorTest.kt @@ -0,0 +1,35 @@ +package io.micronaut.crac + +import io.micronaut.context.BeanContext +import io.micronaut.context.annotation.Property +import io.micronaut.crac.test.CheckpointSimulator +import io.micronaut.test.extensions.junit5.annotation.MicronautTest +import jakarta.inject.Inject +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test + +@MicronautTest +@Property(name = "spec.name", value = OrderedResourceCheckpointSimulatorTest.SPEC_NAME) +class OrderedResourceCheckpointSimulatorTest { + companion object { + const val SPEC_NAME = "OrderedResourceCheckpointSimulatorTest" + } + + //tag::test[] + @field:Inject + lateinit var ctx: BeanContext + + @Test + fun testCustomOrderedResourceUsingCheckpointSimulator() { + val myBean = ctx.getBean(ResourceBean::class.java) + val checkpointSimulator = ctx.getBean(CheckpointSimulator::class.java) // <1> + Assertions.assertTrue(myBean.isRunning) + + checkpointSimulator.runBeforeCheckpoint() // <2> + Assertions.assertFalse(myBean.isRunning) + + checkpointSimulator.runAfterRestore() // <3> + Assertions.assertTrue(myBean.isRunning) + } + //end::test[] +} diff --git a/test-suite-kotlin-ksp/src/test/kotlin/io/micronaut/crac/ResourceBean.kt b/test-suite-kotlin-ksp/src/test/kotlin/io/micronaut/crac/ResourceBean.kt new file mode 100644 index 00000000..3092d42a --- /dev/null +++ b/test-suite-kotlin-ksp/src/test/kotlin/io/micronaut/crac/ResourceBean.kt @@ -0,0 +1,22 @@ +package io.micronaut.crac + +import io.micronaut.context.annotation.Requires +import jakarta.inject.Singleton + +@Requires(property = "spec.name", value = OrderedResourceCheckpointSimulatorTest.SPEC_NAME) +//tag::bean[] +@Singleton +class ResourceBean { + + var isRunning = true // <1> + private set + + fun stop() { + isRunning = false + } + + fun start() { + isRunning = true + } +} +//end::bean[] diff --git a/test-suite-kotlin-ksp/src/test/kotlin/io/micronaut/crac/ResourceBeanResource.kt b/test-suite-kotlin-ksp/src/test/kotlin/io/micronaut/crac/ResourceBeanResource.kt new file mode 100644 index 00000000..aec13337 --- /dev/null +++ b/test-suite-kotlin-ksp/src/test/kotlin/io/micronaut/crac/ResourceBeanResource.kt @@ -0,0 +1,23 @@ +package io.micronaut.crac + +import io.micronaut.context.annotation.Requires +import jakarta.inject.Singleton +import org.crac.Context +import org.crac.Resource + +@Requires(property = "spec.name", value = OrderedResourceCheckpointSimulatorTest.SPEC_NAME) +//tag::resource[] +@Singleton +class ResourceBeanResource(private val resourceBean: ResourceBean) : OrderedResource { // <1> + + @Throws(Exception::class) + override fun beforeCheckpoint(context: Context?) { // <2> + resourceBean.stop() + } + + @Throws(Exception::class) + override fun afterRestore(context: Context?) { // <3> + resourceBean.start() + } +} +//end::resource[] diff --git a/test-suite-kotlin/build.gradle.kts b/test-suite-kotlin/build.gradle.kts index e4959e95..5d4a1aff 100644 --- a/test-suite-kotlin/build.gradle.kts +++ b/test-suite-kotlin/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - id("org.jetbrains.kotlin.jvm") version "1.9.10" - id("org.jetbrains.kotlin.kapt") version "1.9.10" + id("org.jetbrains.kotlin.jvm") + id("org.jetbrains.kotlin.kapt") id("io.micronaut.build.internal.crac-test-suite") }