Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot with Kotlin - @Value annotation not working as expected

I'm developing a Spring boot application using Kotlin. Since I need to connect to an external API (cloudinary) I decided to add to my app a configuration class in order to store (and hide from VCS) my sensible data like username, passwords or API keys.

So this is what i did:

I created a Config class:

package demons

import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.PropertySource

@Configuration
@PropertySource("classpath:application.properties")
class AppConfig {
    @Value("\${test.prop}")
    val testProperty: String? = null
}

Then I added a test.prop entry in my application.properties file

test.prop=TEST

However, in every test I run, after creating an instance of AppConfig, his testProperty attribute is null instead of being the string TEST.

For instance this snippet:

val config = AppConfig()
System.out.println(config.testProperty)

would print out:

null

I've also tried using a separate .properties file instead of the default one like myproperties.properties and declaring the variable as lateinit var. In this last case the variable seems to never be initialized:

kotlin.UninitializedPropertyAccessException: lateinit property testProperty has not been initialized

What am I missing?

like image 334
Adriano Todaro Avatar asked Jul 10 '18 16:07

Adriano Todaro


People also ask

How does @value work in spring boot?

One of the most important annotations in spring is @Value annotation which is used to assign default values to variables and method arguments. We can read spring environment variables as well as system variables using @Value annotation. It also supports Spring Expression Language (SpEL).

Can we use @value in interface?

No, this is not (directly) possible. The default value of an annotation property must be a compile-time constant.

What is spring @ConfigurationProperties?

Spring Boot @ConfigurationProperties is letting developer maps the entire . properties and yml file into an object easily. P.S Tested with Spring Boot 2.1.2.RELEASE.


1 Answers

The issue is that you are creating the instance of AppConfig yourself via the constructor:

val config = AppConfig()

While this class might have Spring annotations, it is NOT spring managed if you create the instance yourself.

I recommend you borrow from the link you mentioned in my other answer. There are good examples of using SpringBoot to create a Spring application for you. Below I created a 'merged' example of your test + an example from the link. There is no need to specify a properties file, as application.properties is used as a property source by default.

@SpringBootApplication
class AppConfig {
    @Value("\${test.prop}")
    val testProperty: String? = null
}

fun main(args: Array<String>) {
    val appContext = SpringApplication.run(AppConfig::class.java, *args)
    val config = appContext.getBean(AppConfig::class.java)
    System.out.println(config.testProperty)
}
like image 97
nicholas.hauschild Avatar answered Sep 21 '22 21:09

nicholas.hauschild