How to inject into module?

(Kaare Digernes) #1


I’ve got a Play 2.6.6 Java app where I’m using PAC4J and the repository pattern (

In order to configure PAC4J I’m using a module which extends AbstractModule. This module is enabled in application.conf so that it’s run at startup.

I’m configuring PAC4J in the module’s configure() method and there are also two methods for providing the configuration and form client. The form client needs an authenticator which in my case is a user repository (JPA).

My problem is that I’ve been unable to inject my UserRepository instance into my module using the typical methods, i.e. constructor and property injection. The constructor approach is invalid since it changes the method signature on the module so it doesn’t match what Play requires, and the property is simply never set.

I’ve tried binding the UserRepository interface to the implementation in another module that is enabled prior to the PAC4J module, but it didn’t make a difference. Ive also tried binding the module itself and using @ImplementedBy and @Singleton on the repository interface and implementation.

Any controller that injects the user repository works just fine.

I worked around this by doing the following:

  • in the module’s configure() method I get a reference to the provider for the class, e.g. userRepositoryProvider = getProvider(UserRepository.class), and then store it.
  • later when the form client is created, I use the provider reference stored on the module instance to get a reference to a UserRepository instance which I pass on to the authenticator.

This works, but I’m not entirely happy with it as I think it deviates from the conventional approach. Is it possible to do the same in a more typical fashion, e.g. as with controllers, or is this pretty much the way to do it?



(Greg Methvin) #2

It doesn’t make sense to inject dependencies into modules. Modules are meant to specify bindings that are used by Guice to construct your dependency graph. Play requires certain constructors in your module because it only has limited information before the injector is constructed.

You can probably accomplish what you need using a @Provides method or by binding a provider, but it’s hard to give a specific suggestion without seeing code.