[cdi-dev] Destroying beans from an interceptor

Jozef Hartinger jharting at redhat.com
Fri Nov 14 04:49:05 EST 2014


On 11/13/2014 04:27 PM, arjan tijms wrote:
> Hi,
>
> On Wednesday, November 12, 2014, Jozef Hartinger <jharting at redhat.com 
> <mailto:jharting at redhat.com>> wrote:
>
>     Hi Arjan,
>
>     there is a bug in Weld (WELD-1785) preventing this from working
>     which is going to be fixed in the next release. What you are doing
>     should work IMO as long as the interceptor does not call any other
>     methods on the target instance. 
>
>
> That's great to hear really.
>
> I'm slightly confused through why Mark thinks this cannot really work, 
> while you say it should.
Don't be confused by that. This often happens to me and Mark :-)
>
> Is there something in the spec that may need to be clarified here? Ie 
> some words about what an interceptor is at least allowed to do and 
> what is definitely not allowed?
>
>     In addition it must count with the target instance being destroyed
>     within the instance.destroy() call.
>
>
> Sorry, I don't fully follow this. You mean something must be counted?
I mean that the interceptor (and others in the chain) should be tolerant 
and not be surprised finding itself and the target bean destroyed 
immediately after the instance.destroy() call.
>
>
>     Perhaps a nicer way of doing this would be:
>
>     @Inject
>     @Intercepted
>     private Bean<?> bean;
>
>             Context context = manager.getContext(bean.getScope());
>             if (!(context instanceof AlterableContext)) {
>                 throw new IllegalStateException("Context does not
>     support removal of instances");
>             }
>             AlterableContext alterableContext =
>     AlterableContext.class.cast(context);
>             alterableContext.destroy(bean);
>
>
> I tried something close to that as well, just used the bean manager to 
> resolve a Bean from the target object. Thanks for the suggestion!
>
> Kind regards,
> Arjan
>
>
>     On 11/10/2014 02:59 PM, arjan tijms 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.
>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/cdi-dev/attachments/20141114/3ad08a78/attachment-0001.html 


More information about the cdi-dev mailing list