Mediator instantiation may result in AmbiguousResolutionException
This may happen if class hierarchies are in use:
@ApplicationScoped
class Foo {
@Incoming("source")
@Outgoing("processed-a")
public String toUpperCase(String payload) {
return payload.toUpperCase();
}
}
@ApplicationScoped
class Bar extends Foo {
}
In this particular case, there are two beans Foo with bean types [Foo,Object] and qualifiers [Default] and Bar with bean types [Bar,Foo,Object] and qualifiers [Default]. So if MediatorManager does instance.select(Foo.class, []).get() => AmbiguousResolutionException.
In theory, you could store the Bean<> object in mediator config but then you would have to switch to BeanManager methods (getReference() etc.). Another possibility is to forbid class hierarchies.
What would be the "CDI" way of handling this situation?
Well, the "correct" way would be to handle the class hierarchies correctly, which is not an easy thing to do. I.e. you would have to filter out beans that override the annotated method:
@ApplicationScoped
class Foo {
@Incoming("source")
@Outgoing("processed-a")
public String toUpperCase(String payload) {
return payload.toUpperCase();
}
}
@ApplicationScoped
class Bar extends Foo {
public String toUpperCase(String payload) { }
}
In this case, ProcessManagedBean.getAnnotatedBeanClass().getMethods() for Bar would return two AnnotatedMethods with the name toUpperCase() and you would have to use AnnotatedMethod.getJavaMember().getDeclaringClass() to determine the type in the type hierarchy that declared the method.
And as I said in the previous comment - you can store a reference to the Bean<> and then use BeanManager.getReference() to obtain a bean instance.
And as I said in the previous comment - you can store a reference to the Bean<> and then use BeanManager.getReference() to obtain a bean instance.
I think what Martin meant is that every MediatorConfiguration would carry an information about Bean<T> instead of the class of that bean. Based on that you can replace bean retrieval process you have (using Instance.select()) with one via BeanManager.getReference(). That way you can get reference to the correct bean even with hierarchy in place (as both Foo and Bar have different Bean<T> metadata).
@mkouba in such case you will have to care about all the CreationalContexts you create, right? E.g. keep a reference to them and them perform release() once you no longer need those beans.
I think what Martin meant is that every MediatorConfiguration would carry an information about Bean<T> instead of the class of that bean.
Exactly.
@mkouba in such case you will have to care about all the CreationalContexts you create...
Exactly.
And there's probably more...
I believe that we should just not support inheritance for now until we get a better / good answer.
+1 and make sure it's documented.