I am new to Guice. I am trying to use requestInjection to inject the dependencies of a kotlin singleton object in this way.
APPROACH 1:
class SampleTest {
@Test
fun test() {
Guice.createInjector(object: KotlinModule() {
override fun configure() {
requestInjection(A)
}
})
assertEquals("Hello world", A.saySomething())
}
}
object A {
@Inject
private lateinit var b: B
fun saySomething(): String {
return b.sayHello()
}
}
class B {
fun sayHello(): String {
return "Hello world"
}
}
But I am getting this error:
kotlin.UninitializedPropertyAccessException: lateinit property b has not been initialized
If I change A to a class with no-arg constructor, it works.
APPROACH 2:
class SampleTest {
@Test
fun test() {
val a = A()
Guice.createInjector(object: KotlinModule() {
override fun configure() {
requestInjection(a)
}
})
assertEquals("Hello world", a.saySomething())
}
}
class A {
@Inject
private lateinit var b: B
fun saySomething(): String {
return b.sayHello()
}
}
class B {
fun sayHello(): String {
return "Hello world"
}
}
Instead, if I change requestInjection to requestStaticInjection, it also works.
APPROACH 3:
class SampleTest {
@Test
fun test() {
Guice.createInjector(object: KotlinModule() {
override fun configure() {
requestStaticInjection<A>()
}
})
assertEquals("Hello world", A.saySomething())
}
}
object A {
@Inject
private lateinit var b: B
fun saySomething(): String {
return b.sayHello()
}
}
class B {
fun sayHello(): String {
return "Hello world"
}
}
Why didn't APPROACH 1 work? Why did APPROACH 2 and APPROACH 3 work?
Kotlin's objects are treated as language static singletons, i.e. their initialization/instantiations happens outside the scope of the dependency injection framework.
Therefor, when using the KotlinModule
to inject an object, you have to use requestStaticInjection
like in APPROACH 3, or change that object to a class, so that the Guice KotlinModule
sees it as non-static
, as presented in APPROACH 2
Hope that clarifies things a bit.