Interceptor bindings from interceptor when using 2.0 interception factory

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Interceptor bindings from interceptor when using 2.0 interception factory

arjan tijms
Hi,

Normally a workaround to get the interceptor bindings from within an Interceptor is to inspect the target and/or the injected intercepted bean.

However, when adding an interceptor via the new CDI 2.0 interception factory, things become a bit more muddy.

See e.g. 



Weld has the following method to get the bindings from the InvocationContext:

Set<Annotation> bindings = (Set<Annotation>) invocationContext.getContextData().get("org.jboss.weld.interceptor.bindings");

But this is obviously non-standard.

Is there a standard way to get the bindings? Perhaps getting hold of the Bean<T> that represents the current Interceptor?

Kind regards,
Arjan Tijms

_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev

Note that for all code provided on this list, the provider licenses the code under the Apache License, Version 2 (http://www.apache.org/licenses/LICENSE-2.0.html). For all other ideas provided on this list, the provider waives all patent and other intellectual property rights inherent in such information.
Reply | Threaded
Open this post in threaded view
|

Re: Interceptor bindings from interceptor when using 2.0 interception factory

Martin Kouba
Hi Arjan,

comments inline...

Dne 21.8.2017 v 13:45 arjan tijms napsal(a):

> Hi,
>
> Normally a workaround to get the interceptor bindings from within an
> Interceptor is to inspect the target and/or the injected intercepted bean.
>
> However, when adding an interceptor via the new CDI 2.0 interception
> factory, things become a bit more muddy.
>
> See e.g.
>
> https://github.com/javaee-samples/javaee8-samples/blob/master/cdi/interception-factory/src/main/java/org/javaee8/cdi/interception/factory/MyGreetingProducer.java#L34
>
>
> Weld has the following method to get the bindings from the
> InvocationContext:
>
> Set<Annotation> bindings = (Set<Annotation>)
> invocationContext.getContextData().get("org.jboss.weld.interceptor.bindings");

In fact, a more safe way is to use the Weld API, cast the invocation
context to org.jboss.weld.interceptor.WeldInvocationContext and use the
appropriate methods.

>
> But this is obviously non-standard.

Yes. There is already a spec issue:
https://issues.jboss.org/browse/CDI-468 but this would require a change
in interceptors spec.

>
> Is there a standard way to get the bindings? Perhaps getting hold of the
> Bean<T> that represents the current Interceptor?

You can inject a bean with scope @Dependent, qualifier @Default and type
Interceptor into any interceptor instance. However, this will not help
for @Nonbinding value members of an interceptor binding.

>
> Kind regards,
> Arjan Tijms
>
>
> _______________________________________________
> cdi-dev mailing list
> [hidden email]
> https://lists.jboss.org/mailman/listinfo/cdi-dev
>
> Note that for all code provided on this list, the provider licenses the code under the Apache License, Version 2 (http://www.apache.org/licenses/LICENSE-2.0.html). For all other ideas provided on this list, the provider waives all patent and other intellectual property rights inherent in such information.
>

--
Martin Kouba
Senior Software Engineer
Red Hat, Czech Republic
_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev

Note that for all code provided on this list, the provider licenses the code under the Apache License, Version 2 (http://www.apache.org/licenses/LICENSE-2.0.html). For all other ideas provided on this list, the provider waives all patent and other intellectual property rights inherent in such information.
Reply | Threaded
Open this post in threaded view
|

Re: Interceptor bindings from interceptor when using 2.0 interception factory

arjan tijms
Hi,

On Mon, Aug 28, 2017 at 9:41 AM, Martin Kouba <[hidden email]> wrote:
Set<Annotation> bindings = (Set<Annotation>) invocationContext.getContextData().get("org.jboss.weld.interceptor.bindings");

In fact, a more safe way is to use the Weld API, cast the invocation context to org.jboss.weld.interceptor.WeldInvocationContext and use the appropriate methods.

Looking in the code that seems to do the same thing, at least in Weld 3.0.1.

Going via getContextData() is much easier though for code that has to support both Weld and OWB.

 

Yes. There is already a spec issue: https://issues.jboss.org/browse/CDI-468 but this would require a change in interceptors spec.

I read the issue, thanks for the pointer. I do wonder if the entry in the context data isn't the easiest option regardless. That might only require an update in the CDI spec. Essentially, just standardise the key being used?

Currently the interceptor factory is an absolutely fantastic feature, but its usefulness is greatly diminished by the fact that no interceptor at this moment can (reliably) retrieve the interceptor bindings for all CDI implementations.

The spec even uses dynamically adding @Transactional as an example;

 * <pre>
 * &#64;Produces
 * &#64;RequestScoped
 * public MyClass produceMyClass(InterceptionFactory<MyClass> factory) {
 *     factory.configure().add(new AnnotationLiteral<Transactional>() {
 *     });
 *     return factory.createInterceptedInstance(new MyClass());
 * }


But all the current interceptor implementations backing @Transactional do something like:

public Object proceed(InvocationContext ctx) throws Exception {
        Transactional transactionalAnnotation =
                ctx.getMethod().getAnnotation(Transactional.class);

So that clearly won't work.

The spec text for InterceptionFactory also doesn't mention this caveat at all. So I wonder, what was the intended approach for   InterceptionFactory and intercepter bindings with attributes?

Or was InterceptionFactory solely intended for intercepter bindings without (non-binding) attributes?

Kind regards,
Arjan Tijms


 



Is there a standard way to get the bindings? Perhaps getting hold of the Bean<T> that represents the current Interceptor?

You can inject a bean with scope @Dependent, qualifier @Default and type Interceptor into any interceptor instance. However, this will not help for @Nonbinding value members of an interceptor binding.


Kind regards,
Arjan Tijms


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev

Note that for all code provided on this list, the provider licenses the code under the Apache License, Version 2 (http://www.apache.org/licenses/LICENSE-2.0.html). For all other ideas provided on this list, the provider waives all patent and other intellectual property rights inherent in such information.


--
Martin Kouba
Senior Software Engineer
Red Hat, Czech Republic


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev

Note that for all code provided on this list, the provider licenses the code under the Apache License, Version 2 (http://www.apache.org/licenses/LICENSE-2.0.html). For all other ideas provided on this list, the provider waives all patent and other intellectual property rights inherent in such information.
Reply | Threaded
Open this post in threaded view
|

Re: Interceptor bindings from interceptor when using 2.0 interception factory

Martin Kouba
Dne 19.9.2017 v 13:37 arjan tijms napsal(a):

> Hi,
>
> On Mon, Aug 28, 2017 at 9:41 AM, Martin Kouba <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>         Set<Annotation> bindings = (Set<Annotation>)
>         invocationContext.getContextData().get("org.jboss.weld.interceptor.bindings");
>
>
>     In fact, a more safe way is to use the Weld API, cast the invocation
>     context to org.jboss.weld.interceptor.WeldInvocationContext and use
>     the appropriate methods.
>
>
> Looking in the code that seems to do the same thing, at least in Weld 3.0.1.

No really. Weld stores the bindings also in context data but the API is
using a direct reference to a stored set.

>
> Going via getContextData() is much easier though for code that has to
> support both Weld and OWB.

Yep, standardizing the key is the only viable solution without
interceptors spec change. However, it's not typesafe, easy-to-use, etc.

>
>
>
>     Yes. There is already a spec issue:
>     https://issues.jboss.org/browse/CDI-468
>     <https://issues.jboss.org/browse/CDI-468> but this would require a
>     change in interceptors spec.
>
>
> I read the issue, thanks for the pointer. I do wonder if the entry in
> the context data isn't the easiest option regardless. That might only
> require an update in the CDI spec. Essentially, just standardise the key
> being used?
>
> Currently the interceptor factory is an absolutely fantastic feature,
> but its usefulness is greatly diminished by the fact that no interceptor
> at this moment can (reliably) retrieve the interceptor bindings for all
> CDI implementations.
>
> The spec even uses dynamically adding @Transactional as an example;
>
>   * <pre>
>   * &#64;Produces
>   * &#64;RequestScoped
>   * public MyClass produceMyClass(InterceptionFactory<MyClass> factory) {
>   *     factory.configure().add(new AnnotationLiteral<Transactional>() {
>   *     });
>   *     return factory.createInterceptedInstance(new MyClass());
>   * }
>
>
> But all the current interceptor implementations backing @Transactional
> do something like:
>
> public Object proceed(InvocationContext ctx) throws Exception {
>          Transactional transactionalAnnotation =
>                  ctx.getMethod().getAnnotation(Transactional.class);

And this is obviously wrong. Recently, we've reviewed a Narayana PR
which is about to fix this problem:
https://github.com/jbosstm/narayana/pull/1211

I personally think that JTA TCK is missing some essential tests here.

>
> So that clearly won't work.
>
> The spec text for InterceptionFactory also doesn't mention this caveat
> at all. So I wonder, what was the intended approach for  
> InterceptionFactory and intercepter bindings with attributes?
>
> Or was InterceptionFactory solely intended for intercepter bindings
> without (non-binding) attributes?

I don't think this is an InterceptionFactory-specific problem. It's a
general issue. It should work the same if you use an extension to add an
interceptor binding.

>
> Kind regards,
> Arjan Tijms
>
>
>
>
>
>         Is there a standard way to get the bindings? Perhaps getting
>         hold of the Bean<T> that represents the current Interceptor?
>
>
>     You can inject a bean with scope @Dependent, qualifier @Default and
>     type Interceptor into any interceptor instance. However, this will
>     not help for @Nonbinding value members of an interceptor binding.
>
>
>         Kind regards,
>         Arjan Tijms
>
>
>         _______________________________________________
>         cdi-dev mailing list
>         [hidden email] <mailto:[hidden email]>
>         https://lists.jboss.org/mailman/listinfo/cdi-dev
>         <https://lists.jboss.org/mailman/listinfo/cdi-dev>
>
>         Note that for all code provided on this list, the provider
>         licenses the code under the Apache License, Version 2
>         (http://www.apache.org/licenses/LICENSE-2.0.html
>         <http://www.apache.org/licenses/LICENSE-2.0.html>). For all
>         other ideas provided on this list, the provider waives all
>         patent and other intellectual property rights inherent in such
>         information.
>
>
>     --
>     Martin Kouba
>     Senior Software Engineer
>     Red Hat, Czech Republic
>
>

--
Martin Kouba
Senior Software Engineer
Red Hat, Czech Republic
_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev

Note that for all code provided on this list, the provider licenses the code under the Apache License, Version 2 (http://www.apache.org/licenses/LICENSE-2.0.html). For all other ideas provided on this list, the provider waives all patent and other intellectual property rights inherent in such information.
Reply | Threaded
Open this post in threaded view
|

Re: Interceptor bindings from interceptor when using 2.0 interception factory

arjan tijms
Hi,

On Tue, Sep 19, 2017 at 1:59 PM, Martin Kouba <[hidden email]> wrote:


No really. Weld stores the bindings also in context data but the API is using a direct reference to a stored set.

Ah, ok, thx

 
Going via getContextData() is much easier though for code that has to support both Weld and OWB.

Yep, standardizing the key is the only viable solution without interceptors spec change. However, it's not typesafe, easy-to-use, etc.

I hear you. The question is when the earliest opportunity will be to update the interceptor spec then. With the whole Java EE transfer I guess this will have to wait at least until that transfer is complete. Hopefully in the new process we can have something like a hierarchical responsibility for specs, such that if e.g. Interceptors and AtInject is not explicitly open, but CDI is, that the CDI EG can take responsibility for it and make changes there.

For now though, if OWB could also store the bindings under some key, interceptors that are intended to be portable can practically check both keys then. Not ideal, but may be a good intermediate solution.

 
And this is obviously wrong. Recently, we've reviewed a Narayana PR which is about to fix this problem:
https://github.com/jbosstm/narayana/pull/1211

I personally think that JTA TCK is missing some essential tests here.

Agreed, and the Java EE Security TCK misses those same tests as well, as it also ships with interceptors.
 

I don't think this is an InterceptionFactory-specific problem. It's a general issue. It should work the same if you use an extension to add an interceptor binding.


You're right, the InterceptionFactory just brought it to the surface again for people testing CDI 2.0 features.

Handling stereotypes as per the issue can be a problem as well. I wonder, wouldn't it be convenient if CDI offers a utility method to look for an annotation where it would automatically recurses into stereotypes?

I created something like for OmniFaces a while ago:


Kind regards,
Arjan Tijms

 


Kind regards,
Arjan Tijms





        Is there a standard way to get the bindings? Perhaps getting
        hold of the Bean<T> that represents the current Interceptor?


    You can inject a bean with scope @Dependent, qualifier @Default and
    type Interceptor into any interceptor instance. However, this will
    not help for @Nonbinding value members of an interceptor binding.


        Kind regards,
        Arjan Tijms


        _______________________________________________
        cdi-dev mailing list
        [hidden email] <mailto:[hidden email]>
        https://lists.jboss.org/mailman/listinfo/cdi-dev
        <https://lists.jboss.org/mailman/listinfo/cdi-dev>

        Note that for all code provided on this list, the provider
        licenses the code under the Apache License, Version 2
        (http://www.apache.org/licenses/LICENSE-2.0.html
        <http://www.apache.org/licenses/LICENSE-2.0.html>). For all
        other ideas provided on this list, the provider waives all
        patent and other intellectual property rights inherent in such
        information.


    --     Martin Kouba
    Senior Software Engineer
    Red Hat, Czech Republic



--
Martin Kouba
Senior Software Engineer
Red Hat, Czech Republic


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev

Note that for all code provided on this list, the provider licenses the code under the Apache License, Version 2 (http://www.apache.org/licenses/LICENSE-2.0.html). For all other ideas provided on this list, the provider waives all patent and other intellectual property rights inherent in such information.
Reply | Threaded
Open this post in threaded view
|

Re: Interceptor bindings from interceptor when using 2.0 interception factory

arjan tijms
Hi,

On Tue, Sep 19, 2017 at 2:22 PM, arjan tijms <[hidden email]> wrote:
No really. Weld stores the bindings also in context data but the API is using a direct reference to a stored set.

[...]


I don't think this is an InterceptionFactory-specific problem. It's a general issue. It should work the same if you use an extension to add an interceptor binding.

So that would hold for Java EE 7 then as well. Last time I looked for Weld 3, but is there also a way to get the interceptor bindings (in a Weld specific way) from Weld 2? Say from a TerminalAroundInvokeInvocationContext?

Kind regards,
Arjan Tijms


_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev

Note that for all code provided on this list, the provider licenses the code under the Apache License, Version 2 (http://www.apache.org/licenses/LICENSE-2.0.html). For all other ideas provided on this list, the provider waives all patent and other intellectual property rights inherent in such information.
Reply | Threaded
Open this post in threaded view
|

Re: Interceptor bindings from interceptor when using 2.0 interception factory

Martin Kouba
Dne 13.10.2017 v 13:09 arjan tijms napsal(a):

> Hi,
>
> On Tue, Sep 19, 2017 at 2:22 PM, arjan tijms <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>         No really. Weld stores the bindings also in context data but the
>         API is using a direct reference to a stored set.
>
>
> [...]
>
>
>         I don't think this is an InterceptionFactory-specific problem.
>         It's a general issue. It should work the same if you use an
>         extension to add an interceptor binding.
>
>
> So that would hold for Java EE 7 then as well. Last time I looked for
> Weld 3, but is there also a way to get the interceptor bindings (in a
> Weld specific way) from Weld 2? Say from a
> TerminalAroundInvokeInvocationContext?

No, this is not possible in weld 2. Feel free to file a feature request
to backport this.

>
> Kind regards,
> Arjan Tijms
>

--
Martin Kouba
Senior Software Engineer
Red Hat, Czech Republic
_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev

Note that for all code provided on this list, the provider licenses the code under the Apache License, Version 2 (http://www.apache.org/licenses/LICENSE-2.0.html). For all other ideas provided on this list, the provider waives all patent and other intellectual property rights inherent in such information.
Reply | Threaded
Open this post in threaded view
|

Re: Interceptor bindings from interceptor when using 2.0 interception factory

arjan tijms
On Fri, Oct 13, 2017 at 12:35 PM, Martin Kouba <[hidden email]> wrote:

No, this is not possible in weld 2. Feel free to file a feature request to backport this.


Thx!

Kind regards,
Arjan Tijms

_______________________________________________
cdi-dev mailing list
[hidden email]
https://lists.jboss.org/mailman/listinfo/cdi-dev

Note that for all code provided on this list, the provider licenses the code under the Apache License, Version 2 (http://www.apache.org/licenses/LICENSE-2.0.html). For all other ideas provided on this list, the provider waives all patent and other intellectual property rights inherent in such information.