Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access Play Framework 2.4 guice Injector in application?

I want to use the getInstance method of the Guice Injector class in Play Framework 2.4, how can I access it?

I have used the Guice FactoryModuleBuilder for implementing a factory that returns another factory at runtime! At the second level of returning a factory I need to access the Play Guice Injector to get objects manually using reflection instead of @Inject annotation.

like image 602
Saeed Zarinfam Avatar asked Jan 19 '16 05:01

Saeed Zarinfam


4 Answers

With Play Framework 2.5.x play.api.Play.current is deprecated and DI should always be preferred. Therefore proper way of getting injector instance is by using:

import play.api.inject.Injector
import javax.inject.Inject

class SomeClassRequiringInjector @Inject() (injector: Injector) { ... }

Works for me even when doing this with DI Provider class :)

like image 72
Egregore Avatar answered Nov 16 '22 00:11

Egregore


There are many ways. I use this one.

Edit: This is relevant for Play versions which are <= 2.4:

Play.maybeApplication.map(_.injector.instanceOf[MyProdClass]).getOrElse(new MyDevClass)

or

Play.current.injector.instanceOf[MyClass]

For versions which are >= 2.5:

import play.api.inject.Injector
import javax.inject.Inject

class MyService @Inject() (injector: Injector) ={
    val myClassInstance = injector.instanceOf[MyClass]
    //do stuff
}
like image 27
Tomer Avatar answered Nov 16 '22 01:11

Tomer


It is better to inject Guice Injector:

@Inject
private Injector injector;

Or you can use this code for Play Framework Java edition:

Play.application().injector().instanceOf(YourClass.class);
like image 42
Saeed Zarinfam Avatar answered Nov 16 '22 02:11

Saeed Zarinfam


Apart from the other Play 2.5.x solutions, there may be a situation in which you want to get the Injector in an object without using injection. For example when you're using a Scala singleton, for which @inject probably doesn't work.

In that case, you can use this:

@Singleton
class GlobalContext @Inject()(injector: Injector) {
  GlobalContext.injector = injector
}

object GlobalContext {
  private var injector: Injector = null  
}

With a Guice module to set the singleton to eager, otherwise it won't be initialized automatically:

// Module.scala
class Module extends AbstractModule {
  override def configure() = {
    // ...

    // Eager initialize Context singleton
    bind(classOf[GlobalContext]).asEagerSingleton()
  }
}
like image 34
Devabc Avatar answered Nov 16 '22 00:11

Devabc