how to use spring annotations like @Autowired or @Value in kotlin for primitive types?

44.3k views Asked by At

Autowiring a non-primitive with spring annotations like bellow works:

@Autowired
lateinit var metaDataService: MetaDataService

But this doesn't work:

@Value("\${cacheTimeSeconds}")
lateinit var cacheTimeSeconds: Int

Error:

lateinit modifier is not allowed for primitive types.

How to autowire primitve properties into Kotlin classes?

7

There are 7 answers

0
anstue On BEST ANSWER

You can also use the @Value annotation within the constructor:

class Test(
    @Value("\${my.value}")
    private val myValue: Long
) {
        //...
  }

This has the benefit that your variable is final and none-nullable. I also prefer constructor injection. It can make testing easier.

0
jrtapsell On

The problem is not the annotation, but the mix of primitive and lateinit, as per this question, Kotlin does not allow lateinit primitives.

The fix would be to change to a nullable type Int?, or to not use lateinit.

This TryItOnline shows the issue.

0
Eduard Kornev On

Kotlin compiles Int to int in java code. Spring wanted non-primitive types for injection, so you should use Int? / Boolean? / Long? and etc. Nullable types kotlin compile to Integer / Boolean / etc.

0
drix On

I just used Number instead of Int like so:

@Value("\${cacheTimeSeconds}")
lateinit var cacheTimeSeconds: Number

The other options are to do what others mentioned before:

@Value("\${cacheTimeSeconds}")
var cacheTimeSeconds: Int? = null

Or you can simply provide a default value like:

@Value("\${cacheTimeSeconds}")
var cacheTimeSeconds: Int = 1

In my case I had to get a property that was a Boolean type which is primitive in Kotlin, so my code looks like this:

@Value("\${myBoolProperty}")
var myBoolProperty: Boolean = false
2
qwert_ukg On

@Value("\${cacheTimeSeconds}") lateinit var cacheTimeSeconds: Int

should be

@Value("\${cacheTimeSeconds}")
val cacheTimeSeconds: Int? = null
0
Yao Yuan On

Try to set a default value

    @Value("\${a}")
    val a: Int = 0

in application.properties

a=1

in the code

package com.example.demo

import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.stereotype.Component

@SpringBootApplication
class DemoApplication

fun main(args: Array<String>) {
    runApplication<DemoApplication>(*args)
}

@Component
class Main : CommandLineRunner {

    @Value("\${a}")
    val a: Int = 0

    override fun run(vararg args: String) {
        println(a)
    }
}

it will print 1

or use contructor inject

@Component
class Main(@Value("\${a}") val a: Int) : CommandLineRunner {

    override fun run(vararg args: String) {
        println(a)
    }
}
4
Braian Coronel On

Without default value and outside constructor

From:

@Value("\${cacheTimeSeconds}") lateinit var cacheTimeSeconds: Int

To:

@delegate:Value("\${cacheTimeSeconds}")  var cacheTimeSeconds by Delegates.notNull<Int>()

Good Luck

Kotlin doesn't have primitive type