On 17. 10. 24 17:13, Laird Nelson wrote:
On Thu, Oct 17, 2024 at 3:44 AM Martin Kouba <mkouba(a)redhat.com
<mailto:mkouba@redhat.com>> wrote:
I believe that if you replace the original InjectionTarget and change
the set of injection points then it's your responsibility to perform
the
injection for the additional injection points because Weld (the
original
InjectionTarget) does not have enough information to fulfill this
task -
after all, the spec is very clear that "Implementations of Producer and
InjectionTarget must ensure that the set of injection points
returned by
getInjectionPoints() are injected by produce() or inject()." [1]. In
this particular case, the replacement is the "implementation".
Why, then, does the InjectionTarget interface have a
getInjectionPoints() method?
So that it's possible to access the metadata about all injection points
of a specific InjectionTarget.
What purpose does it serve for Weld?
What information does Weld lack that prevents it from reading an
arbitrary injection point, which of course contains a member, and
performing injection on it?
In theory, an arbitrary injection point does not have to provide a valid
member.
In any case, my point is that if you replace the InjectionTarget and
modify some configuration then it's up to you to reflect those changes.
You can't rely on/delegate to the orginal InjectionTarget because it was
created from a different configuration. You expect the Weld
implementation to automatically adjust itself based on your changes. But
that would be inefficient.
But again, the spec wording is clear - it's up to the InjectionTarget
implementation.
In my opinion, the ProcessInjectionTarget API opens up many
possibilities, but not all of them are feasible in terms of
implementation. When using this API it's easy to shoot yourself in your leg.
Best,
Laird
Martin
[1]
https://jakarta.ee/specifications/cdi/4.1/jakarta-cdi-spec-4.1#injectiont...
<
https://jakarta.ee/specifications/cdi/4.1/jakarta-cdi-spec-4.1#injectiont...
On 17. 10. 24 10:43, Matej Novotny wrote:
> I recall this came up some long time ago as well and while I am
still
> refreshing my knowledge on this, here are some thoughts.
>
> > 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.
>
> IIRC, Weld did recognize these added IPs for the purpose of
validation
> which is probably the part you noticed.
>
> > 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".
>
> What exactly should CDI do with this injection point in your opinion?
> Given a class based beans with some fields (just to keep it
simple), you
> can modify the set of injection points and add an extra IP of
type Foo
> that wasn't present before.
> You can "honor" the InjectionPoint contract but you can still
configure
> the IP arbitrarily - you can override a field that's already
injected
> but you can also make up one. You could use an ordinary method as a
> Member and that would never get injected anyway.
> Apart from validation which would fail if Foo bean is not
resolvable,
> what do you gain? No user can put their hands on Foo as there is no
> param or field that would really be injected that they can access.
>
> > 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?)
>
> Frankly speaking, I always found the ability to override IPs for an
> injection target very strange and I don't think I saw a use for
it that
> wasn't at least mostly theoretical.
> That being said, I recall there were some implementation issues
which
> resulted in the current behavior; my guess would be it was the
> difficulty of identifying the IP via its Member and making sense
of it.
> After all, any additional injection might as well be one via
overriden
> inject(...) method in the same API.
> I am still digging through some older issues trying to see if I
can find
> some notion of why we ended up handling it this way.
>
> This might also be worth asking on the CDI spec to get more
opinions and
> possibly eventually a clarification.
> But I'll leave that up to you.
>
> Matej
>
> On Thu, Oct 17, 2024 at 6:36 AM Laird Nelson <ljnelson(a)gmail.com
<mailto:ljnelson@gmail.com>
> <mailto:ljnelson@gmail.com <mailto:ljnelson@gmail.com>>> wrote:
>
> 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...
<
https://github.com/weld/core/blob/225ced4d3dff4d0df5bf167c4d2374cdce00e55...
<
https://github.com/weld/core/blob/225ced4d3dff4d0df5bf167c4d2374cdce00e55...
<
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
> _______________________________________________
> weld-dev mailing list -- weld-dev(a)lists.jboss.org
<mailto:weld-dev@lists.jboss.org>
> <mailto:weld-dev@lists.jboss.org
<mailto:weld-dev@lists.jboss.org>>
> To unsubscribe send an email to
weld-dev-leave(a)lists.jboss.org <mailto:weld-dev-leave@lists.jboss.org>
> <mailto:weld-dev-leave@lists.jboss.org
<mailto:weld-dev-leave@lists.jboss.org>>
> Privacy Statement:
https://www.redhat.com/en/about/privacy-policy
<
https://www.redhat.com/en/about/privacy-policy>
> <https://www.redhat.com/en/about/privacy-policy
<
https://www.redhat.com/en/about/privacy-policy>>
> List Archives:
>
https://lists.jboss.org/archives/list/weld-dev@lists.jboss.org/message/EZ...
<
https://lists.jboss.org/archives/list/weld-dev@lists.jboss.org/message/EZ...
<
https://lists.jboss.org/archives/list/weld-dev@lists.jboss.org/message/EZ...
<
https://lists.jboss.org/archives/list/weld-dev@lists.jboss.org/message/EZ...
>
>
> _______________________________________________
> weld-dev mailing list -- weld-dev(a)lists.jboss.org
<mailto:weld-dev@lists.jboss.org>
> To unsubscribe send an email to weld-dev-leave(a)lists.jboss.org
<mailto:weld-dev-leave@lists.jboss.org>
> Privacy Statement:
https://www.redhat.com/en/about/privacy-policy
<
https://www.redhat.com/en/about/privacy-policy>
> List Archives:
https://lists.jboss.org/archives/list/weld-dev@lists.jboss.org/message/2E...
<
https://lists.jboss.org/archives/list/weld-dev@lists.jboss.org/message/2E...
--
Martin Kouba
Principal Software Engineer
Red Hat, Czech Republic