[cdi-dev] Destroying beans from an interceptor
arjan tijms
arjan.tijms at gmail.com
Mon Nov 10 08:59:07 EST 2014
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
More information about the cdi-dev
mailing list