Search code examples
dependency-injectionguicekotlin

Why isn't Guice finding my List<Interface> binding?


I've got a interface with a couple of implementations:

interface PuNoManager {
    fun notifyUser(userId: Int)
}

class FcmManager
@Inject
constructor(val fcmClient: FcmClient) : PuNoManager {
    override fun notifyUser(userId: Int) { ...  }
}

class ApnsManager
@Inject
constructor(val apnsClient: ApnsClient) : PuNoManager {
    override fun notifyUser(userId: Int) { ...  }
}

Which are both bound in my Module, along with a @Provides-annotated method to get a List<PuNoManager>:

class PuNoModule: AbstractModule() {
    override fun configure() {
        bind(ApnsManager::class.java)
        bind(FcmManager::class.java)
    }

    @Provides
    fun puNoManagers(apnsManager: ApnsManager, fcmManager: FcmManager): List<PuNoManager> {
        return listOf(apnsManager, fcmManager)
    }
}

The problem arises when I have a class that needs the List<PuNoManager>—Guice complains that the type hasn't been bound:

Explicit bindings are required and java.util.List<? extends ...PuNoManager> is not explicitly bound.
  while locating java.util.List<? extends ...PuNoManager>

I know my Guice setup is working, as I previously had just the ApnsManager and am adding the second PuNoManager, FcmManager. The problem stems from the dependent class requesting injection of List<PuNoManager> instead of just ApnsManager.


Solution

  • List<X> in Kotlin is translated to java.util.List<? extends X> on the JVM. Apparently, Guice doesn't support injection of such values. To avoid the wildcard here, you can use a MutableList<X> instead, which translates to java.util.List<X>