[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