Eclipse RCP - Injecting interfaces marked with #Singleton - java

I have the following code:
public interface DummyInterface {
}
and
#Singleton
#Creatable
public class DummyInterfaceImpl1 implements DummyInterface {
}
And when I want I can simply inject this, and it works just fine, (see below):
#Inject
DummyInterfaceImpl1
However I can't do
#Inject
DummyInterface
Because I get an
Unable to process "ClassWhereIInject.dummyInterface": no actual value was found for the argument "DummyInterface".
So, I am trying to understand, if I use the combination of #Creatable and #Singleon, without adding the instance that I want to inject in the IEclipseContext, then I can only inject implementation classes and not interfaces?
I can see how this can get problematic, especially when one has multiple implementation classes for the same interface, and the dependency injection framework doesn't know which to inject...that is if you don't use the #Named annotation to specify...

The injection system only looks for something with the name you specify. It does not try and find a class that happens to implement that interface. So no you can't use an #Creatable class with a different name to the interface.
An alternative is to use a 'ContextFunction'. This is a function which is called when the injection system is looking for a name. The context function can create an instance of something suitable and put it in the context for the injector. Full details on context function are here

Related

WELD-001409: Ambiguous dependencies for type T with qualifiers #Default

I got 2 beans.
The first one is the model I use in production, Model.
#Named("model")
#RequestScoped
public class Model{
}
The second one is the extension of Model that I use for testing.
#Named("modelTest")
#RequestScoped
public class ModelTest extends Model{
}
How can I force CDI to select Model by default?
Since you want to change the 'default' bean for given type and you don't want to use qualifiers, I assume the original bean is not to be injected anywhere. Therefore, what you are probably after is either an alternative or a specialization.
If we talk about alternatives, you need to mark the new bean with #Alternative annotation and also 'select' it - that can be done on a per bean archive basis in beans.xml or simply globally with #Priority(int). Here is a code snippet:
#Named("modelTest")
#RequestScoped
#Alternative
#Priority(1) // "activates"/selects the alternative
public class ModelTest extends Model{
}
With a selected alternative, whenever you inject the previous type (Model), CDI will instead inject this alternative (ModelTest), as it fits the injection point as well.
Secondary option is specialization. It is very similar to alternatives but stricter in a way that the original bean is 'discarded', you can read more about that in CDI spec. Specialization also comes with qualifier and bean name inheritance (not the scope though!). There is also no need to select the bean (as opposed to alternatives). Here is the code:
#RequestScoped
#Specializes
public class ModelTest extends Model{
// bean name with be inherited automatically as "model"
}
Note that a bean can only have one bean name at a time, as per specification. Therefore if you inherit one name and declare another, you will be getting errors - alter your code accordingly.

GUICE - at runtime decide on object graph

I'm reviewing Guice. Let's say I've got the following setup:
public interface IsEmailer {...}
public interface IsSpellChecker {...}
public class Emailer implements IsEmailer {
#Inject
public class Emailer(final IsSpellChecker spellChecker)....
}
public class FrenchSpellChecker implements IsSpellChecker {....}
public class EnglishSpellChecker implements IsSpellChecker {....}
#BindingAnnotation public #interface English {}
#BindingAnnotation public #interface French {}
Then in my module I've bound the interfaces to their respective implementations, and annotated the spell checkers with the respective binding-annotation.
Now, let's say based on a runtime variable I need to construct an emailer that either uses the English or the French spell checker.
I thought of using a named providers in my module:
#Provides
#English
IsEmailer provideEnglishEmailer() {
return new Emailer(new EnglishSpellChecker());
}
#Provides
#French
IsEmailer provideFrenchEmailer() {
return new Emailer(new FrenchSpellChecker());
}
This works like this:
IsEmailer emailer = myModule.getInstance(Key.get(IsEmailer.class,
French.class));
Is this the cleanest way to do something like this? After all, I'm forced to construct the object by hand (in the providers).
Thanks
First some notes:
Generally you want to avoid using getInstance as much as possible, except for your "root" element (e.g. YourApplication). Within anything that Guice provides, your best bet is to ask for an injection of Provider<IsEmailer>, or perhaps #English Provider<IsEmailer> and #French Provider<IsEmailer>. Guice will not actually create the elements until you call get on the Provider, so the overhead of creating the Provider is very very light.
You don't have to bind to a provider to get a provider. Guice will resolve any binding of X, Provider<X>, or #Provides X to any injection of X or Provider<X> automatically and transparently.
Provider implementations can take injected parameters, as can #Provides methods.
If you want to bind a lot of things to #English or #French, you may also investigate private modules, since this sounds like the "robot legs" problem to me.
The easiest way is simply to go with the first bullet and inject a Provider of each, especially if you're only doing this once.
You can also bind it in a Module, if your runtime variable is accessible via Guice. Put this in your module along with the #Provides annotations above. (As noted, you may want to rewrite them to accept an EnglishSpellChecker and FrenchSpellChecker as parameters respectively, to enable the spell checkers to inject their own dependencies.)
#Provides IsEmailer provideEmailer(Settings settings,
#English Provider<IsEmailer> englishEmailer,
#French Provider<IsEmailer> frenchEmailer) {
if (settings.isEnglish()) {
return englishEmailer.get();
} else {
return frenchEmailer.get();
}
}
You could use a MapBinder. That would allow you to inject a Map<Language, IsSpellChecker>, and then retrieve the appropriate spell checker at runtime.

Camel SimpleRegistry and DI

If I have an OrderHandler interface:
public interface OrderHandler {
public void handle(Order order);
}
And have several implementations (DefaultOrderHandler, ComplexOrderHandler, SpecialOrderHandler, etc.) of it, how do I specify which one to use in Camel's SimpleRegistry? For instance, if I have the following route:
from("direct:pointA")
.bean(OrderHandler.class)
.to("direct:pointB");
How do I specify a SimpleRegistry, and how do I configure that registry to "inject" a DefaultOrderHandler when I specify a processor of type bean(OrderHandler.class)?
I ask because it would be nice (for unit testing) to be able to inject a DummyOrderHandler during testing, and a real impl during production. Thanks in advance!
When using
bean(MyClass.class)
Then usually the class type (eg MyClass.class) must be a class (not abstract, not interface) as Camel will use that to instantiate an instance.
However if the method that is being invoked is a static method, then Camel does not need to instantiate an object, and therefore the class can be abstract etc. You can supply the method name as a 2nd parameter to pint point which method to call.
In your case have 3 different implementations of an interface. You need to specify the type to use
bean(MyImpl.class)
Or refer to a bean by a name to lookup in the registry, or provide an object instance
For example:
OrderHandler handler = new DummyOrderHandler;
...
bean(handler)
As its just Java code, and if you are using RouteBuilder then you can juse have getter/setter for OrderHandler, and then set the desired implementation on RouteBuilder
RouteBuilder myBuilder = new MyRouteBuilder();
myBuilder.setOrderHandler(new DummyOrderHandler());
...
And then in the configure method in MyRouteBuilder you can use
bean(handler)

Howto inject simple config parameters to beans using Guice?

Is there a simple way to inject simple primitive type parameters (string and int) to the beans?
What i need is to find the guice equivalent of something like this from spring.xml:
<bean id="aBean" ...>
<property name="fieldName" value="aStringValue"/>
<property name="anotherFieldName" value="123"/>
</bean>
The values could be constructor injected, field injected or method injected, but i don't want to use separate named annotation or factory or provider for every value that i need to pass to the bean.
EDIT: my solution
Here is what i finally came to. I think it is closest to what i'm looking for, but any improvements would be welcome.
I found that in the module, i can declare a provider method and use it to set any properties i need:
MyModule extends AbstractModule{
...
#Provides #Named("testBean") MyTestBean createTestBean(MembersInjector<TestBean> mi){
TestBean test = new TestBean();
mi.injectMembers(test);
test.setFieldName("aStringValue");
test.setAnotherFieldName(123);
return test;
}
...
}
The good point is that the Provides method replaces the bind() for the bean and this way the actual line count doesn't increase much.
I'm still not 100% sure about any side effects, but it looks promising.
There is a build in mechanism to inject properties.
Properties File:
name=jan
city=hamburg
Module
#Override
protected void configure() {
Names.bindProperties(binder(), properties);
}
then in your bean, just inject by Name
class Customer {
#Inject
#Named("name")
String name;
....
}
There are a couple different ways you could do this, including your way. The only drawback to using a Provider method is that it's essentially a hand-rolled factory that you have to remember to maintain. (And in this specific case, you're also not getting the benefits of constructor injection).
Absent a Provider method, you have to use a binding annotation of some kind. If #Named won't work for you, then you'd need to create an annotation for each binding.
bindConstant().annotatedWith(FieldName.class).to("aStringValue");
public SomeClass {
public void setFieldName(#FieldName String fieldname) {}
}
In some cases this might require a 1-to-1 annotation per primitive/String instance to be bound. But I try to make my annotations somewhat orthogonal to the actual instance being described, preferring instead to use the annotation to describe the relationship between the bound objects and the injection points.
It's not always possible, but a whole group of related primitives could then potentially be described by a single binding annotation, as long as each primitive type is only used once in the set. So, this could hypothetically work:
bindConstant().annotatedWith(MyAnnotation.class).to("aStringValue");
bindConstant().annotatedWith(MyAnnotation.class).to(123);
Parenthetically, I'm curious why you can't used #Named annotations on the property, but you can use them on the injected bean?

Guice Inject Field in class not created by Guice

I have a class like so, that I create myself somewhere in my code:
class StarryEyes {
#Inject MyValidator validator;
public StarryEyes(String name) {
//..
}
public doSomething() {
// validator is NULL
}
}
I want Guice to inject an instance of validator, which has a #Singleton annotation.
I have a module that's loaded at startup and it contains the line:
bind(MyValidator.class);
However, it doesn't seem to work as "validator" is always null. I've tried a number of variations like:
bind(MyValidator.class)toInstance(new MyValidator());
or other things like that. Is this not how Guice is supposed to work?
Typically Guice needs to create objects to inject them. If you just call new StarryEyes(name), Guice isn't ever going to see that object so it won't be able to inject it. One thing you can do is to call injector.injectMembers(obj) on the object after you've created it. I wouldn't recommend that, though, as you should avoid referencing the injector in your code.
What you really probably want here is Assisted Inject. With Assisted Inject, you'd declare the constructor for your class something like this:
#Inject public StarryEyes(MyValidator validator, #Assisted String name)
What that means is that validator is a parameter that Guice should inject, while name must be "assisted" (that is, provided at the time the instance is created).
You then create an interface like this:
public interface StarryEyesFactory {
StarryEyes create(String name);
}
With Assisted Inject, Guice can then implement that factory for you. You bind it like this:
bind(StarryEyesFactory.class).toProvider(
FactoryProvider.newFactory(StarryEyesFactory.class, StarryEyes.class));
You then inject a StarryEyesFactory anywhere you want to create an instance of it. Where you would have called new StarryEyes(name) previously, you now call starryEyesFactory.create(name) instead. When you call create(name) on the factory, it will take the name and pass it to the constructor and provide the bound validator itself.
Starting in Guice 3, you do this using a FactoryModuleBuilder:
install(new FactoryModuleBuilder().build(StarryEyesFactory.class));

Categories