How do I configure Google-Guice using a generic interface? - java

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?

Related

Java polymorphism through injection at runtime

I hear that in Java I can achieve polymorphism through injection at runtime. Can someone please show a simple example of how that is done? I search online but I can't find anything: maybe I am searching wrong. So I know about polymorphism through interface and and extension such as
class MyClass extends Parent implements Naming
in such case I am achieving polymorphism twice: MyClass is at once of type Parent and Naming. But I don't get how injection works. The idea is that I would not be using the #Override keyword during injection. I hope the question is clear. Thanks.
So the end result here, per my understanding, is to change the behavior of a method through injection instead of by #Override it during development.
So I know about polymorphism through interface and and extension such as
class MyClass extends Parent implements Naming
This is known as inhertiance and not polymorphism. MyClassis a Parent and MyClass is also a Naming. That being said, inheritance allows you to achive polymorphism.
Consider a class other thanMyClass that also implements Naming :
class SomeOtherClass implements Naming {
#Override
public void someMethodDefinedInTheInterface() {
}
}
Now consider a method that takes a Naming argument somewhere in your code base :
public void doSomething(Naming naming) {
naming.someMethodDefinedInTheInterface();
}
The doSomething method can be passed an instance of any class that implements Naming. So both the following calls are valid :
doSomething(new MyClass());//1
doSomething(new SomeOtherClass());//2
Observe how you can call doSomething with different parameters. At runtime, the first call will call someMethodDefinedInTheInterface from MyClass and the second call will call someMethodDefinedInTheInterface from SomeOtherClass. This is known as runtime-polymorphism which can be achieved through inheritance.
But I don't get how injection works. The idea is that I would not be using the #Override keyword during injection
That's true in the broader sense. To inject something into a class, the class should ideally favor composition over inheritance. See this answer that does a good job in explaining the reason for favoring composition over inheritance.
To extend the above example from my answer, let's modify the doSomething method as follows :
public class ClassHasANaming {
private Naming naming;
public ClassHasANaming(Naming naming) {
this.naming = naming;
}
public void doSomething() {
naming.someMethodDefinedInTheInterface();
}
}
Observe how ClassHasANaming now has-a Naming dependency that can be injected from the outside world :
ClassHasANaming callMyClass = new ClassHasANaming(new MyClass());
callMyClass.doSomething();
If you use the Factory pattern, you can actually chose which subclass gets instantiated at runtime.
Do you think we could have done what we did above using inheritance?
public class ClassIsANaming implements Naming {
public void doSomething() {
someMethodDefinedInTheInterface();
}
#Override
public void someMethodDefinedInTheInterface() {
//....
}
}
The answer is No. ClassIsANaming is bound to a single implementation of the someMethodDefinedInTheInterface method at compile time itself.
`
Taking a contrived example. You have a class Store that stores things:
class Store {
private List l
void store(Object o) {
l.add(o);
}
void setStoreProvider(List l) {
this.l = l
}
}
You can inject the actual List used as the backing storage using setStoreProvider which could be a linked list, array backed list, whatever.
Hence, depending on the injected type your Store class would have the features of the injected type (with regards to memory usage, speed, etc).
This is a kind of polymorphism without the class implementing an interface.

Guice equivalent of Spring's #Autowire list of instances

In spring when I do:
#Autowire
List<MyInterface> myInterfaces;
then this list will get populated by all beans which implement MyInterface. I didn't have to create bean of type List<MyInterface>.
I'm looking for such behaviour in Google Guice.
Sofar I went with:
Multibinder<MyInterface> myInterfaceBinder = MultiBinder.newSetBinder(binder(), MyInterface.class);
Now if I have a bean which implements MyInterface and I bind it, say via:
bind(MyInterfaceImpl.class).asEagerSingleton();
it won't be included in my multibinder. I need to add:
myInterfaceBinder.addBinding.to(MyInterfaceImpl.class);
This is somewhat more complicated than what Spring offers. So I was wonmdering whether I'm not using it in wrong way. So is there easier way of achieving this?
I haven't used it that way myself, yet, but according to Guice's API documentation, I think you should be able to write something not much more than this once:
bindListener(Matchers.subclassesOf(MyInterface.class), new TypeListener() {
public <I> void hear(TypeLiteral<I> typeLiteral,
TypeEncounter<I> typeEncounter) {
myInterfaceBinder.addBinding().to(typeLiteral);
}
}
Then, when you bind an implementation via
bind(MyInterfaceImpl.class).asEagerSingleton();
it should be added to your multibinder automatically.
A hacky solution would be to do it all in a loop:
Multibinder<MyInterface> myInterfaceBinder
= MultiBinder.newSetBinder(binder(), MyInterface.class);
Class<? extends MyInterface>[] classes = {
MyInterfaceImpl,
YourInterfaceImpl.class,
MyCatsInterfaceImpl
};
for (Class<? extends MyInterface> c : classes) {
bind(c).asEagerSingleton();
myInterfaceBinder.addBinding.to(c);
}
It's hacky, it's applicable for such simple cases only, but it's simple and DRY.

Why cannot generic extend a non-generic class in Java?

It looks like a generic class in java cannot extend a regular non-generic class. What is the reason for that? Is there any workaround?
I was mistaken. As ColinD pointed out my problem was actually with exceptions. Can anybody explain why generic exceptions are not allowed in Java?
public class A {
}
public class B<T> extends A {
}
Works without any problems.
Java seems to do it :
public abstract class AbstractCollection<E>
extends Object
implements Collection<E>
Do you have some code, so we can see the problem?
Because exceptions catching require the jvm to know the exact type of exception at runtime (reification) which is not possible in java because all type parameter information is erased by the compiler
You can! - with certain restrictions. Exceptions are one of those restrictions. You can't make them generic. Erasure removes the exception type information preventing the exception hierarchy from working if you threw generic versions of exceptions. Too bad :(.
Consider this:
import org.apache.commons.collections.set.UnmodifiableSet;
import org.apache.commons.beanutils.BeanMap;
//Can't do this:
//public class MyBeanMap<K, V> extends BeanMap implements Map<K,V>{
//Can do this:
public class MyBeanMap<K, V> extends BeanMap {
//Can't make actual method calls return generic types.
public V get(V arg0) {//Name clash
...
return (V)retval;
}
//Also can't do this:
#override
public V get(V arg0) {//Name clash
return (V)retval;
}
}
I guess you could throw UnsupportedOperation exceptions in overridden methods for the existing interface, and implement your own new generic methods:
public V getGeneric(V){
...
}
but that seems a lot uglier than implementing a facade pattern and just extending the map code, but that is a LOT of intermediate code to create a facade for.

Guice - How to get an instance when all you know is the interface

In all of the Guice examples I have found, getting an instance involves calling Injector.getInstance() with the concrete class as a parameter. Is there a way to get an instance from Guice using only the interface?
public interface Interface {}
public class Concrete implements Interface {}
Interface instance = injector.getInstance(Interface.class);
Thanks
Actually that's exactly what Guice is made for.
In order to make getInstance() work with an interface you'll need to first bind an implementation of that interface in your module.
So you'll need a class that looks something like this:
public class MyGuiceModule extends AbstractModule {
#Override
protected void configure() {
bind(Interface.class).to(Concrete.class);
}
}
Then when you create your injector you just need to pass an instance of your module in:
Injector injector = Guice.createInjector(new MyGuiceModule());
Now your call to injector.getInstance(Interface.class) should return a new instance of Concrete using the default constructor.
Of course there are many many more ways you can do bindings but this is probably the most straight forward.
It works for interface as well:
bind( Interface.class ).to( Concrete.class );
Without using a Module, you can also specify the implementation class to be used by default, directly in the interface declaration:
#ImplementedBy(Concrete.class)
public interface Interface {}
This doesn't necessarily fit every situation but I found this comes in handy most of the times.
Additionnally, when using #ImplementedBy annotation, you can still override the implementation class by binding another concrete class in a Module. That can also be useful.

Java Generics, extended Generics and abstract classes

I've got the following classes set up:
public abstract class Process<T,S> {
...
}
public abstract class Resource<T, S extends Process<T, S>> {
protected S processer;
...
}
public class ProcessImpl<EventType1, EventType2> {
...
}
public class ResourceImpl extends Resource<EventType1, ProcessImpl> {
processer = new ProcesserImpl();
...
}
Everything is fine until I get to the ResourceImpl. I'm told that ProcessImpl is not a valid substitute for the bounded parameter <S extends Process<T,S>> of the type Resource<T,S>.
I've tried various ways of getting around this and keep hitting a wall.
Does anyone have any ideas?
public class ProcessImpl<EventType1, EventType2> {
...
}
Because ProcessImpl doesn't extend Process. Your ProcessImpl is not derived from Process, which is what you're declaring that parameter should be.
You might want to do something like this:
public abstract class Process<T, S> {
}
public abstract class Resource<T, S extends Process<T, S>> {
S processor;
}
public class ProcessImpl extends Process<EventType1, ProcessImpl> {
}
public class ResourceImpl extends Resource<EventType1, ProcessImpl> {
}
If you constrain the S parameter of the Resource to be a processor you also need to properly declare it on the ProcessImpl class. I don't know what EventType2 is but it should be implementing Process interface. I assumed you actually want to say ProcessImpl.
I can't see a way to edit the original version, or comment on given answers without a better rep.
This code will exist on a web layer, the eventtype2 is defined on the persistence layer and accessible only in the core layer which exists below this level.
So unfortunately without having a tight coupling, which I would like to avoid, I don't have access to EventType2.
If you don't want your code to depend on some existing package, which contains the Process, you could also introduce some new interface package depending on nothing in the very bottom of the class hierarchy. (If you are able to change the constrains of the inheritance of course.)

Categories

Resources