How to get all implementors/subclasses of an interface with Guice? - java

With Spring, you can define an array property and have Spring inject one of every (#Component) class that derives from the given type.
Is there an equivalent for this in Guice? Or an extension point to add this behavior?

This looks like a use case for Guice MultiBinder. You could have something like that:
interface YourInterface {
...
}
class A implements YourInterface {
...
}
class B implements YourInterface {
...
}
class YourModule extends AbstractModule {
#Override protected void configure() {
Multibinder.newSetBinder(YourInterface.class).addBinding().to(A.class):
Multibinder.newSetBinder(YourInterface.class).addBinding().to(B.class):
}
}
And you can inject a Set<YourInterface> anywhere:
class SomeClass {
#Inject public SomeClass(Set<YourInterface> allImplementations) {
...
}
}
That should match with what you need.

Guice Multibindings require you to explicitly addBinding() for A & B to YourInterface. If you would like a more "transparent" (automatic) solution such as what AFAIK Spring offers out-of-the-box, then assuming that Guice already knows about A & B because you already have a binding for A & B elsewhere anyway, even if not explicit but just implicit e.g. through an #Inject somewhere else, then and only then you alternatively could use something like this for auto-discovery (inspired by as done here, based on accessing Guice injector in a Module):
class YourModule extends AbstractModule {
#Override protected void configure() { }
#Provides
#Singleton
SomeClass getSomeClass(Injector injector) {
Set<YourInterface> allYourInterfaces = new HashSet<>();
for (Key<?> key : injector.getAllBindings().keySet()) {
if (YourInterface.class.isAssignableFrom(key.getTypeLiteral().getRawType())) {
YourInterface yourInterface = (YourInterface) injector.getInstance(key);
allYourInterfaces.add(yourInterface);
}
return new SomeClass(allYourInterfaces);
}
}
Note again that this approach does NOT require any classpath scanning; it just looks at all already known bindings in the Injector for anything that IS-A YourInterface.

Kotlin
Class SomeModule : AbstractModule() {
override fun configure() {
val myBinder: Multibinder<MyInterface> = Multibinder.newSetBinder(binder(), MyInterface::class.java)
myBinder.addBinding().to(Implementation1::class.java)
myBinder.addBinding().to(Implementation2::class.java)
}
Usage
#Inject constructor(private val someVar:Set<#JvmSuppressWildcards MyInterface>)

Related

Google Guice - Classes must have either one (and only one) constructor annotated with #Inject or a zero-argument constructor that is not private

all
I have some questions regarding Google Guice. Any help is appreciated.
I have a handler interface and an implementation of it.
public interface Handler {
void handle();
}
public class HandlerImpl implements Handler {
private Filter filterOne;
#Override
void handler() {
filterOne.foo();
}
}
Filter is another interface:
public interface Filter {
void foo();
}
There are multiple implementation of it.
public class FilterOne implements Filter {
void foo() {
}
}
public class FilterTwo implements Filter {
void foo() {
}
}
Then in my Guice module:
public class HandlerModule extends AbstractModel {
#Override
protected void configure() {
bind(Handler.class).to(HandlerImpl.class);
}
#Provides
#Singleton
public Handler provideHandler(#Named("filterOne")filter filterOne) {
return new HandlerImpl(filterOne);
}
#Provides
#Singleton
#Named("filterOne")
public Filter provideFilterOne() {
return new FilterOne();
}
#Provides
#Singleton
#Named("filterTwo")
public Filter provideFilterTwo() {
return new FilterTwo();
}
}
With above implementation, I'm always getting the error - Could not find a suitable constructor in HandlerImpl. Classes must have either one (and only one) constructor annotated with #Inject or a zero-argument constructor that is not private.
I'm using #Named to differ two filters. Am I using it wrong?
Is it because I have two implementations of Filter and the Guice cannot tell which one to use when try to provide the HandlerImpl?
You are binding Handler.class twice:
In configure() method: bind(Handler.class).to(HandlerImpl.class);
As a provider:
#Singleton
public Handler provideHandler(#Named("filterOne")filter filterOne) {
return new HandlerImpl(filterOne);
}
The first of these bindings can't work, since HandlerImpl doesn't have a constructor annotated with #Inject. If you fix it though, it still won't work - you can't provide multiple bindings for the same key.
TL;DR: remove the bind(Handler.class).to(HandlerImpl.class); from the configure() method

How can I inject for generic inherited types?

I spent a plenty of time for finding any answers, but I think I have to ask.
I'm using Weld-SE for testing my entities.
I prepared entity randomizer for testing.
abstract class BaseEntityRandomizer<T extends BaseEntity>
implements Randomizer<T> {
#Override public T getRandomValue() {
...
}
}
class MySomeOtherEntityRandomizer
extends BaseEntityRandomizer<MySomeOther> {
#Override public MySomeOther getRandomValue() {
...
}
}
Now, with my test class, I want to inject those randomizers which each matches generic parameters
#ExtendWith(WeldJunit5Extension.class)
#AddPackages({BaseEntityRandomizer.class})
abstract class BaseEntityTest<T extends BaseEntity> {
#Test void doSome() {
}
#Inject
private BaseEntityRandomizer<T> entityRandomizer;
}
class MySomeOtherTest extends BaseEntityTest<MySomeOther> {
...
// I expect an instance of MySomeOtherRandomizer in injected
// into the entityRandomizer field.
}
Subclasses of randomizers and tests are prepared.
But I failed to make it work.
How can I make it work?
I tried with following factory class
class BaseEntityRandomizerFactory {
#Produces
public BaseEntityRandomizer<MySome> produceMySomeRandomizer() {
return new MySomeRandomizer();
}
}
I got
org.jboss.weld.exceptions.IllegalArgumentException:
WELD-001408: Unsatisfied dependencies for type BaseEntityRandomizer<T extends BaseEntity> with qualifiers #Default
at injection point [BackedAnnotatedField] #Inject protected transient ....BaseEntityTest.entityRandomizer
at ....BaseEntityTest.entityRandomizer(BaseEntityTest.java:0)
One way to achieve this is to use CDI Programmatic lookup. In your case, I'd start with #Inject Instance<Object> and then you can use subsequent calls to select() and get() methods to pick up whichever bean you desire. Usage looks something like this (assumes existence of beans with types Foo, Bar and List<String>):
#Inject
private Instance<Object> instance;
#Test void doSome() {
// selecting and obtaining instances of beans
Foo foo = entityRandomizer.select(Foo.class).get();
Bar bar = entityRandomizer.select(Bar.class).get();
// in case you need to select a parameterized type from instance, use TypeLiteral
List<String> listBean = entityRandomized..select( new TypeLiteral<List<String>>(){}).get()
}

How to implement the "robot legs" use case with Google Guice?

I'm learning Google Guice. Do you know how to implement the "robot legs" problem? Let me explain this with an example.
Let's say that I have some class called Service:
#Singleton
public class Service {
#Inject
Source source;
}
The interface Source has two implementations:
public class SourceDatabase implements Source {
}
public class SourceFileSystem implements Source {
}
My module is implemented like this:
public class MyModule extends AbstractModule {
#Override
protected void configure() {
bind(Service.class).asEagerSingleton();
}
}
Well, I would like to know if this is possible:
public class MainClass {
#Inject #SomeAnnotation("database")
Service serviceWithADatabaseSource;
#Inject #SomeAnnotation("file-system")
Service serviceWithAFileSystemSource;
}
Does exist some annotation or binding that let me do that, let me annotate a member like serviceWithADatabaseSource, and this helps Guice to know that the internal member source should be injected with the SourceDatabase implementation?
Edit: Thanks to Daniel Martin, for give us the name of this kind of problem on his comment.
As documented in the Guice Wiki, you need to install two PrivateModules, each of which exposes a Service with the right annotation for you.
public class MyModule extends AbstractModule {
#Override
protected void configure() {
install(new PrivateModule() {
#Override public void configure() {
// Bind Source to SourceDatabase.
bind(Source.class).to(SourceDatabase.class);
// Bind #Named("database") Service to Service.
bind(Service.class).annotatedWith(Names.named("database"))
.to(Service.class);
// Now expose #Named("database") Service without exposing
// either of the other two conflicting bindings.
expose(Service.class).annotatedWith(Names.named("database"));
}
});
install(new PrivateModule() {
#Override public void configure() {
// Same as above.
bind(Source.class).to(SourceFileSystem.class);
bind(Service.class).annotatedWith(Names.named("file-system"))
.to(Service.class);
expose(Service.class).annotatedWith(Names.named("file-system"));
}
});
}
}
If the modules were not PrivateModule instances, those bindings to Source and Service would conflict with one another. However, instead, each binding inherits all the public bindings from the Injector but only exposes the #Named(...) Service to the outside world. This way the same Service implementation can inject the same non-annotated Source but have it return different fully-injected types.
Also note that you will not be able to ask for a Source or Service (without an annotation) outside of the PrivateModules, because you haven't established a binding in any non-private Module. This should be expected: The PrivateModule bindings shouldn't conflict with any public bindings, and without entering through one of the PrivateModule's exposed bindings, Guice won't know which Source or Service to return.
Finally, given that Module instances can take constructor parameters, it may be a good idea to extract the two anonymous inner PrivateModules into a named equivalent:
public class MyModule extends AbstractModule {
#Override
protected void configure() {
install(new SourcePrivateModule(SourceDatabase.class, "database"));
install(new SourcePrivateModule(SourceFileSystem.class, "file-system"));
}
}

In guice is there a difference between #provides and bind()?

I am wondering what the difference is between using #provides on a method and using bind() in my guice modules.
I usually override AbstractModule.configure() and bind all my implementations to my interfaces like this:
public class MyModule extends AbstractModule
{
#Override
protected void configure()
{
this.bind(myIface.class).to(myIfaceImpl.class);
this.bind(myOtherIface.class).to(myOtherIfaceImpl.class).asEagerSingleton();
}
...
}
However, I have noticed a pattern in the codebase I'm currently working with where implementations aren't bound explicitly they are being returned from providers like this:
public class MyModule extends AbstractModule
{
#Provides
#Singleton
myIface iFaceProvider()
{
return new myIfaceImpl();
}
...
}
Is there a reason to prefer one over the other? Are there cases that force a particular method?
If you do
bind(MyInterface.class).to(MyImplementation.class)
Guice creates the instance for you. This enables certiain things like AOP. If you do
#Provides
MyInterface provideMyInterface() {
return new MyImplementation();
}
then Guice didn't create the instance so AOP won't work. Also, it requires an accessible constructor for MyImplementation. Generally, this form is only used when you can't edit MyImplementation to make it Guice-compatible.
There's a third form:
#Provides
MyInterface provideMyInterface(MyImplementation impl) {
return impl;
}
which is almost totally equivalent to the bind(...).to(...) form. It is commonly used in frameworks like Dagger that do not have the bind syntax.

Guice wrap generic injections

Is it possible to wrap generic injections in some way?
Given the interface:
interface IFoo<T>
In my guice module:
bind((Key<IFoo<SomeType>) Key.get(Types.newParameterizedType(IFoo.class, SomeType.class))).to(Foo.class);
But before I return the Foo instance I want to wrap it with this:
class FooWrapper<T> implements IFoo<T> { public FooWrapper(Foo<T> foo) { ... } }
Somewhere like this:
return new FooWrapper<T>(foo);
Here's one way you can do this:
public class FooModule extends PrivateModule {
#Retention(RUNTIME) #BindingAnnotation
private #interface Internal {}
#Override protected void configure() {
bind(new TypeLiteral<IFoo<SomeType>>(){}).annotatedWith(Internal.class)
.to(new TypeLiteral<Foo<SomeType>>(){});
}
#Provides #Exposed IFoo<SomeType> provideFoo(#Internal IFoo<SomeType> foo) {
return new FooWrapper<SomeType>(foo);
}
}
Another thing that might work well would be to add a general annotation like #Wrapped and then to declare FooWrapper's constructor like this:
#Inject public FooWrapper(#Wrapped IFoo<T> foo) { ... }
Then in your private module you could bind Foo annotated with #Wrapped and bind and expose FooWrapper normally, without needing to use an #Provides method.
There may well be better ways of doing this I haven't thought of yet. Do also keep in mind that method interception is often a good way of decorating interface implementations with other behavior as well.

Categories