Reputation: 1308
I instantiated using dependency injection in my controller class. When i try to use that object using @inject annotation elsewhere, i get null value. Here is my code skeleton.
@singleton
class ServiceClient(ws: WSClient, config: Configuration) {
def get response() {...}
}
class App @Inject()(client: ServiceClient) extends Controller {
def getItems = Action {
Obj()
}
}
case class Obj() {
@Inject
var client: ServiceClient = _
def doStuff() {
client.getResponse() //client is null so get null pointer exception.
....
}
}
The @Inject in Obj never seems to be working. and my client object is always null. (I do not want to pass client as param to Obj.) My expectation was that ServiceClient object created in controller should have been injected in Obj(). What did i do wrong?
update
Injecting Obj to the controller, is not an option. (In my app Obj are instantiated at run time my some complicated rule, using reflection).Also i dont want to have the constructor injection in the Obj. I am looking for field injection of ServiceClient outside of the controller.
update2
I was able to solve the problem using
var client: ServiceClient = play.api.Play.current.injector.instanceOf(classOf[ServiceClient])
in the Obj class. However, play.api.Play.current is deprecated in play 2.5 so i am still kind of stuck with a warning.
Upvotes: 0
Views: 1137
Reputation: 401
You cannot inject dependency into the class instance without asking about it the DI framework. In your code you manually instantiate Obj
which means the dependency injection magic is not happening. In order to inject dependency to Obj
class its instantiation should be handled by the DI framework. What you can do here is:
Inject ServiceClient
to either Obj
constructor or filed:
class Obj @Inject() (client: ServiceClient) {
//
}
It makes sense to use simple class instead of case class because case class sounds more like "data" class with immutable data inside rather than service or some helper class. Actually, your current definition of Obj
class should work.
Inject Obj
and (or, depending on your needs) ServiceClient
to your App class:
class App @Inject()(obj: Obj, client: ServiceClient) extends Controller {
def getItems = Action {
obj.doStuff()
}
}
I'd recommend you to read more about dependency injection and Guice framework which is used in Play by default. Guice wiki
Upvotes: 1