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

7

47

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?

Cavetto answered 15/9, 2017 at 11:44 Comment(2)
Can you autowire the nullable version? And does the field have to be lateinitProfundity
Yes, var todCacheTimeSeconds: Int? = null works, but thats not what i want.Cavetto
B
54

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.

Brougham answered 11/12, 2019 at 14:52 Comment(0)
H
21

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

should be

@Value("\${cacheTimeSeconds}")
val cacheTimeSeconds: Int? = null
Hypo answered 7/6, 2018 at 5:41 Comment(2)
also u can inject env and pass values form there, using lazy delegateHypo
I would advise against a nullable type, if possible (and not only because OP said that's not an option). Making something nullable that you didn't intend to make nullable by design is basically going backwards towards Java...Untie
H
13

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
Herbalist answered 24/10, 2019 at 13:37 Comment(0)
F
3

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)
    }
}
Forequarter answered 27/6, 2019 at 7:47 Comment(0)
S
1

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

Stralka answered 10/3, 2020 at 1:9 Comment(4)
OP says "Autowiring a non-primitive with spring annotations"...Faustofaustus
@Faustofaustus Could you share the property to try to deduce why it fails or reproduce? And also the full errorStralka
String is Object, not primitive. I know, there is only objects in Kotlin, but not for JVM. See example in OP: @Value("\${cacheTimeSeconds}") lateinit var cacheTimeSeconds: Int There is few solutions are given in this thread, but without default value and outside constructor you can do it in this way: @delegate:Value("\${cacheTimeSeconds}") var cacheTimeSeconds by Delegates.notNull<Int>()Faustofaustus
Updated answer. ThanksStralka
P
0

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.

Profundity answered 15/9, 2017 at 11:53 Comment(0)
L
0

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.

Loralyn answered 15/9, 2017 at 16:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.