Hi,
On 21. 10. 20 17:17, Tomas Langer wrote:
From Matej Novotny:
- Bean Metadata - there is a need for build-time
processing API, but the runtime model I think should be
built into the existing model in CDI to make it capable
of reflection free handling, with the reflected methods
being deprecated. If two models are really needed, we
can work on your PR to come up with a model good for
both annotation processing and byte code processing. We
could have a `jakarta.cdi.lite` model for build time
annotation metadata, and have the current CDI meta model
extend it to add the reflection methods (that may be
used in EE or existing extension and beans).
- Extensibility - agreed, the extensibility model
should be designed in cooperation, to make sure it works
for either build time approach; I will add the link to
the document. Luckily there are not three parties, we
have written the document with Graeme, so we should be
on the same page here
- beans.xml - see below, this one is a bit longer;
can you please explain how you approach this for build
time and runtime in your proposal? Maybe I am missing
some use case that requires a different approach
- reduction of scope - this is a complicated topic, I
can see problems starting with jakarta.inject (Provider
should be deprecated and extend Supplier, and Supplier
used instead, maybe consider adding NonBinding as it
belongs to Qualifier, and I would consider some
additional scopes as they make sense in general, such as
Dependent and RequestScope), and jakarta.annotation-api
(I have doubts about the security, sql package,
ManagedBean class, Resource class - seems like a
mixture of classes that are from different areas, not
all of them have meaning in SE; we should also add Nullable
and Nonnul annotations), there are some areas in
interceptor API that may be improved, and of course the
areas in the CDI spec itself. The question here is
whether these should be dropped from the specification
(e.g. deprecated and eventually removed), or just not
part of a profile, or a combination of both
- Extensibility #2:
- “Lite” would only implement build-time
- SE and EE would support existing portable
extension
- I think we should aim at providing a capability
to “transform” output of a build-time extension into a
portable extension; this would not work for synthetic
beans created at runtime and for beans added by other
portable extensions (as the build time extension would
not know about them). I think we should go through a few
use cases to see if this would be useful at all, or
would just bring confusion
- My concern - if we create “Lite” with build time
extension (only), and “SE” and “EE” with portable
extensions (only), we would end up with two sets of
extensions for each feature (such as a “OpenTracingLite”
and “OpenTracingExtension”) - this may be a good
solution, I am myself not sure about it
Beans.xml and bean discovery:
You (Matej) consider class path scanning is needed at
build time, we were thinking about class path scanning
free approach. Each archive that is a bean archive
should have appropriate “META-INF/services” with a
service that provides the list of beans in that archive.
If done this way, there is no need for beans.xml. This
of course implies that each bean archive is compiled
with build-time processing. We could have a component,
that would add such metadata on existing bean archives
(yet I think this can be vendor specific).
How would this work?
- build time of a bean archive: the processor
(annotation or byte code) generates a
META-INF/service/jakarta.cdi.lite.BeanDefinitionProvider
with a list of (generated) implementations for each bean
in the archive
- build time of my application: we process the
current application source (or byte code) to create the
service list (either via annotation processing or byte
code scanning)
- run time: we read all the BeanDefinitionProvider
instances and create our bean landscape from them (the
bean landscape is almost fully pre-computed, may be
using some conditions to limit the list of beans being
loaded)
- in case we want to “enhance” a bean archive that is
not our application (such as adding an interceptor to an
existing bean), we would use a concept of “bean import”,
with a configurable way to mark classes to be
re-computed and provide an alternative with higher
priority than the original bean
I wanted to get back to this, as I find it the most
important open topic. It's not just about bean discovery,
it's also about what extensions can do.
I'll use my favorite example of MicroProfile Fault
Tolerance and SmallRye Fault Tolerance, as I'm familiar
with it, but the setting is quite general.
So, let's assume there's a MicroProfile Fault Tolerance
API in the mp-ft.jar. (That's basically what you can get
from Maven Central at
org.eclipse.microprofile.fault-tolerance:microprofile-fault-tolerance-api.)
This JAR has no beans.xml and no classes with bean
defining annotations.
Further, let's assume there's a SmallRye Fault Tolerance
implementation of the previous API in srye-ft.jar. (In
reality, it's several JARs at
io.smallrye:smallrye-fault-tolerance*, but let's assume
it's just one.) This JAR has no beans.xml either, but
there are some classes with bean defining annotations, and
there's also an extension (in current reality, that's a
Portable Extension, but it could also be a Build
Compatible Extension).
The extension does a bunch of things, but for the purpose
of this discussion, 2 are important:
- it takes some classes from mp-ft.jar and "adds" an
annotation to them, for the purpose of interceptor binding;
- it also registers some classes from srye-ft.jar as beans
(srye-ft.jar has no beans.xml, so beans from it are not
discovered automatically, but we need them).
That all works nice in current CDI. It also translates
relatively straightforwardly to Quarkus, or to the Build
Compatible Extension proposal I created -- which assumes
some form of access to the whole world (classpath
scanning, Jandex, whatever).
What I'd like to understand is -- how do your constraints
apply here?
Assuming extensions are discovered via ServiceLoader, you
would be able to run the extension in srye-ft.jar just
fine. But would the extension be able to add the beans
from srye-ft.jar to the application? Would it be able to
"modify" the classes from mp-ft.jar?
Do you think that mp-ft.jar and srye-ft.jar would require
some other build-time processing during _their_ build?
(What kind of processing? Who would maintain that tool?)
And do you think that would be enough?
For example, the extension in srye-ft.jar could "install"
a custom scope (it doesn't in reality, but it could),
which extends the set of bean defining annotations. Would
beans with such new bean defining annotation still be
discovered?
I'm sure I'm missing a lot, but it seems to me that we
would either have to carefully restrict all things that
might possibly require access to the whole world, or...
well... require all JARs to carry not just a list of
beans, but an index of all their classes and annotations.
LT
_______________________________________________