How to mix scala object based singleton and Guice DI


(Tenstriker) #1

Is there a way to achieve this without creating classes in calling application?

I have an application which uses scala Objects to define sigletone services. Another app that uses guice. There is a common module for this service which defines some classes with DI. I can inejct them just fine in my 2nd app as that app is DI base as well. But I can’t in first one as there is no DI there.

One approach I see is to create a scala Objects for classes in common module so that they can be accessed via application that relies on scala Object singletons. Any other suggestions?


(Marcos Pereira) #2

Well, dependency injection does not requires a framework. Can’t you change the application that is not using DI to just declare how to initialize instances? For example, going from:

object Something {
  val ws: WSClient = ??? // initialize the WSClient instance somehow
}

To:

class Something(val ws: WSClient) {
  ...
}

And on the side where you need dependency injection, you can just declare and bind a provider:

class SomethingProvider @Inject()(ws: WSClient) extends javax.inject.Provider[Something] {
  override def get: Something = new Something(ws)
}

import play.api.inject.{ SimpleModule, bind }
class SomethingModule extends SimpleModule(
  bind[Something].toProvider[SomethingProvider]
)

Or maybe I’m not fully understanding your question. Why do you need an object? Why not plug the existing application using providers?

Best.


(Tenstriker) #3

We use scala Object as it’s a signleton. We use is in one of our app (app A) to define stateless services, repositories, utilities etc. Now, If now they have to communicate with Class define in common module then, something needs to initialize it and provide a classic factory access to it.

e.g
Following needs a companion object so it can called via normal scala object. This is what I am doing so far.

//class in common module
class ServiceXRestClient @Inject()(ws: WSClient) extends javax.inject.Provider[Something] {
  def doGet = {
    ws.url("").get
  }
}

object ServiceXRestClient  {
  val ws: WSClient = ??? // initialize the WSClient instance somehow
  val serviceXRestClient = new ServiceXRestClient(ws)
  def apply() = serviceXRestClient
}

so now in my app A I can just do:

object ExternelSerice {
 val serviceXRestClient = ServiceXRestClient()

 def doGet() = {
   serviceXRestClient.doGet()
 }
}

I don’t think you can inject dependency via Provider or direct Injection into scala object unless I missed something.