Search code examples
scalagenericsdependency-injectionguice

Scala - Injecting Generic type using guice when dependency class is also using same generic type


I want to inject dependency with Generic type using Guice. Find below example in scala which replicate the issue.

ProductModel.scala

trait BaseProduct  

case class Product() extends BaseProduct 

CartService.scala

class CartService[A <: BaseProduct] @Inject()(productService : ProductService[A]) {
 def getCartItems = productService.getProduct
}

ProductService.scala

class ProductService[A]{
 def getProduct = println("ProductService")
}

Main.scala

object Main extends App {

  val injector = Guice.createInjector(new ShoppingModule)
  val cartService = injector.getInstance(classOf[CartService[Product]])
  cartService.getCartItems
}

class ShoppingModule extends AbstractModule with ScalaModule {
  override def configure(): Unit = {
    bind[BaseProduct].to(scalaguice.typeLiteral[Product])
  }
}

while running this Main.scala app getting below error.

service.ProductService<A> cannot be used as a key; It is not fully specified.

I have tried binding using codingwell library. But it doesn't help to identify ProductService Type.


Solution

  • When you create instance of cartService at that time use typeLiteral to create instance like

    val cartService = injector.getInstance(Key.get(scalaguice.typeLiteral[CartService[Product]])
    

    if you create instance like above you don't need to create module. Create injector using default Module (i.e. useful if you have any other bindings in default Module.scala at application level)

    val appBuilder = new GuiceApplicationBuilder()
    val injector = Guice.createInjector(appBuilder.applicationModule())
    

    and if you don't have any module you can skip passing module as argument and create injector without passing any module as well like

    val injector = Guice.createInjector()