BasicInjectionTarget ignores injection points set by portable extension?
by Laird Nelson
It is possible I am doing something wrong.
I have an observer method in a portable extension that observes
ProcessInjectionTarget events.
This is in CDI SE in case it ends up mattering. I hope it won't.
I replace the InjectionTarget via the official, documented,
event.setInjectionTarget(InjectionTarget) by decorating the InjectionTarget
that is reachable from the event. So, for example, my custom
InjectionTarget calls event.getInjectionTarget().dispose() when dispose()
is called on my custom InjectionTarget, and, indeed, for most of the
methods involved. Basic forwarding/delegate stuff.
In my replacement InjectionTarget, I add an InjectionPoint to the Set of
InjectionPoints reported by the InjectionTarget via its
getInjectionPoints() method. Nothing fancy.
The injection point so added is one of my choosing and it does not matter
why I chose it. It honors the InjectionPoint contract. My intention is that
this is something that CDI should "fill".
Through some details that I can go into if needed, I can see that some
portion of Weld indeed does recognize my custom injection point. So in some
places in the Weld codebase, my work is recognized, i.e.
getInjectionPoints() is returning something that I have added, that Weld's
internals "see". It makes some sort of validation attempt, or something, to
satisfy it. So far so good.
However, my InjectionTarget's inject() method, which I have *not*
customized, but merely forwarded to the container-supplied InjectionTarget,
does not respect the Set of InjectionPoints I have reported, which includes
my custom one. I found this strange. I would have expected its injection
mechanism to work on the InjectionPoints I have reported, and none other.
Instead it seems it works only on fields it has discovered. Or something.
(In which case why let portable extensions modify this area only to ignore
them?)
Digging deeper, I found that the BasicInjectionTarget (the
"container"-supplied one) passes off injection to something called an
Injector. It passes along "this", which is, among other things, an
InjectionTarget. So far so good, though it is starting to get a little
murky. That is, at least the Injector seems to have the possibility of
calling getInjectionPoints() on the target rather than deciding it knows
best.
For some reason, and I don't think I care, ultimately, the Injector is a
ResourceInjector.
In any event, it then proceeds to do injection, but, contrary to my
expectations, it ignores my custom injection points. That is, it never
calls myCustomInjectionTarget.getInjectionPoints() to see what needs to be
injected. See for yourself (note that injectionTarget (mine, in this case)
is never used (well, OK, it is passed to the InjectionContextImpl, where it
seems to be ignored)):
https://github.com/weld/core/blob/225ced4d3dff4d0df5bf167c4d2374cdce00e55...
Note that this Injector has a reference to the InjectionTarget, but never
seems to call getInjectionPoints() when it is doing injection. You would
think that since portable extensions can replace the InjectionTarget, it
must do this, but it does not.
What am I missing? If an InjectionTarget's InjectionPoints are never
consulted, why make an InjectionTarget report them in the first place?
Should I file a bug?
Best,
Laird
1 month
Primitive type question regarding events
by Laird Nelson
The CDI 4.0 spec says in section 2.8.1 (
https://jakarta.ee/specifications/cdi/4.0/jakarta-cdi-spec-4.0#event_type...
):
"Any Java type may be an observed event type."
That means I can do this:
private void primitive(@Observes int i) { // any type, including int, can
be an observed event type
System.out.println("primitive: " + i);
}
And this:
private void wrapper(@Observes Integer i) {
System.out.println("wrapper: " + i);
}
Then of course the only way to fire an event is by using the Event object
and specifying the type of even you want to fire as its sole type argument:
// for example
@Inject
private Event<Integer> e;
(Type arguments of course cannot be primitive.)
No mention in the specification's section on observer resolution talks
about primitive types and/or wrapper types and how they interact.
(Obviously there are unrelated sections regarding typesafe resolution in
the context of dependency injection that do talk about this, but they do
not seem to apply here without a biiiiiig stretch (observed event
parameters are not injection points; event types are not bean types).)
If I do e.fire(Integer.valueOf(42)), the primitive(int) observer method
above is called (in Weld 5.1.3.Final). So is the wrapper(Integer) observer
method. This certainly is convenient and I'm kind of glad it works that
way, but is it correct? Is it a Weld value-add? Or should the spec have
said something about interoperability of primitives and wrapper types in
observer resolution?
Best,
Laird
1 month