Is there any way to ask Weld SE to inject a specific implementation at a given time? - weld

I use Weld SE in an application, in my application I have an interface for which I have 3 implementations but this causes an ambiguity for Weld. As far as I can see Weld ambiguity resolution technics are static, this can be done by mean of: #specialize, #alternative, #Named or using Qualifier. but this doesn't help me. I need to be able specify a given class implementation of the interface for each case.
I couldn't figure out a solution for my requirement.
Here is a code that illustrates my point
public class Foo {
#Inject
MyInterface target;
public void doSomething() {
target.doIt();
}
}
public class Bar1 implements MyInterface {
public void doIt() {
System.out.println("Hello");
}
}
public class Bar2 implements MyInterface {
public void doIt() {
System.out.println("Goodbye");
}
}
public class FooMain {
public static void main(String[] args) {
Weld weld = new Weld();
final WeldContainer container = weld.initialize();
Foo foo1 = container.instance().select(Foo.class).get();
Foo foo2 = container.instance().select(Foo.class).get();
}
}
This code causes this exception :
Exception in thread "main" org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type MyInterface with qualifiers #Default
at injection point [BackedAnnotatedField] #Inject com.lodh.arte.test.cdi.Foo.target
at com.lodh.arte.test.cdi.Foo.target(Foo.java:0)
Possible dependencies:
- Managed Bean [class com.lodh.arte.test.cdi.Bar2] with qualifiers [#Any #Default],
- Managed Bean [class com.lodh.arte.test.cdi.Bar1] with qualifiers [#Any #Default]
I need to dynamically tell Weld which implementation to use for injection, just like in this imaginary method Weld.use:
Weld.use ( MyInterface.class, Bar1.class);
Foo foo1 = container.instance().select(Foo.class).get();
Weld.use ( MyInterface.class, Bar2.class);
Foo foo2 = container.instance().select(Foo.class).get();
Thank you for your help
Regards
Nader

First you have two implementations of MyInterface. Bar1 and Bar2. Weld does not know which implementation to choose when injecting MyInterface, so it throws this "Ambiguous dependencies" error.
To avoid this error you should give your implementation different qualifiers.
You have to Qualify your implementations first:
#MyQualifier1
public class Bar1 implements MyInterface {
(...)
}
#MyQualifier2
public class Bar2 implements MyInterface {
(...)
}
This will allow to inject a specific implementation like this:
#Inject
#MyQualifier1
MyInterface target;
Now you're injecting an MyInterface qualified with #MyQualifier1. At runtime its Type will be Bar1 in this case.
Another approach if you want to decide at runtime which implementation you need would be the use of Instance:
#Inject
Instance<MyInterface> unqualifiedInstance;
void do(){
/// first attach the qualifier, we missed at the injection-point:
Instance qualifiedInstance = instance.select(new AnnotationLiteral<MyQualifier2>(){})
/// Now you have a qualified Instance, which is a new Object without touching the unqualifiedInstance!
MyInterface target = qualifiedInstance.get();
/// so you can decide which implementation you need by passing the qualifier per select-method. in this case its bar2
target.doIt();
}
If you need further help with qualifiers you may find the weld documentation and especially chapter 4.3 and the following helpful.
http://docs.jboss.org/weld/reference/latest/en-US/html/injection.html

Related

How to inject a list with different implementations of the same interface in a nested module scenario via Guice?

There is an interface DCE, which is implemented by a class DCEImpl which has a dependency, say, string S, which it gets via its constructor.
The universe of S is limited, say S can only take values {'A','B','C'}.
There is an already existing Guice module that accepts the value of S in its constructor, and then binds the interface DCE to the correctly initialized version of DCEImpl.
public class DCEModule extends AbstractModule {
private final String s;
public DCEModule(String s){
this.s = s;
}
protected void configure() {
bind(DCE.class).toInstance(new DCEImpl(s));
}
}
Now I have a class C which needs a List<DCE> with all the 3 implementations (actually a lot more than 3, using 3 for example purpose).
I want to inject this list via Guice in C. To do that, I created a new module DCEPModule, which will provide a List<DCE> in this way:
#Provides
List<DCE> getDCE() {
for(String s: S){
Module m = new DCEModule(s);
install(m);
Injector injector = Guice.createInjector(m);
listDomains.add(injector.getInstance(DCE.class));
}
}
My problem is that I don't want to call a new injector in this module, because DCEPModule will be installed by a different module.
public class NewModule extends AbstractModule {
protected void configure() {
install(DCEPModule);
}
}
I want a way to get the List<DCE> without explicitly creating a new injector in DCEPModule.
You can achieve this by using a Multibinder (javadoc, wiki).
Here’s an example:
public class SnacksModule extends AbstractModule {
protected void configure(){
Multibinder<Snack> multibinder = Multibinder.newSetBinder(binder(), Snack.class);
multibinder.addBinding().toInstance(new Twix());
  multibinder.addBinding().toProvider(SnickersProvider.class);
  multibinder.addBinding().to(Skittles.class);
}
}
Now, the multibinder will provide a Set<Snack>. If you absolutely need a List instead of a Set, then you can add a method to your module like this:
#Provides
public List<Snack> getSnackList(Set<Snack> snackSet) {
return new ArrayList(snackSet);
}
You can add implementations to the same Multibinding in more than one module. When you call Multibinder.newSetBinder(binder, type) it doesn’t necessarily create a new Multibinding. If a Multibinding already exists for for that type, then you will get the existing Multibinding.

Kotlin + Dagger 2: RuntimeException: has no zero argument constructor

When I try to inject a class via constructor in a Kotlin class I am getting this exception.
I have been reading about ways to solve it in Java by adding an empty constructor to the class that gets the injection.
However, it does not seem to be possible (or I do not how) to do it in Kotlin.
The code that throws the exception has nothing out of normal...just a simple injection.
Here it is a piece of the code with the injection that throws exception:
class RemoteService #Inject constructor(
#SongListRepo private val songListRepo: SongListRepo): MainBaseService() {
...
...
...
}
And of course the SongListRepo is provided by a module in the usual Dagger 2 way.
-------- EDIT: ---------
After some help and comments from #Demigod the code looks like this
class RemoteService (): MainBaseService() {
lateinit var songLR : SongListRepo
#Inject constructor(#SongListRepo songListRepo: SongListRepo) : this(
{
this.songLR = songListRepo
}
Problem now is that secondary constructor never gets initialized
Is it possible that the error you're getting is related to this Service (I think like Fragment they must have a zero argument constructor, so that the platform would be able to re create them)? If yes than you might use an on demand injection, like:
class RemoteService: MainBaseService() {
#Inject
#SongListRepo
private lateinit var songListRepo: SongListRepo
init {
// Something like this
AndroidInjection.inject(this)
}
}
Or, anyway you can add additional constructors like:
class RemoteService constructor(): MainBaseService() {
private lateinit var songListRepo: SongListRepo? = null
#Inject constructor(#SongListRepo songListRepo: SongListRepo):this() {
this.songListRepo = songListRepo
}
}
More about constructors here

Bind list of objects using Guice + Kotlin

I'm writing a JavaFX application in Kotlin with the following controller definition:
class MainController {
#Inject private lateinit var componentDescriptors: List<ComponentDescriptor>
/* More code goes here */
}
I'm using Guice for Dependency management. And I'm trying to inject the list of class instances loaded via java.util.ServiceLoader. My problem is to define a binding that will inject the list of loaded object instances into the declared field. I tried annotation based provisioning:
internal class MyModule: AbstractModule() {
override fun configure() { }
#Provides #Singleton
fun bindComponentDescriptors(): List<ComponentDescriptor> =
ServiceLoader.load(ComponentDescriptor::class.java).toList()
}
and multibinding extension (switched List to Set in field definition of corse):
internal class MyModule: AbstractModule() {
override fun configure() {
val componentDescriptorBinder = Multibinder.newSetBinder(binder(), ComponentDescriptor::class.java)
ServiceLoader.load(ComponentDescriptor::class.java).forEach {
componentDescriptorBinder.addBinding().toInstance(it)
}
}
}
but both of these approaches leads to the same error:
No implementation for java.util.List<? extends simpleApp.ComponentDescriptor> was bound.
while locating java.util.List<? extends simpleApp.ComponentDescriptor>
for field at simpleApp.MainController.componentDescryptors(MainController.kt:6)
while locating simpleApp.MainController
1 error
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1042)
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1001)
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1051)
at com.gluonhq.ignite.guice.GuiceContext.getInstance(GuiceContext.java:46)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:929)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:971)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:220)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:744)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
... 12 more
I'm starting to suspect that it somehow related to Kotlin gerenic variance and Guice strict type checking. But I don't know how to declare the binding so Guice will know what to inject into this field.
Yes, it happens because of variance but there's a way to make it work.
class MainController {
#JvmSuppressWildcards
#Inject
private lateinit var componentDescriptors: List<ComponentDescriptor>
}
By default Kotlin generates List<? extends ComponentDescriptor> signature for the componentDescriptors field. The #JvmSuppressWildcards makes it generate a simple parameterized signature List<ComponentDescriptor>.
#Michael gives the correct answer and explanation. Here's an example of one strategy for unit testing a Set multibinding for those that like to test their modules:
class MyModuleTest {
#JvmSuppressWildcards
#Inject
private lateinit var myTypes: Set<MyType>
#Before fun before() {
val injector = Guice.createInjector(MyModule())
injector.injectMembers(this)
}
#Test fun multibindings() {
assertNotNull(myTypes)
assertTrue(myTypes.iterator().next() is MyType)
}
}
#Michael comment is working. If you want to do the injection in constructor, you need do something like
class MainController #Inject consturctor(
private var componentDescriptors: List<#JvmSuppressWildcards ComponentDescriptor>
) {}

EL and covariant return types

i have these classes
public abstract class Unit
{
public abstract UnitType getType();
...
}
public class Item extends Unit
{
protected ItemType type;
#Override
public ItemType getType()
{
return type;
}
public void setType(ItemType type)
{
this.type = type;
}
...
}
and obvoiusly ItemType extends UnitType.
and i get:
javax.el.PropertyNotWritableException: /WEB-INF/facelets/general.xhtml #23,165 value="#{bean.item.type}": The class 'com.example.Item' does not have a writable property 'type'.
i can understand that covariant return type can confuse EL (2.2), so is this a bug?
i can workaround this using
generics
change setType signature to public void setType(UnitType type) and check instanceof inside
change method name to avoid override
is there a REAL solution instead of workarounds?
Seems like java.beans.Introspector is responsible. There were a lot of relevant bugs in Java:
7092744, 7122138, 6528714, 6794807, 6788525. Problems manifest with covariant return types and generics due to synthetic bridge methods. With some Java 7 updates (45, 51, 67, 71) problems manifest not right way but after running the server for some time - this is probably related to softly/weakly referenced caches in the Introspector and related classes.
All these problems seem to be fixed in Java 1.7.0_80 (tested with Mojarra 2.2.8 and Wildfly 8.2.0.Final).

Inject dependencies in methods or in the constructor?

Dependency injection seems to be a good thing. In general, should dependencies be injected at the methods that require them, or should they be injected in the contructor of the class?
See the samples below to demonstrate the two ways to inject the same dependency.
//Inject the dependency into the methods that require ImportantClass
Class Something {
public Something()
{
//empty
}
public void A()
{
//do something without x
}
public void B(ImportantClass x)
{
//do something with x
}
public void C(ImportantClass x)
{
//do something with x
}
}
//Inject the dependency into the constructor once
Class Something {
private ImportantClass _x
public Something(ImportantClass x)
{
this._x = x;
}
public void A()
{
//do something without x
}
public void B()
{
//do something with this._x
}
public void C()
{
//do something with this._x
}
}
The major benefit of constructor injection is that it allows your fields to be marked final. For example:
class Foo {
private final Bar _bar;
Foo(Bar bar) {
_bar=bar;
}
}
The following page has a great list of the pro's and con's: Guice Best Practices:
Method injection
+ Isn't field injection
+ Only thing that works for some strange edge cases
Constructor injection
+ Fields can be final!
+ Injection cannot possibly have been skipped
+ Easy to see dependencies at a glance
+ It's what the idea of construction is all about
- No optional injections
- Useless when DI library can't do instantiation itself
- Subclasses need to "know about" the injections needed by their superclasses
- Less convenient for tests that only "care about" one of the parameters
If you inject during the methods than you are not differentiating the behavioral abstraction from the concrete dependencies. This is a big no no :). You want to depend on abstractions so you are not coupled with the dependencies of your classes dependencies . . .
Since your constructor would not be there in any interface that your concrete class supports than you are not coupling to that dependency. But the method calls would have that issue.
Here is a good article on this tiopic:
http://chrisdonnan.com/blog/2007/05/20/conquest-through-extreme-composition-glue-part-2/
By not injecting the dependency at each method you then force each caller to know or retrieve the dependency.
Also from a tooling standpoint there are many frameworks available (at least in .NET) that enable or make constructor injection much easier to do. This should not sway the decision but makes it much more attractive.
Good luck.
Another method is to user a setter for the dependency. Sometimes this is combined with constructor injection. This can be useful if you want to change which implementation you are using later without having to recreate the instance.
public interface IFoo
{
void Do();
}
public class DefaultFoo : IFoo
{
public void Do()
{
}
}
public class UsesFoo
{
private IFoo foo;
public IFoo Foo
{
set { this.foo = value; }
}
public UsesFoo()
{
this.Foo = new DefaultFoo();
}
public UsesFoo( IFoo foo )
{
this.Foo = foo;
}
public void DoFoo()
{
this.Foo.Do();
}
}
Crazy Bob Lee says use constructor injection whenever possible. Only use method injection when you don't have control over instantiation (like in a servlet).

Resources