So far it looks reasonable to me, I will hopefully get time in the new year to try and push forward a second implementation besides Quarkus to validate the ideas.
On Wed, Nov 25, 2020 at 12:27 PM Ladislav Thon <lthon@xxxxxxxxxx> wrote:
I'd like to highlight that this doesn't mean the work on the API
is done -- far from it. It only proves that the API can be
implemented [in Quarkus], not that it's a good API that covers all
use cases that Portable Extensions cover. I present the prototype
implementation as a solid ground on top of which we can debate.
Specifically, the proposed API still uses Class objects to refer
to classes, which might or might not be an issue for
implementations based on annotation processors. The proposed API
is completely push-based now, but that can easily mean that it
can't satisfy some use cases (e.g. deciding based on absence).
There is a bunch of TODOs in the code that need discussion and
resolution. Etc. etc. etc.
I'm currently thinking that the Portable Extensions approach,
where the "observer" methods on the extension class are
themselves callbacks, might actually be better, if we really
need to be push-based. I'll probably explore that approach
too, to see how it would look like.
LT
On 30. 09. 20 14:14, Ladislav Thon
wrote:
Ah, one more thing. We also got a very good feedback from
Graeme on the current proposal [1], and we'll work on
incorporating that. So any and all examples should be
considered temporary and subject to change. I've been saying
that since the beginning, so hopefully it doesn't come up as
a surprise :-)
OK, I got carried away a bit too much. Please disregard
the "replace" word -- at this point, it's way premature.
Let's say "find an alternative". What it really becomes in
the end is hard to know at this point.
Sorry, and thanks for understanding.
LT
with a mechanism that is similarly powerful, caters to
similar use cases, but removes an important
architectural constraint (the need for everything to run
in a single JVM).
As a developer, I want to use the CDI
extension to:
Providing its own beans, interceptors and
decorators to the container
The `@Discovery` phase has a method to add arbitrary
classes to the "application". If such class doesn't have
a bean defining annotation etc., you can add those
annotation in the `@Enhancement` phase.
Injecting dependencies into its own objects
using the dependency injection service
Sorry, I'm not sure what this means.
Is this about extension-contributed classes being
treated as application classes, i.e. can have
dependencies injected and themselves being injected, can
declare observers, etc. etc.? If so, then sure, I'd say
that's a given.
Or is this about being able to access the extension
instance at application runtime? That would be a no-no
I'm afraid. The instance is potentially long gone when
the application starts. The class is potentially a
different class (loaded by a different classloader in a
different JVM).
Providing a context implementation for a
custom scope
The `@Discovery` phase has a method to register custom
context class. If the class doesn't have all the
necessary metadata (such as the scope annotation), the
API also has methods to set those.
Augmenting or overriding the annotation-based
metadata with metadata from some other source
The `@Enhancement` phase is all about this.
There's also an API to add synthetic beans and
observers (`@Synthesis`), and an API for validating the
application and preventing successful build/deployment
(`@Validation`). To sum up, the most important use cases
for CDI extensions, as far as I can tell, are covered.
LT, can you double check whether this is the use
case your PR is for? It will be very appreciated if
you can put some code snippets to demonstrate how to
achieve some of the use cases.
OK, let me try.
Registering a custom context:
public class MyContext implements AlterableContext { ... }
public class MyExtension {
@Discovery
public void customContext(Contexts contexts) {
contexts.add().implementation(MyContext.class);
}
}
Contributing a bean to the application:
@ApplicationScoped
public class MyBean { ... }
public class MyExtension {
@Discovery
public void customBean(AppArchiveBuilder app) {
app.add(MyBean.class);
}
}
Contributing a non-bean class to the application and
making it a bean:
public class MyBean { ... }
public class MyExtension {
@Discovery
public void customClass(AppArchiveBuilder app) {
app.add(MyBean.class);
}
@Enhancement
public void makeItABean(ClassConfig<MyBean> bean) {
bean.addAnnotation(ApplicationScoped.class);
}
}
Vetoing a bean:
public class MyExtension {
@Enhancement
public void vetoABean(ClassConfig<SomeBean> bean) {
bean.addAnnotation(Vetoed.class);
}
}
Makes sense? I know these are toy examples, but should
give you an idea.
LT
If you can't deal with some of the use cases
listed above, we can discuss here on whether we
should reduce the scope or we can suggest some
alternative solutions.
Thanks,
Emily
On Wed, Sep 30, 2020
at 9:41 AM Ladislav Thon <lthon@xxxxxxxxxx>
wrote:
Yes. With (truly!!) all
respect to Antoine, it's a
bit all over the place and
not a list of use cases or
goals.
Can we just put down
here, in simple bullet point
formats, what at least the
goals of this effort are?
I don't mean to suggest
this is a trivial exercise,
because it is not, and Emily
certainly tried to get it
rolling before (mostly
unsuccessfully) with issue
#425 (https://github.com/eclipse-ee4j/cdi/issues/425;
and I applaud her attempt to
start with the use cases).
But let's try again, here,
publicly, on this list.
For the record, I'm
definitely aware of
{handwave} build time
{handwave} no reflection
{handwave} but I'm quite
sure we can do better than
that as a group. Here is an
incomplete sketch of one
example of the sort of thing
I had in mind.
Meta-goal: disrupt the
specification as little as
humanly possible (true of
all specifications
everywhere that are this
old)
Goal: permit a CDI
SeContainer to run a
precomputed set of beans
without having to run
portable extensions
Why: certain products
create their beans at build
time/ahead of time: we want
them to be part of the CDI
fold as well
Hindrance: the
SeContainerInitializer/portable
extension APIs, even with
something like
SeContainerInitializer.disableDiscovery().addExtension(new
Extension() { /* add beans
here however they are
generated/created */ }) is
insufficient because of X, Y
and Z
Hindrance: all (not just
some) portable extensions
must be available at runtime
via
BeanManager#getExtension()
…etc. and so on. I can
see the germs of something
like this lurking in your
posts and others' and in
Antoine's blog article and
elsewhere but I think it is
necessary that we have
small, traceable, actionable
goals spelled out here
before we try to solve them.
So I think we have explained the
why quite a bit, and importantly we
are talking about fundamental
compatibility differences (two-phase
multi-VM execution vs one phase), so
you are already at the point of having
to start anew. It’s not something that
a simple API tweak here and there is
going to solve.
Totally agree. I'd highlight what you put into
parens :-) I have never considered it a use
case, or anything worth extra mentioning, which
in hindsight is an obivous mistake, so let me
try to phrase it concretely.
Goal: modify the specification and the APIs to
no longer assume that everything happens in a
single JVM. It should be possible for a big part
of the "application initialization lifecycle",
including extensions, to run in another JVM, to
"pre-wire" the application statically and enable
significant performance gains during actual
application startup.
(I understand this might not necessarily be a
SMART goal. Sorry about that, I'm a simple man
and prefer debating concrete ideas rather than
abstract methodologies.)
Just a small clarification that I am
specifically referring to portable extensions
(#434) and the proposal (#451) which is the
subject of this thread. This is the area that
requires a reboot, to cover the same extension
author use cases.
The other areas of CDI are less of a
problem, each of those items will have their
own issue against them (which might involve
small spec wording changes). Some of them
might be future decision points (should lite
include X yes/no?) However, the hardest part
of a potential CDI-Lite is solving the
portable extension problem, so IMO it makes
sense to tackle this area first. FWIW we new
this would tough, so we first proposed just
leaving this aspect to venders, but a number
of commenters really wanted to see work on a
new SPI. So here we go :)