Reputation: 2799
How can I use lateinit properties in my class constructor:
I have a spring component that I use to setup and access a third party library like so:
@Service
class LibProxy {
@Value("\${lib.someProperty}")
private lateinit var someProperty: String
final var lib: Lib
init {
lib = Lib(someProperty)
}
}
This gives a
kotlin.UninitializedPropertyAccessException: lateinit property someProperty has not been initialized
How is this supposed to be done?
I would like to avoid constructs like so:
@Service
class LibProxy {
@Value("\${lib.someProperty}")
private lateinit var someProperty: String
private var lib: Lib? = null
getLib(): Lib {
if (lib == null) {
lib = Lib(someProperty)
}
return lib ?: Lib(someProperty)
}
}
Upvotes: 3
Views: 4310
Reputation: 18577
Two possibilities here:
The easy one is to replace the init
block with a @PostConstruct
method. Spring will call this once, after the object has been constructed (and hence autowired values are all set). For example:
@PostConstruct
private fun initialise() {
lib = Lib(someProperty)
}
The other is to arrange for the autowired property to be passed in a constructor, not set as a property (as per other answers).
One approach that works well, especially if you have several configuration properties, is to have a central class storing them:
@ConfigurationProperties("lib")
class ConfigProperties {
var someProperty = "defaultValue"
// …and other properties…
}
This will set someProperty
from a "lib.someProperty" value in a config file (or left as "defaultValue" if not present).
You can then autowire its instance in the constructor, e.g.:
class SomeService @Autowired constructor(
private val configProperties: ConfigProperties) {
init {
lib = Lib(configProperties.someProperty)
}
}
(Centralising the properties can make it easier to find what properties are available, too.)
Upvotes: 3