Dependency injection


#1

Hi All,

My current approach to define dependencies that are supposed to be injected by a framework (Spring, Guice, etc) is like following:

 
@Inject
private val logger: Logger? = null

Although, from language point of view it is true that logger in above example can be null, but considering the DI framework, we can fairely assume that logger is always NOT null. Is there any solution to define such depencies as following or something similar ?

 
@Inject
private val logger: Logger

Regards,
Mohammad Shamsi


#2

I declare my Guice dependencies in the constructor:

public class MyClass @Inject constructor(val logger: Logger, val db: Database) { ...


#3

As an alternative to what Cedric does, you can use the not-null property delegate (http://kotlinlang.org/docs/reference/delegated-properties.html#not-null), though that would possibly introduce some function call overhead (because it always needs to check before reading the property?), but you should probably not worry about that most of the time (though I would prabably prefer using constructor injection as Cedric most of the time).


#4

This is ok with some DI frameworks but not all. Some of them require to have the class with default constructor. they inject dependencis after instance creataion.


#5

This solution also does not work in some DI frameworks (for example: Tapestry IoC).


#6

Sure Mohammad, when an x alternative is not a solution for a specific y problem, then you shouldn't use it.


#7

We are going to roll out a new feature that fixes this issue very soon


#8

@Andrey,

May I have the issue number (if it is available in issue tracker)?


#9

https://youtrack.jetbrains.com/issue/KT-9067


#10

Or use delegates to inject from Injekt framework:

https://github.com/kohesive/injekt

It can be used as default constructor expressions, as delegates, or as just a function to return a value from the object registry.

Injekt will soon materialize object graphs, and the “lateinit” will be useful then possibly.

Also it would be nice for the Jackson-Jr port to Kotlin.  But mostly those are taking a bit different approach that might include “lateinit” but as a lower priority.  With M13 they can base decisions on which things are nullable or not, final or can be set later, have default values or not (Java injection and data binding frameworks will not get this right, so they will never really fit well without using Kotlin reflection), and lastly could use “lateinit” when no other path makes sense such as a “val” property not in the constructor and should be injected without a delegate (but why not use a delegate unless your object wasn’t made by you that you are injecting into).  So a combination of constructor parameters, setters, and “lateinit” properties.

But these are “going forward” frameworks that assume most your App code is Kotlin, and you “use” Java libraries but the Kotlin is in control, and where Injection and data binding happen.  Although our data binder will handle generic Java cases as well.  Just not as pretty.


#11

The issue has been fixed and here is the description: https://kotlinlang.org/docs/reference/properties.html#late-initialized-properties


#12

Constructor injection is also recommended with Spring, see this spring-kotlin FAQ entry for more details.


#13

You might want to look at Kodein which is a nice DI alternative for Kotlin, that I quite like. It does not use annotation processing, it instead uses property delegation to retrieve dependencies: