[cdi-dev] Enabling programmatic/synthetic decorators added by extension

arjan tijms arjan.tijms at gmail.com
Fri Mar 4 11:18:40 EST 2016


ProxyFactory sounds like a perfect solution indeed.

I now got something working, more or less, emphasis on less.

I first make a "normal" (but effectively dummy) decorator with @Priority
available:

@Decorator
@Priority(PLATFORM_BEFORE + 200)
public abstract class HttpAuthenticationBaseDecorator implements
HttpAuthenticationMechanism, Serializable {

    private static final long serialVersionUID = 1L;

    @Inject
    @Delegate
    HttpAuthenticationMechanism delegateMechanism;

    @Override
    public AuthStatus validateRequest(HttpServletRequest request,
HttpServletResponse response, HttpMessageContext httpMessageContext) throws
AuthException {
        return delegateMechanism.validateRequest(request, response,
httpMessageContext);
    }
   // ...
}


Then I create a "dynamic/programmatic" decorator:


public class DynamicHttpAuthenticationDecorator implements
Decorator<HttpAuthenticationBaseDecorator> {

    private final Set<Type> types = new
HashSet<Type>(asList(HttpAuthenticationBaseDecorator.class, Object.class));
    private final Set<Type> decoratedTypes =
singleton(HttpAuthenticationMechanism.class);

    private final BeanManager beanManager;
    private final InjectionPoint decoratorInjectionPoint;
    private final Set<InjectionPoint> injectionPoints;

    public DynamicHttpAuthenticationDecorator(BeanManager beanManager) {

        decoratorInjectionPoint = new DecoratorInjectionPoint(
            HttpAuthenticationMechanism.class,

beanManager.createAnnotatedType(HttpAuthenticationBaseDecorator.class).getFields().iterator().next(),
            this);

        injectionPoints = singleton(decoratorInjectionPoint);

        this.beanManager = beanManager;
    }

    public HttpAuthenticationBaseDecorator
create(CreationalContext<HttpAuthenticationBaseDecorator>
creationalContext) {
        return new AutoApplySessionDecorator(
            (HttpAuthenticationMechanism)
beanManager.getInjectableReference(decoratorInjectionPoint,
creationalContext));
    }

    public void destroy(HttpAuthenticationBaseDecorator instance,
CreationalContext<HttpAuthenticationBaseDecorator> creationalContext) {
        creationalContext.release();
    }

    public Set<Type> getTypes() {
        return types;
    }

    public Set<Type> getDecoratedTypes() {
        return decoratedTypes;
    }

    public Class<?> getBeanClass() {
        return HttpAuthenticationBaseDecorator.class;
    }

    public Type getDelegateType() {
        return HttpAuthenticationMechanism.class;
    }

    public Set<InjectionPoint> getInjectionPoints() {
        return injectionPoints;
    }
}

This Decorator<T> "pretends" that it's for the dummy decorator, via the
getTypes(), but in create() it returns another actual Decorator. Then I
create the delegate injection point of that decorator by grabbing the
@Delegate annotated field from the real decorator, wrapping that basically
in an InjectionPoint and then using that later with
beanManager#getInjectableReference.

Now after adding this via afterBeanDiscovery.addBean(new
DynamicHttpAuthenticationDecorator(beanManager)), and it actually gets
called at runtime (tested on Weld).

Disadvantages are a fixed priority and the fact that the dummy decorator is
called as well.

Have to say that implementing the javax.enterprise.inject.spi.Decorator
interface, especially the part for grabbing the @Delegate is quite
non-obvious.

What do you think, is this guaranteed to work, or did I abuse the CDI APIs
too much here?

Kind regards,
Arjan Tijms














On Wed, Mar 2, 2016 at 11:14 PM, Thomas Andraschko <
andraschko.thomas at gmail.com> wrote:

> +1
>
> in DeltaSpike we implemented an own mechanism + proxy to invoke
> interceptors for partial beans.
> We will probably enhance this for such usecases or even producers:
> https://issues.apache.org/jira/browse/DELTASPIKE-1069
>
>
> 2016-03-02 22:51 GMT+01:00 Romain Manni-Bucau <rmannibucau at gmail.com>:
>
>> +1, seems it is the way to fix several issues without introducing a lot
>> of new concepts/API and in term of technical stack it is just standardizing
>> what is there.
>>
>>
>> Romain Manni-Bucau
>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
>> <http://rmannibucau.wordpress.com> | Github
>> <https://github.com/rmannibucau> | LinkedIn
>> <https://www.linkedin.com/in/rmannibucau> | Tomitriber
>> <http://www.tomitribe.com>
>>
>> 2016-03-02 22:48 GMT+01:00 Mark Struberg <struberg at yahoo.de>:
>>
>>> ProxyFactory…
>>>
>>> I’m really thinking about introducing something like javax.proxy, maybe
>>> as own sub-spec PDF…
>>>
>>> LieGrue,
>>> strub
>>>
>>>
>>> > Am 02.03.2016 um 16:31 schrieb arjan tijms <arjan.tijms at gmail.com>:
>>> >
>>> > Hi,
>>> >
>>> > I'm trying to add decorators and/or interceptors to a Bean<T> that's
>>> added via an extension. There doesn't seem to be any way to add
>>> interceptors, but decorators seem almost possible.
>>> >
>>> > I've added a decorator in the following way:
>>> >
>>> >
>>> > AnnotatedType<AutoApplySessionDecorator> annotatedType =
>>> beanManager.createAnnotatedType(AutoApplySessionDecorator.class);
>>> >
>>> > BeanAttributes<AutoApplySessionDecorator> beanAttributes =
>>> beanManager.createBeanAttributes(annotatedType);
>>> >
>>> > Bean<AutoApplySessionDecorator> bean =
>>> beanManager.createBean(beanAttributes, AutoApplySessionDecorator.class,
>>> beanManager.getInjectionTargetFactory(annotatedType));
>>> >
>>> > afterBeanDiscovery.addBean(bean);
>>> >
>>> > Where the "AutoApplySessionDecorator" is an existing (non-scanned)
>>> decorator just used as an example.
>>> >
>>> >
>>> > While this seems to work, the problem is with the enablement.
>>> @Priority is not processed in this way, since it's only read from an
>>> AnnotatedType that's been added to the deployment (see e.g. in Weld
>>> org.jboss.weld.bootstrap.BeanDeployer.processPriority(AnnotatedType<?>)).
>>> >
>>> > beans.xml is not really an option here due to the static nature of
>>> that and the fact that the decorator needs to be enabled dynamically here,
>>> plus that the implementation class of the decorator is a detail I would not
>>> like to expose to the application.
>>> >
>>> >
>>> > Is there any other way to either enable a (synthetic) decorator
>>> programmatically, or to add Interceptors to a programmatically added
>>> Bean<T>?
>>> >
>>> > Kind regards,
>>> > Arjan Tijms
>>> >
>>> > _______________________________________________
>>> > cdi-dev mailing list
>>> > cdi-dev at lists.jboss.org
>>> > 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.
>>>
>>>
>>> _______________________________________________
>>> cdi-dev mailing list
>>> cdi-dev at lists.jboss.org
>>> 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.
>>
>>
>>
>> _______________________________________________
>> cdi-dev mailing list
>> cdi-dev at lists.jboss.org
>> 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.
>>
>
>
> _______________________________________________
> cdi-dev mailing list
> cdi-dev at lists.jboss.org
> 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.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/cdi-dev/attachments/20160304/04901f05/attachment.html 


More information about the cdi-dev mailing list