Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [cdi-dev] CDI future - problems and proposal


On 21 Oct 2020, at 19:19, arjan tijms <arjan.tijms@xxxxxxxxx> wrote:

Hi,

On Wed, Oct 21, 2020 at 5:17 PM Tomas Langer <tomas.langer@xxxxxxxxxx> wrote:

From Arjan Tijms:
 - Interceptors on programmatically created beans - I understand there should be a way to get appropriate decorated instance, that would apply all interceptors when methods are invoked on the returned instance; I think this must be handled with care with regard to the new features we discuss, as a bean computed at build time would already know about all its interceptors. Bean.create in such a case returns an already decorated instance. Why cannot this be done using extension to add an interceptor binding to the bean before it is set up?

The problem is that in Bean.create you'd normally return just an instance instantiated with say new. There's no API available to know about all its interceptors, yet the Bean<T> contract, more specifically javax.enterprise.context.spi.Contextual.create(CreationalContext<T>), demands that the returned instance is already decorated.

As the Bean<T> is by definition added using an extension, I'm not 100% sure what you mean by "add an interceptor binding to the bean before it is set up". How would one go about doing that?

What I expect the process is (before we reach Bean instance):
- there is an annotated type that is processed, or a synthetic annotated type is created in before bean discovery
- extension can process these annotated types, for example by adding an interceptor binding to them (or vetoing them etc.)

So for each of these, the interceptors should be configured by the container based on the annotated type.

The only problem I see if an extension creates an actual synthetic bean instance (e.g. a class implementing Bean<X>), and registers it in AfterBeanDiscovery using the addBean(Bean) method.
If that is the use case you refer to, then I understand that you may be in trouble when it comes to interceptors (though a lot of cases may be covered by `BeanConfigurator addBean()` method in AfterBeanDiscovery).

Anybody else has a solution for this use case? 

If not, then maybe we could add something like (to AfterBeanDiscovery?):
Bean<X> decorate(Bean<X>, Annotation… interceptorBindings)

Would this be helpful? 


 
 - Access to injection point in Bean#create() -  Do you envision what change in API would be useful here? What is the needed (additional) metadata you want to obtain from the injection point? I guess some sort of “synthetic” injection point could be created when requesting this programmatically. Or we could add support for parameters to @Produces methods, that could be explicitly defined when invoking this...

The needed metadata is essentially everything an existing Producer (or Bean.create method that obtains the InjectionPoint) could see on the InjectionPoint. Parameters would partially solve it, but would make life more complicated for Producers, who then explicitly have to take into account both injected and programmatic lookup. A contrived example would be requesting beans made available by the MP Config API, for instance:

CDI.current().select(String.class, new ConfigPropertyLiteral(), new InjectionPointImpl().withMemberName("foo"));

I know there's other ways to do this, but it's just an example. Here the MP Producer would get to see a non-null InjectionPoint instance, and when inspecting its member it would find the name "foo", and would therefore use that as the property name.

A new method with signature (pseudo code, I think we should make the programmatic lookup a bit easier..):
<T> T get(Class<? extends T> type, InjectionPoint ip, Annotation... qualifiers)

And your example (just switched params, to support varargs):
String property = CDI.current().get(String.class, InjectionPoint.builder().setDeclaringBean(getClass()).setMemberName(“foo”).build(), new ConfigPropertyLiteral());

I also think the producer API may require a bit of a change to support this use case. Currently you need to have a method for each produced type. And if the type is not known at extension processing time, you cannot prepare a CDI producer to match the injected type. We can prepare producers for primitive types and String, but not for a POJO owned by the application and only requested through API.

So for `CDI.current().select(MyPojo.class, injectionPoint, new ConfigPropertyLiteral(“my-pojo”))` it would be nice to have a producer that could cover any type (AFAIK this is not possible in current CDI), such as:
@Dependent
@Produces
@ConfigProperty
protected <T> T produceObject(InjectionPoint ip, Class<T> type) {
return ....
}
What do others think? Is this already possible in CDI, and if not, would this be a good path?


Kind regards,
Arjan Tijms


_______________________________________________
cdi-dev mailing list
cdi-dev@xxxxxxxxxxx
To unsubscribe from this list, visit https://urldefense.com/v3/__https://www.eclipse.org/mailman/listinfo/cdi-dev__;!!GqivPVa7Brio!Kn1bjYTEHIhUm3Ku3E75QMYK2YPOvtrldvolNxdpJwWlW32MaT6X_0moWpaFuA6Icg$

Tomas

Back to the top