Migrating from JavaX to Kodein DI

Introduction

When migrating an existing project from Java to Kotlin, chances are the project is already using a dependency injection library. There is a big chance that this library is using javax.inject.* annotations such as Guice or Dagger 1 & 2. If this is the case, then migrating to Kodein should not be a hassle :)

If you are migrating a project to Kotlin & Kodein, chances are you are already sold on the benefit on using Kodein.
Everything that is described here exists only to ease the transition from Java to Kotlin. You should definitely not use what is described here on Kotlin code and classes. This is for Java only!

Install

  1. Remove the previous library dependency. Good riddance ;)

  2. Add the Kodein dependency.

  3. Replace the previous bindings with Kodein’s bindings.

  4. Add the Kodein JxInject dependency (don’t forget to import the jxInjectorModule).

Inject

Fields & methods

If you can access a Kodein instance, you can inject any class that uses the classic @Inject annotation.

Example: Java class whose fields can be automatically injected.
public class MyJavaController {
    @Inject
    Connection connection;

    @Inject
    FileSystem fs;

    /* ... */
}

You can then inject existing instances of such classes by using kodein.jx in Kotlin, or Jx.of(kodein) in Java.

Example: Injecting an existing instance in Kotlin
val controller = MyJavaController()
kodein.jx.inject(controller)
Example: Injecting an existing instance in Java
MyJavaController controller = new MyJavaController();
Jx.of(kodein).inject(controller);

Kodein-JxInject supports, out of the box:

  • Field injection

  • Method injection

  • javax.inject.Provider injection

Constructors

You can create a new instance of a given class, provided that:

  • The class has only one constructor

  • Or the class have one of its constructors annotated with @Inject.

It is a good practice, however, to always have an @Inject constructor, even if it is the only constructor.

Example: Java class that can be automatically created with injections
public class MyJavaController {
    @Inject
    public MyJavaController(Connection connection, FileSystem fs) {
        /* ... */
    }
    /* ... */
}

You can then create instances of such classes by using kodein.jx in Kotlin, or Jx.of(kodein) in Java.

Example: Creating a new instance in Kotlin
val controller = kodein.jx.newInstance<MyJavaController>()
Example: Creating a new instance in Java
MyJavaController controller = Jx.of(kodein).newInstance(MyJavaController.class);

Qualifiers

JavaX dependency injection libraries use the concept of qualifier annotations while Kodein uses the very similar concept of tag.

The @Named annotation is supported out of the box and uses the string value of the annotation directly as the tag.

If you are using qualifiers annotations other than @Named, you need to register "transform" functions that transform qualifier annotations into tags.

Example: Registering a qualifier annotation
val kodein = Kodein {
    import(jxInjectorModule)

    /* Other bindings */

    jxQualifier<MyQualifier> { MyTag(it.value) } (1)
}

<1>: Transforms a MyQualifier qualifier annotation into a MyTag Kodein tag.

Use Kodein’s Kotlin API

Don’t forget that kodein-jxinject should only be used in or on Java code! If you are transforming Java code into Kotlin, than take the time to migrate the injection code to Kodein’s native api.

Simply: Replace all @Inject annotated fields with their kodein.instance() counterparts.