I have a module that acquires and holds an API token (simplified):
@Singleton
public class KeyHolderModule extends AbstractModule {
// This doesn't seem to be injected
private @Inject TokenConnector connector;
private DateTime keyLastRefreshed;
private String key;
private Credentials creds = config.getCreds();
@Override protected void configure() {
this.key = connector.getToken(creds);
this.keyLastRefreshed = DateTime.now();
}
@Provides @Named("apiKey") public String getKey() {
// logic to check key last refreshed and handle generating a new one
return this.key;
}
}
I get a null pointer error on the line where I try to access the connector (this.key = connector.getToken(creds);
), so the connector is obviously not getting wired up correctly.
I've tried creating a constructor and using @Inject there, but I'm manually adding these modules via new
to a list in my app bootstrap class, so that's sort of out.
Obviously I'm missing something here -- I could probably just new
up a TokenConnector
in this case since it doesn't have any dependencies itself, but that wouldn't fix my fundamental failure to grasp what's happening here. So if you want to see (simplified) other pieces of code, or less simplified pieces of this code, let me know.
Though you can't use @Inject
for a Module (unless you get the Module from another Injector, which I recommend strongly against), you can easily inject into a @Provides method.
public class KeyHolderModule extends AbstractModule {
private DateTime keyLastRefreshed;
private String key;
private Credentials creds = config.getCreds();
@Override protected void configure() {}
@Provides @Named("apiKey") public String getKey(
TokenConnector connector) {
// logic to check key last refreshed and handle generating a new one
this.key = connector.getToken(creds);
this.keyLastRefreshed = DateTime.now();
return this.key;
}
}
The trick here is that a Module is typically manually instantiated at injector creation time, but @Provides
methods are invoked when the dependencies they provide are needed. Consequently, the Injector isn't ready to provide anything when the Module is constructed, but @Provides
methods invoked throughout the application lifecycle have access to whatever other injector-provided dependencies they might need. When configure
is run the Injector is not yet created, the best you can do is call getProvider
(though you can't call get
on those until the Injector is ready).
I wrote up a variety of other in-Module injection techniques as this SO answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With