Is there any way to check if an implementation exists for an interface?
For example, the method "hasBind" below does not exist:
public class MyModule extends AbstractModule {
#Override
protected void configure() {
// do something like this:
if (!hasBind(SomeInterface.class)) {
bind(SomeInterface.class).to(MyOtherSomeInterface.class);
}
}
}
Since the order of applied modules does not matter in guice, you cannot detect if a binding exists before the injector was created, see this post.
The proposed solution is to create a starting module with default bindings and use Modules.overwrite to apply ypur additional bindings.
Related
I use com.google.inject:guice. In my project, I included a dependency that have a module (a class that extends com.google.inject.AbstractModule) that defines a MapBinder like that
public class ParentGuiceModule extends AbstractModule {
#Override
protected void configure() {
MapBinder.newMapBinder(binder(), TypeLiteral.get(String.class), TypeLiteral.get(SomeModuleClass.class));
...
}
}
In my module class, I want to get that MapBinder and add new bindings to it. I mean I want to write something like that:
public class MyGuiceModule extends AbstractModule {
#Override
protected void configure() {
MapBinder<String, SomeModuleClass> parentModules = MapBinder.get(binder(), TypeLiteral.get(String.class), TypeLiteral.get(SomeModuleClass.class));
parentModules.addBinding("MyId").to(MyClass.class);
}
}
How can I do that? I can not change the parent module.
I looked into MapBinder class, seems it does not have any methods to get already installed MapBinder.
This is exactly what MapBinder is designed for—after all, if you knew everything that was going to be inside a MapBinder from within a single Module, you could just write #Provides Map<Foo, Bar> or bind(new TypeLiteral<Map<Foo, Bar>>(){}) and be done with it.
From the MapBinder top-level docs:
Contributing mapbindings from different modules is supported. For example, it is okay to have both CandyModule and ChipsModule both create their own MapBinder<String, Snack>, and to each contribute bindings to the snacks map. When that map is injected, it will contain entries from both modules.
Don't be discouraged by the name newMapBinder: As long as you have the exact same parameters to newMapBinder and have both of your Modules installed in the same Injector, you will wind up with one Map that contains bindings from both modules.
I have a Guice based project using vanilla Guice;
no Assisted-Inject, no AOP, no extra plugin extending Guice, etc.
To run it more easily on Android, Dagger seems like a better solution.
Every class has a dependency and a constructor with #Inject annotation.
No field or method injection is used.
The modules are quite simple (making Guice an overkill) and mostly contain bindings like the following:
class SomethingModule extends AbstractModule {
protected void configure() {
Bind(Handler.class)
.annotatedWith(Names.named("something"))
.to(SomeImplementation.class);
}
}
}
And later used like the following:
Injector inj = Guice.createInjector(new SomethingModule());
... = inj.getInstance(SampleInterface.class);
// and rest of the code.
Unfortunately,
I can not get my head around Daggers terminology.
Can you guide me with a direct translation / transformation of a Guice module to a Dagger module?
Dagger has:
Dagger's Components.
Dagger's Modules.
#Provides
#Inject
Guice has:
#Inject
#Named (or any custom annotation, if implemented correctly).
Our modules extending AbstractModule.
#Provides in the modules.
Guice Injector created from modules.
How do these relate?
Update: In addition to the nice answer by EpicPandaForce, these slides can help too.
Bind(Handler.class)
.annotatedWith(Names.named("something"))
.to(SomeImplementation.class);
Would translate to
#Module
public class SomethingModule {
#Provides
#Named("something")
//scope if needed
public Handler handler() {
return new SomeImplementation();
}
}
Which would be bound to an "Injector" (component):
#Component(modules={SomethingModule.class})
//scope if needed
public interface SomethingComponent {
#Named("something")
Handler handler();
void inject(ThatThingy thatThingy);
}
Which is an "injector" that you have to create with the APT-generated builder:
SomethingComponent somethingComponent = DaggerSomethingComponent.builder()
.somethingModule(new SomethingModule()) //can be omitted, has no params
.build();
somethingComponent.inject(thatThingy);
Where that thingy has
public class ThatThingy {
#Inject
#Named("something")
Handler handler;
}
Components typically exist per scope, so for example #ApplicationScope has one "injector" (component). Scoping can be achieved with subcomponents and component dependencies.
Important fact, a component has provision methods (which are the dependencies that are inherited to subscoped components if you use component dependencies), and void inject(X x); formatted methods. This is required for field injection per concrete type. A base class for example can only inject itself, and not its subclasses. You can however write a method called protected abstract void injectThis() which would call the .inject(this) on the subclass as well.
As I haven't really used Guice, I'm not sure if I missed out on anything. I think I forgot constructor injection, which is an issue because while Dagger does support it, it cannot be reconfigured. For reconfiguration, you have to use modules, and do the injection in the constructors yourself.
#Module(includes={ThoseModule.class, TheseModule.class})
public abstract class SomethingModule {
#Binds
abstract Whatever whatever(WhateverImpl impl);
}
#Singleton
public class WhateverImpl implements Whatever {
Those those;
These these;
#Inject
public Whatever(Those those, These these) {
this.those = those;
this.these = these;
}
}
#Component(modules={SomethingModule.class})
#Singleton
public interface SomethingComponent {
These these();
Those those();
Whatever whatever();
}
I have a use case where it appears that referencing a Guice injector from multiple locations is the only solution—though this is generally discouraged.
My application is built on top of Talend, an open source ETL platform. Most of my actual application is in Java classes that are called by Talend components. These components include Java snippets that I write and that, in turn, instantiate/invoke my classes.
Now I intend to use Guice throughout my Java classes but there is absolutely no way for me to inject dependencies into the Talend components (so that they would be available to the Java snippets). Instead, I need to actually create these dependencies. I’d like to at least have Guice control the instantiation, which means that instead of using new, it appears that the only way I can instantiate my classes (the ones with #Inject constructors) is to call injector.getInstance. This, in turn, implies that I need to keep the injector around, presumably using an old-fashioned factory that creates it in the first place and makes it available as a singleton.
I just can’t see any other way to handle this but perhaps I’m missing something.
Consider static injection. This will still hide persistent references to your injector across your app, but it will save you from having to pepper your code with injector.getInstance(...) calls. In any case you can inject Injector if you really need to.
class TalendDependencyModule extends AbstractModule {
#Override public void configure() {
requestStaticInjection(ExtractorDependencies.class);
requestStaticInjection(ProcessorDependencies.class);
}
}
public class ExtractorDependencies {
#Inject private static Provider<ParserService> parserServiceProvider;
#Inject private static Provider<SomethingElse> somethingElseProvider;
private ExtractorDependencies() { }
static ParserService getParserService() {
return parserServiceProvider.get();
}
/* ... */
}
I don't know how many Talend objects you have but you might want to consider using providers. For instance suppose you have your own class that you want Guice to manage creation of:
public interface INotTalendControlled {}
public class NotTalendControlled implements INotTalendControlled {}
This will be added to a Talend object whose dependencies cannot be injected via Guice (although I assume there is some manual process for doing so either constructor or setter):
public class TalendControlled {
private INotTalendControlled notTalendControlled;
private TalendControlled(INotTalendControlled notTalendControlled) {
this.notTalendControlled = notTalendControlled;
}
public INotTalendControlled getValue() {
return notTalendControlled;
}
}
If you want Guice to manage these lifecycles and the lifecycle of Talend controlled objects you can use a provider like so:
public static class TestModule extends AbstractModule {
#Override
protected void configure() {
bind(INotTalendControlled.class).to(NotTalendControlled.class);
}
#Provides
public TalendControlled provideInjectsToTalendObject(INotTalendControlled notTalendControlled) {
return new TalendControlled(notTalendControlled);
}
}
The #Provides method will hide of the use of new for all objects as you can now directly inject TalendControlled objects (#Inject TalenControlled talendControlled) and an explicit injector is not needed to construct their dependencies.
I have a bunch of entity type factories that derive from a common, generic interface. For instance,
public class ConnectionFactory implements IEntityFactory<Connection> { ... }
I'd like to use Google-Guice to break hard dependencies on these factories.
However, there's a syntax error when I try to configure Guice:
public class EntityFactoryModule extends AbstractModule {
#Override
protected void configure() {
bind(IEntityFactory<Connection>.class).to(ConnectionFactory.class);
}
}
Eclipse says "IEntityFactory cannot be resolved to a variable."
Can someone please help me understand why this doesn't work? Also, is there an alternate syntax that will work?
My Guice-fu is generally limited, but I think you want a type literal here:
bind(new TypeLiteral<IEntityFactory<Connection>>() {})
.to(ConnectionFactory.class);
One method is to declare a new interface:
interface IConnectionFactory extends IEntityFactory<Connection> { ...}
Then I can do:
bind(IConnectionFactory.class).to(ConnectionFactory.class);
But, there's already an interface explosion going on in my project.
Is there a better way?
I'm trying to inject things with Google Guice 2.0 and I have the following structure:
FooAction implements Action
BarAction implements Action
I then have an ActionLibrary with the following constructor:
ActionLibrary (List<Action> theActions)
When I request an instance of ActionLibrary from Guice, I would like Guice to identify both of the registered Action classes (FooAction, BarAction) and pass them into the constructor. The motivation here being that when I add a third action BazAction, it would be as simple as registering it in the Module and it would automatically be added to the list in the constructor.
Is this possible?
What you want for this is Multibindings. Specifically, you want to bind a Set<Action> (not a List, but a Set is probably what you really want anyway) like this:
Multibinder<Action> actionBinder = Multibinder.newSetBinder(binder(), Action.class);
actionBinder.addBinding().to(FooAction.class);
actionBinder.addBinding().to(BarAction.class);
Then you can #Inject the Set<Action> anywhere.
Let me show you what I consider an even better way of multibinding things. If you want Actions to be pluggable and let anyone add them, it's often useful to provide a simple Module for someone to use that hides needing to instantiate the Multibinder. Here's an example:
public abstract class ActionModule extends AbstractModule {
private Multibinder<Action> actionBinder;
#Override protected void configure() {
actionBinder = Multibinder.newSetBinder(binder(), Action.class);
configureActions();
}
/**
* Override this method to call {#link #bindAction}.
*/
protected abstract void configureActions();
protected final LinkedBindingBuilder<Action> bindAction() {
return actionBinder.addBinding();
}
}
Now why is this better? It allows someone to use an ActionModule from anywhere to add more Actions via the standard binding API. I think it's more readable. Here's an example usage:
public final class MyStandardActionModule extends ActionModule() {
#Override protected void configureActions() {
bindAction().to(FooAction.class);
bindAction().to(BarAction.class);
// If you need to instantiate an action through a Provider, do this.
bindAction().toProvider(BazActionProvider.class);
// You can also scope stuff:
bindAction().to(MySingletonAction.class).in(Singleton.class);
}
}
This pattern of using a Module to hide the multibinder is used in Guice code. It's a little work up front, but keeps things clean. You can also do something similar for a MapBinder if you need to. Keep in mind you can instantiate as many ActionModules as you want.