[cdi-dev] Destroying beans from an interceptor

arjan tijms arjan.tijms at gmail.com
Mon Nov 10 10:43:55 EST 2014


Hi,

On Mon, Nov 10, 2014 at 4:21 PM, Mark Struberg <struberg at yahoo.de> wrote:
> Did I understand this correctly? You like to destroy the contextual instance you are currently intercepting?

Indeed, I hoped that if the interceptor method that called the destroy
doesn't do anything after that call and just immediately exits there
could be little harm done.

> If so, then I fear you would effectively kill yourself.

Perhaps, so that's unfortunate indeed. It -does- work when another
request thread within the same session calls the destroy method, even
when the first thread is still inside the session scoped bean or
interceptor. This other thread apparently gets a different proxy
instance.

> Doesn't sound that healthy to me...

Do you know of any other way via which I could automatically destroy a
bean after an exception? What I'm looking for is more of a "pure
interceptor"; a stateless interceptor that depends on nothing.
Basically what I would get if I manually wrapped an object.

As such I've been looking for a way to wrap the proxy that CDI
injects, but as of yet I haven't found a way to do so.

What I'm trying to implement is a copy of the feature EJB session
beans have, where a bean instance is by default automatically
destroyed after a (system) exception.

Kind regards,
Arjan Tijms





>
> 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 at 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 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.
>>


More information about the cdi-dev mailing list