Did I understand this correctly? You like to destroy the contextual instance you are
currently intercepting?
If so, then I fear you would effectively kill yourself.
Please remember that an interceptor and decorator is per specification always a @Dependent
scoped 1:1 instance of the contextual instance it intercepts or decorates. Thus it also
gets stored in the CreationalContext of your very contextual instance. And by destroying
the contextual instance it's CreationalContext gets properly cleaned up and destroyed
as well. While doing so it will also destroy your interceptor/decorator.
Doesn't sound that healthy to me...
Maybe that might work for simple examples, but don't forget that real world apps are
no samples but much more complex and the side effects might be really ugly and highly
non-portable. Have a bad gut feeling about it.
LieGrue,
strub
On Monday, 10 November 2014, 14:59, arjan tijms
<arjan.tijms(a)gmail.com> wrote:
> Hi,
I wonder if it would be allowed according to the CDI spec to destroy a
bean instance from within an interceptor.
To test this (on Weld) I used the following code:
@Interceptor
@DestroyOnError
@Priority(APPLICATION)
public class DestroyOnErrorInterceptor implements Serializable {
private static final long serialVersionUID = 1L;
@AroundInvoke
public Object tryInvoke(InvocationContext ctx) throws Exception {
try {
return ctx.proceed();
} catch (Exception e) {
destroy(ctx.getMethod().getDeclaringClass());
throw e;
}
}
private <T> void destroy(Class<T> clazz) {
Instance<T> instance = CDI.current().select(clazz);
instance.destroy(instance.get());
}
}
When I use this interceptor on a SessionScoped bean:
@SessionScoped
public class TestBean implements Serializable {
private static final long serialVersionUID = 1L;
@DestroyOnError
public void test() {
throw new IllegalStateException();
}
}
And then inject said bean in say a Servlet and call the test() method,
destruction of the bean happens partially, but as soon as Weld tried
to invocate a preDestroy method, it goes through the bean proxy again,
detects that "the" interceptor handler is already active, promptly
skips its attempt to call a preDestroy method and then to add insult
to injury tries to call a "proceed" method which is always null and
thus throws a NPE.
(this happens in
org.jboss.weld.bean.proxy.CombinedInterceptorAndDecoratorStackMethodHandler.invoke)
I tried some alternative methods to destroy the bean such as:
Bean<T> bean = resolve(beanManager, beanClass);
AlterableContext context = (AlterableContext)
beanManager.getContext(bean.getScope());
context.destroy(bean);
with resolve being:
public static <T> Bean<T> resolve(BeanManager beanManager,
Class<T> beanClass) {
Set<Bean<?>> beans = beanManager.getBeans(beanClass);
for (Bean<?> bean : beans) {
if (bean.getBeanClass() == beanClass) {
return (Bean<T>)
beanManager.resolve(Collections.<Bean<?>>singleton(bean));
}
}
return (Bean<T>) beanManager.resolve(beans);
}
But this resulted in the same problem.
Any idea?
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.