I have two classes, which I wish to inject:
@ApplicationScoped
public class BeanThing {
public String apply(String s) {
return "bt(" + s + ")";
}
}
and
@ApplicationScoped
public class ClassFunction implements Function<String, String> {
@Override
public String apply(String s) {
return "cf(" + s + ")";
}
}
When I try and use them elsewhere I get different behaviour:
Set<Bean<?>> functions = beanManager.getBeans(Function.class);
for (Bean<?> untyped : functions) {
Bean<Function<String, String>> typed = (Bean<Function<String, String>>) untyped;
Function<String, String> function = beanManager.getContext(typed.getScope()).get(typed, beanManager.createCreationalContext(typed));
System.err.println(function.apply("beanManager"));
}
Set<Bean<?>> beanThings = beanManager.getBeans(BeanThing.class);
for (Bean<?> untyped : beanThings) {
Bean<BeanThing> typed = (Bean<BeanThing>) untyped;
BeanThing beanThing = beanManager.getContext(typed.getScope()).get(typed, beanManager.createCreationalContext(typed));
System.err.println(beanThing.apply("beanManager"));
}
System.err.println(injectedFunction.apply("injected"));
System.err.println(beanThing.apply("injected"));
System.err.println("injectedFunction is a function: " + (injectedFunction instanceof Function));
my output is:
bt(beanManager)
cf(injected)
bt(injected)
injectedFunction is a function: true
which is one fewer lines than I expect.
Could someone explain what going on here?
Solution, thanks to Siliarus for setting me off down the right path:
Set<Bean<?>> functions = beanManager.getBeans(new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return new Type[]{new WildcardType() {...}, new WildcardType() {...};
}
@Override
public Type getRawType() {
return Function.class;
}
});
If I get your sample correctly what you are missing is the first line - output from the
Function
when obtained viaBeanManager
.My guess is, that the
Set<Bean<?>> functions
is empty. The reason for that are generics.Function
is a generic type and methods onBeanManager
are not really good with that. CDI spec defines Typesafe resolution for parameterized types pretty well (although it takes some reading).In short, your bean of type
Function<String, String>
won't be assignable to just rawFunction.class
, which you pass toBeanManager
method.As a side note, if you wish to instantiate parametrized types on-the-fly, you can always use
Instance<T>
, which supports the use ofTypeLiteral
- a special construct which holds not only the raw type, but also information about the actual parameters.