Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to load configuration for a data class containing a kotlin.time.Duration? #453

Open
chrisalbright opened this issue Oct 10, 2024 · 3 comments

Comments

@chrisalbright
Copy link

I've been using Kotlin 2.0.20, but I've tested with 1.6.21 and get the same error regardless. I've included a sample project illustrating the problem. Ironically, I created this project (hoplite-test.zip) in order to demonstrate the issue and I'm seeing the same behavior but the underlying cause is different.

The original project I'm working on is manifesting with a ClassCastException:

Exception in thread "main" com.sksamuel.hoplite.ConfigException: Error loading config because:

    Could not instantiate class Simple from args [kotlin.time.Duration]: Expected args are [class kotlin.time.Duration]. Underlying error was java.lang.ClassCastException: Cannot cast java.lang.Long to kotlin.time.Duration
	at com.sksamuel.hoplite.ConfigLoaderKt$returnOrThrow$1.invoke(ConfigLoader.kt:315)
	at com.sksamuel.hoplite.ConfigLoaderKt$returnOrThrow$1.invoke(ConfigLoader.kt:312)
	at com.sksamuel.hoplite.fp.ValidatedKt.getOrElse(Validated.kt:115)
	at com.sksamuel.hoplite.ConfigLoaderKt.returnOrThrow(ConfigLoader.kt:312)
	at com.sksamuel.hoplite.ConfigLoader.returnOrThrow(ConfigLoader.kt:273)
	at SimpleKt.main(Simple.kt:33)
	at SimpleKt.main(Simple.kt)

The code that creates this stacktrace is

import com.sksamuel.hoplite.ConfigLoaderBuilder
import com.sksamuel.hoplite.ExperimentalHoplite
import com.sksamuel.hoplite.addResourceSource
import kotlin.time.Duration

data class Simple(val duration: Duration?)

@OptIn(ExperimentalHoplite::class)
fun main() {
    val simple = ConfigLoaderBuilder
        .default()
        .withExplicitSealedTypes()
        .addResourceSource("/duration.yml").build()
        .loadConfigOrThrow<Simple>()

    println(simple)
}

With this configuration file

duration: 5 minutes

The (slightly modified) build configuration is

plugins {
    kotlin("jvm") version "2.0.20"
    `java-library`
    `maven-publish`
}

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(11))
    }
}

repositories {
    mavenCentral()
    mavenLocal()
}

dependencies {
    kotlin("stdlib")
    val hopliteVersion = "2.8.2"
    implementation("com.sksamuel.hoplite:hoplite-core:$hopliteVersion")
    implementation("com.sksamuel.hoplite:hoplite-toml:$hopliteVersion")
    implementation("com.sksamuel.hoplite:hoplite-yaml:$hopliteVersion")
}

The demonstration project included here is also failing, but with a different underlying error:

com.sksamuel.hoplite.ConfigException: Error loading config because:

    Could not instantiate class org.example.NotWorking$Simple from args [kotlin.time.Duration]: Expected args are [class kotlin.time.Duration]. Underlying error was java.lang.IllegalArgumentException: argument type mismatch
	at com.sksamuel.hoplite.ConfigLoaderKt$returnOrThrow$1.invoke(ConfigLoader.kt:315)
	at com.sksamuel.hoplite.ConfigLoaderKt$returnOrThrow$1.invoke(ConfigLoader.kt:312)
	at com.sksamuel.hoplite.fp.ValidatedKt.getOrElse(Validated.kt:115)
	at com.sksamuel.hoplite.ConfigLoaderKt.returnOrThrow(ConfigLoader.kt:312)
	at com.sksamuel.hoplite.ConfigLoader.returnOrThrow(ConfigLoader.kt:273)
	at org.example.DemoKt.main(Demo.kt:186)
	at org.example.DemoKt.main(Demo.kt)

I've been trying to get it to fail the same way, but no success - maybe you'll see some difference in the configuration that isn't standing out to me.

In both cases the error is coming from the DataClassDecoder class (/com/sksamuel/hoplite/decoder/DataClassDecoder.kt:126, /com/sksamuel/hoplite/decoder/DataClassDecoder.kt:140, /com/sksamuel/hoplite/decoder/DataClassDecoder.kt:144)

I have only encountered this problem with kotlin.time.Duration?. kotlin.time.Duration works without any problem.

@sksamuel
Copy link
Owner

So it only happens on nullable durations ?

@chrisalbright
Copy link
Author

That's right. I supposed I could have phrased that more clearly.

@rocketraman
Copy link
Contributor

@chrisalbright Seems like it might be a bug with kotlin-reflect 1.6.21.

Explicitly adding implementation(kotlin("reflect", "2.0.20")) to your dependencies resolves the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants