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(a)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(a)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(a)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(a)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(a)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(a)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(a)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(a)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.