Search code examples
kotlinconfigurationquarkusinject

How to read Quarkus Config in dedicated Kotlin Class


Reading application properties in Kotlin/Quarkus works in a test class likes this correctly (the print will write the value which are defined in the application.properties file):

@QuarkusTest
class Test {

    @ConfigProperty(name = "test.env")
    val testEnv: String? = null

    @Test
    fun test(){
        println(testEnv)
    }
}

But when I create a dedicated configuration class and try to access the member from that class, the value is always null (and not as defined in the application.properties):

class Config{
    
    @ConfigProperty(name = "test.env")
    val foo: String? = null
}

Trying to access this value in the test class (but the value is always null):

@QuarkusTest
class Test {

    @Test
    fun test(){
        println(Config().foo)
    }
}

Quarkus version: 1.10.3.Final

What am I doing wrong?


Solution

  • The @ConfigProperty annotation is in fact a CDI qualifier. In Quarkus, if a field is annotated with a qualifier, it doesn't have to be annotated @Inject -- but it is treated as if it was.

    So your test class is equivalent to this:

    @QuarkusTest
    class Test {
        @Inject
        @ConfigProperty(name = "test.env")
        val testEnv: String? = null
    
        @Test
        fun test(){
            println(testEnv)
        }
    }
    

    Now, the other important thing is that if possible, the Quarkus test framework treats the test class as a CDI bean. That is, the test class is instantiated by the CDI container, which performs dependency injection. That is how testEnv is populated.

    How do you achieve the same thing?

    1. Make your class a bean by adding a bean defining annotation.
    @Singleton
    class Config{ 
        @ConfigProperty(name = "test.env")
        val foo: String? = null
    }
    

    (Note that in standard CDI, @Singleton is not a bean defining annotation. In Quarkus, @Singleton is a bean defining annotation, but if you want to strictly adhere to the standard, you can use @ApplicationScoped instead.)

    1. Don't instantiate Config by calling the constructor. Instead, use dependency injection again:
    @QuarkusTest
    class Test {
        @Inject
        Config config;
    
        @Test
        fun test(){
            println(config.foo)
        }
    }