Dagger 2 in Kotlin : Is there a way to do injection for class with default parameterized constructor without using Module? - kotlin

I want to have my Dagger 2 inject the below class and doesn't plan to use #Module to do so.
So I put #Inejct constructor as below
class InjectClass #Inject constructor(var txt: String = "Default")
It doesn't work as it complaints
e: [kapt] An exception occurred: java.lang.IllegalStateException: Found multiple
#Inject constructors: [InjectClass(java.lang.String), InjectClass()]
Is there a way to make it work here?

Instead of using a default value, you could write a secondary constructor instead:
class InjectClass #Inject constructor(var txt: String) {
constructor(): this("Default")
}
Like this you make sure that the default constructor is not annotated with #Inject and Dagger knows how to create InjectClass.
Optionally, we could do this
class InjectClass(var txt: String) {
#Inject constructor(): this("Default")
}

Related

Quarkus + kotlin dependency injection in tests

I am working on my quarkus + kotlin application. Having class:
#ApplicationScoped
class ParrallerCronScheduler(private val someService: SomeService) : CronScheduler
When the application is running there is no problem, quarkus injects someService.
Running this tests class:
#QuarkusTest
#QuarkusTestResource(PostgresResource::class)
internal class CroneUpdateTest(private val someService: SomeService): BaseIntegrationTest()
makes quarkus throw:
When using constructor injection in a test, the only legal operation is to assign the constructor values to fields. Offending class is class com.tui.promotion_campaigns_service.services.impl.CroneUpdateTes
which forces to use this imo ugly thing in tests:
#Inject
lateinit var someService: SomeService
Why the first way of test implementation not working? Is it possible to make it work?
I tried
class ParrallerCronScheduler #Inject constructor(private val someService: SomeService) : CronScheduler

Guice & Dropwizard - Field Injection not working - while Constructor Injection does

I have a test class that looks something like this
Behind the scenes, we're using Guice and DropwizardAwareModule to configure the binding and provide instantiated classes/beans.
class SomeTest {
companion object {
#RegisterExtension
#JvmField
val app = TestGuiceyAppExtension.forApp(MyServer::class.java)
.config(configFileName).hooks(GuiceyConfigurationHook {
builder(it)
}).create()
}
#Inject
#Named("something")
private lateinit var someClass: SomeClass
}
The SomeClass is defined in the following way:
class SomeClass(firstClass: FirstClass, secondClass: SecondClass) {
}
With no constructor injection.
In a separate DropwizardAwareModule, I define a Provides function that provides 2 possible instances of SomeClass. For example -
#Provides
#Named("something")
fun getSomeClass(firstClass: FirstClass, secondClass: SecondClass) {
return SomeClass(firstClass, secondClass)
}
The test class fails to inject SomeClass, claiming it doesn't have a no-args constructor, nor an #Inject annotated constructor, fair enough.
However, if I transform the field injection into a constructor injection, it works flawlessly.
That is - this configuration works well, and the SomeClass instance I provided in the module above, shows up alright.
class SomeTest #Inject constructor(#Named("something") someClass: SomeClass) {
}
Why is it so? is it because of some limitation in test classes? or is it something to do with #Provides generating an immutable instance, whereas field injection requires mutable objects?
Thanks!

Why use #singleton instead using simply object

In Kotlin, a common use for object is using it for singletons, like:
object MyObject {
...
}
However, when using micronaut framework, the official documentation recommends using something like this:
#Singleton
class V8Engine : Engine {
override var cylinders = 8
override fun start(): String {
return "Starting V8"
}
}
Why can't I use simply object instead of using annotation #Singleton with a class?
With a #Singleton, Micronaut can automatically manage dependencies between beans. If you go with the other class in https://docs.micronaut.io/latest/guide/ioc.html#beans, translated to Kotlin:
#Singleton
class Vehicle(private val engine: Engine) {
public fun start() = engine.start()
}
It can't be just an object because takes a parameter.
This parameter is discovered by Micronaut to be the singleton instance of V8Engine, which needs that to be a #Singleton and not an object.
Of course, in this case you could just directly use V8Engine in Vehicle; but it's easier to change e.g. if you want Engine not to be a singleton anymore.
Why can't I use simply object instead of using annotation #Singleton
with a class?
You can use object instead of using #Singleton with a class. Micronaut won't manage instances for you, but that is allowed.

What should I do if I don't want a devired class call base class's constructor in Kotlin?

Is there any way to create an instance of Derived but not call the constructor of Base?
open class Base(p: Int)
class Derived(p: Int) : Base(p)
You actually can do it
import sun.misc.Unsafe
open class Base(p: Int){
init {
println("Base")
}
}
class Derived(p: Int) : Base(p){
init {
println("Derived")
}
}
fun main() {
val unsafe = Unsafe::class.java.getDeclaredField("theUnsafe").apply {
isAccessible = true
}.get(null) as Unsafe
val x = unsafe.allocateInstance(Derived::class.java)
println("X = $x")
}
But don't, this solution is a low-level mechanism that was designed to be used only by the core Java library and not by standard users. You will break the logic of OOP if you use it.
this is not possible. The constructor of the derived class has to call (any) constructor of the base class in order to initialise the content(fields) of the base class.
This is also the same case in Java. Just that the default constructor is called by default (if no parameters are provided in the constructor), but if you have to choose between constructors with parameters, you always have to call them explicitly, because you have to choose which values to pass into the constructor.
You must always call a constructor of a super-class to ensure that the foundation of the class is initialized. But you can work around your issue by providing a no-arg constructor in the base class. Something like this:
open class Base(p: Int?){
val p: Int? = p
constructor(): this(null)
}
class Derived(p: Int) : Base()
The way you handle which constructor of the base class is default and which parameters are nullable, etc. will depend highly on the specific case.

Kotlin inheritance: pass this as constructor argument

Im trying to create a GsonRequest class that extends a normal volley request, and also implements the error listener. The code I'm using to do this is
public class GsonRequest<T>(url: String, val clazz: Class<T>) :
Request<T>(Request.Method.GET, url, this), ErrorListener
However, I'm getting the following error: 'this' is not defined in this context. Is what I'm trying to do possible?
You can not use this on the JVM before the super-constructor finished working, so you can not pass it to the super-constructor.
What you can do is use an object expression or a lambda for an error listener:
public class GsonRequest<T>(url: String, val clazz: Class<T>) :
Request<T>(Request.Method.GET, url, { <handling code here> } )
Alternatively, consider taking the listener as a parameter for constructor of class GsonRequest