-
Notifications
You must be signed in to change notification settings - Fork 81
add support for synthetic bean injection points #833
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This is a draft, because it's very much not ready. The biggest open question is: does One way would be to say something like:
That is obviously a breaking change, but I don't see a better way that wouldn't be more breaking. |
👍 Although a breaking change it makes perfect sense IMO. |
What are you trying to fix by adding this? I don't see an explanation of the problem or a linked issue. |
In a build-time environment, such as Quarkus, injection point metadata has to be recorded for any |
What @mkouba says is just the reason why I'm submitting this PR now. The ultimate cause is feature parity -- Portable Extensions allow this, while Build Compatible Extensions do not. |
03541db
to
039589f
Compare
I eventually decided that this is something we should keep doing in Quarkus, outside of the specification. The spec should stay silent on this. |
Thanks @Ladicek for the explanation on the call. As I understand it now: With portable extensions, you can create a synthetic bean by implementing Other extensions can also modify the injection points by observing As far as I can see, there's no way to link an injection point to an injected dependent bean to allow the dependent bean to inspect where it's been injected. This PR would add equivalent functionality to build compatible extensions. Injection points can be added to the synthetic bean and will be validated by the container and available for other extensions to inspect with Additionally, Quarkus want the ability to do some additional out-of-spec optimisations (such as removing any beans which aren't needed), and having this functionality in build compatible extensions would add a way for the user to indicate that certain beans are used by their synthetic bean and can't be optimised away. |
Actually, let me push this PR back to draft, because there's a bit of a conflict we need to resolve: the Portable Extensions API allows this, but expect a direct implementation of |
039589f
to
591d477
Compare
I found some time and updated the proposal with a somewhat better (I believe) API. The main question remains (and it's why I'm keeping this PR as a draft): how can we bridge this with Portable Extensions, which expect full blown |
da88af4
to
bc1874b
Compare
Pardon my ignorance, I am pretty sure we discussed this but I don't see it recorder here - what was the issue with introducing |
I don't think there's an issue with that. (Besides the name. We need a good name.) If you think that's a reasonable way forward, I'll try to figure something out. |
It does sound reasonable to me, but we can discuss it further in the mtg today (assuming you are coming). |
@Ladicek @Azquelt based on our discussion during the mtg, I checked for It should therefore be safe to conclude that the synthetic IPs we are discussing here should not trigger the event either. |
For an unexplainable reason, I'm quite fond of the idea of |
Sure, works for me. |
Users can also obtain the injection point via:
If we allow synthetic beans to have an If we really want to guarantee that the user cannot get an If we don't do that, I can't see how we could avoid altering |
Right, you'd only be getting regular IPs here until now, or empty collections for synth beans (excepting some edge cases where a synth. bean would "mimic" actual IP for the sake of validation which has no real use).
I am not sure I understand how would you need to see the new IP here? Or you mean to use it in place of the current method? |
I was thinking it would be quite acceptable to do a small breaking change and say that |
I was looking around and I didn't really find good explanation of what is this particular spec part about.
It has nothing to do with checking bean availability, we can do that with just type and qualifier and knowing which beans are enabled where. So it is likely meant to support the last bullet point:
But how does it help there? |
bc1874b
to
f657c84
Compare
f657c84
to
23493ca
Compare
Injection points are registered on a `SyntheticBeanBuilder` using `withInjectionPoint()`. The synthetic bean creation/destruction functions can look up injectable references for registered injection points from `SyntheticInjections`. The `SyntheticBeanCreator` and `SyntheticBeanDisposer` interfaces used to have one method. That method is now deprecated for removal and a second method is added. The second method no longer has an `Instance<Object>` parameter for arbitrary lookups; instead, is has a parameter of type `SyntheticInjections` for pre-registered injections.
23493ca
to
f96f107
Compare
@@ -0,0 +1,54 @@ | |||
/* | |||
* Copyright (c) 2025 Red Hat and others |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong copyright header?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed. I'll fix.
* on the {@link SyntheticBeanBuilder}. Returns {@code null} if the type/qualifiers | ||
* combination was not registered on the {@code SyntheticBeanBuilder}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't it be an error to try and retrieve a non-registered bean?
Since it is just one party registering and then using the synth. injection point, they should know what to look for and a wrong input should give them some meaningful error.
Besides, there is always the edge case of a dependent scoped producer returning null
as a bean which is then indistinguishable from not having any such bean.
Or we could return an Optional
which would be empty if there was no bean.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. We could throw IllegalArgumentException
I guess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aside: I think I specified this to behave the same as the corresponding API we have in ArC, but I think throwing an exception is a better idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you talking about io.quarkus.arc.SyntheticCreationalContext.getInjectedReference(Class<R>, Annotation...)
? If so, then we also throw an IllegalArgumentException
if a corresponding synthetic injection point was not defined...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we? Then I have no idea why I wrote this the way I wrote it :-)
api/src/main/java/jakarta/enterprise/inject/build/compatible/spi/SyntheticBeanBuilder.java
Show resolved
Hide resolved
Just FYI, my force-pushes recently didn't change anything in this PR, I just rebased on latest |
Injection points are registered on a
SyntheticBeanBuilder
usingwithInjectionPoint()
. The synthetic bean creation/destruction functions can look up injectable references for registered injection points fromSyntheticInjections
.The
SyntheticBeanCreator
andSyntheticBeanDisposer
interfaces used to have one method. That method is now deprecated for removal and a second method is added. The second method no longer has anInstance<Object>
parameter for arbitrary lookups; instead, is has a parameter of typeSyntheticInjections
for pre-registered injections.