[cdi-dev] Destroying @Stateless proxies obtained via CDI.current().select()

John D. Ament john.d.ament at gmail.com
Wed May 11 06:16:24 EDT 2016


On Wed, May 11, 2016 at 5:58 AM arjan tijms <arjan.tijms at gmail.com> wrote:

> Hi,
>
> On Wed, May 11, 2016 at 11:43 AM, Martin Kouba <mkouba at redhat.com> wrote:
>
>> I don't think so. Remember that Instace is more like a "factory" and not
>> only for @Dependent objects. What would actually close() do?
>
>
> I'd intuitively say release and where appropriate destroy all beans that
> were created from that particular instance of uhm Instance. But maybe the
> existing semantics of Instance aren't a good fit for that.
>
> Thinking out loud, maybe an AutoInstance variant?
>
> try (AutoInstance<Foo> fooInstance = CDI.current().autoSelect(Foo.class)) {
>
>      Foo foo = fooInstance.get();
>      foo.bar();
> }
>
>
Sounds very similar to my original proposal, I would just use dependent in
this case, unless we want to hide that from the developer.


> autoSelect could even throw early if the selected bean is not dependent
> scoped. But as mentioned, just thinking out loud here.
>
> Kind regards,
> Arjan Tijms
>
>
>
>
>
>> Also the users would be tempted to use this for injected Instance which
>> does not make sense.
>>
>>
>>> try (Instance<Foo> fooInstance =CDI.current().select(Foo.class)) {
>>>
>>>      Foo foo = fooInstance.get();
>>>      foo.bar();
>>> }
>>>
>>> Kind regards,
>>> Arjan Tijms
>>>
>>>
>>>
>>>
>>>     Martin
>>>
>>>     Dne 11.5.2016 v 10:40 arjan tijms napsal(a):
>>>
>>>         Hi Martin,
>>>
>>>         Thanks for the swift action and the reference. I do have one more
>>>         question looking at the test that was added. It now uses this
>>> SLSB:
>>>
>>>         @Stateless
>>>         public class SLSessionBean {
>>>
>>>               public void ping(){
>>>               }
>>>
>>>               static final AtomicBoolean DESTROYED = new AtomicBoolean();
>>>
>>>               @PreDestroy
>>>               public void destroy() {
>>>                   DESTROYED.set(true);
>>>               }
>>>         }
>>>
>>>         The assertion in the test is that the (a?) SLSB is actually
>>>         destroyed,
>>>         but wasn't the idea that only the internal reference is
>>>         destroyed, and
>>>         the bean just stays in the pool?
>>>
>>>         Here it looks like the code intends to destroy a random SLSB
>>>         instance
>>>         from the pool. (random, since I guess an internal reference
>>> doesn't
>>>         stick to the same actual instance of a SLSB, otherwise you would
>>> get
>>>         stateful like semantics).
>>>
>>>         Or did I miss something?
>>>
>>>         Kind regards,
>>>         Arjan Tijms
>>>
>>>
>>>
>>>
>>>         On Wed, May 11, 2016 at 9:11 AM, Martin Kouba <mkouba at redhat.com
>>>         <mailto:mkouba at redhat.com>
>>>         <mailto:mkouba at redhat.com <mailto:mkouba at redhat.com>>> wrote:
>>>
>>>              Hi Arjan,
>>>
>>>              I believe it's a Weld bug - you should be able to use
>>>              Instance.destroy() to discard an internal SLSB proxy. See
>>> also
>>>              "Lifecycle of stateless and singleton session beans" [1].
>>> Tomas
>>>              Remes created WELD-2148 to track this issue [2].
>>>
>>>              Also the "leak" is an expected behaviour. See for example
>>>         WELD-920
>>>              [3] discussion.
>>>
>>>              Martin
>>>
>>>              [1]
>>>
>>> http://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#stateless_lifecycle
>>>
>>>              [2]
>>>         https://issues.jboss.org/browse/WELD-2148
>>>
>>>              [3]
>>>         https://issues.jboss.org/browse/WELD-920
>>>
>>>              Dne 10.5.2016 v 17:11 arjan tijms napsal(a):
>>>
>>>                  Hi,
>>>
>>>                  Given a simple @Stateless bean:
>>>
>>>                  @Stateless
>>>                  public class Foo {
>>>                        public void bar() {}
>>>                  }
>>>
>>>                  Then requesting an instance of this via CDI as follows:
>>>
>>>                  Foo foo = CDI.current().select(Foo.class).get();
>>>
>>>                  Causes a lot of leaked proxy instances (at least on
>>>         Weld). Now
>>>                  what I
>>>                  guess needs to be done is destroying the proxy, taking
>>>         Antoine's
>>>                  answer
>>>                  here as a lead:
>>>
>>> http://stackoverflow.com/questions/28767536/scope-of-stateless-bean
>>>
>>>                  Only the following throws an
>>>         UnsupportedOperationException (on Weld
>>>                  2.3.2, haven't tested OWB yet)
>>>
>>>                  Instance<Foo> fooInstance
>>> =CDI.current().select(Foo.class);
>>>                  Foo foo = fooInstance.get();
>>>                  foo.bar();
>>>                  fooInstance.destroy(foo);
>>>
>>>                  The question is, is this how it's supposed to be done
>>>         via the spec?
>>>
>>>                  Implementation wise, what happens in Weld is that the
>>>         CDI/EJB proxy
>>>                  (com.test.Foo$Proxy$_$$_Weld$EnterpriseProxy$) in the
>>>         following code
>>>                  doesn't hit the check for a dependent instance
>>>         (comments in capitals
>>>                  added by me):
>>>
>>>
>>>                        public void destroy(T instance) {
>>>                            Preconditions.checkNotNull(instance);
>>>
>>>                            // check if this is a proxy of a
>>>         normal-scoped bean
>>>                            if (instance instanceof ProxyObject) {
>>>
>>>                                // THIS BRANCH IS TAKEN FOR CDI/EJB PROXY
>>>
>>>                                ProxyObject proxy = (ProxyObject)
>>> instance;
>>>                                if (proxy.getHandler() instanceof
>>>                  ProxyMethodHandler) {
>>>                                    ProxyMethodHandler handler =
>>>         (ProxyMethodHandler)
>>>                  proxy.getHandler();
>>>                                    Bean<?> bean = handler.getBean();
>>>                                    Context context =
>>>                  getBeanManager().getContext(bean.getScope());
>>>                                    if (context instanceof
>>>         AlterableContext) {
>>>                                        AlterableContext alterableContext
>>> =
>>>                  (AlterableContext) context;
>>>
>>>                                        // CONTEXT IS A
>>>         DEPENDENTCONTEXTIMPL THAT
>>>                  THROWS
>>>                                        // UnsupportedOperationException
>>>         FROM ITS
>>>                  DESTROY()
>>>                  METHOD
>>>                                        alterableContext.destroy(bean);
>>>                                        return;
>>>                                    } else {
>>>                                        throw
>>>                  BeanLogger.LOG.destroyUnsupported(context);
>>>                                    }
>>>                                }
>>>                            }
>>>
>>>                            // check if this is a dependent instance
>>>                            CreationalContext<? super T> ctx =
>>>         getCreationalContext();
>>>                            if (ctx instanceof WeldCreationalContext<?>) {
>>>                                WeldCreationalContext<? super T> weldCtx
>>>         = cast(ctx);
>>>
>>>                                // PROXY REFERENCES ARE KEPT HERE IN A
>>>                                // "dependentInstances" LIST, AND WOULD
>>>         BE CLEARED
>>>                  HERE
>>>                                // BUT THIS CODE IS NEVER REACHED
>>>
>>>  weldCtx.destroyDependentInstance(instance);
>>>                            }
>>>                        }
>>>
>>>                  Now I wonder, am I doing something wrong (according to
>>>         the CDI
>>>                  spec), or
>>>                  could this be a bug in the Weld code?
>>>
>>>                  Kind regards,
>>>                  Arjan Tijms
>>>
>>>
>>>                  _______________________________________________
>>>                  cdi-dev mailing list
>>>         cdi-dev at lists.jboss.org <mailto:cdi-dev at lists.jboss.org>
>>>         <mailto:cdi-dev at lists.jboss.org <mailto: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.
>>>
>>>
>>>              --
>>>              Martin Kouba
>>>              Software Engineer
>>>              Red Hat, Czech Republic
>>>
>>>
>>>
>>>     --
>>>     Martin Kouba
>>>     Software Engineer
>>>     Red Hat, Czech Republic
>>>
>>>
>>>
>> --
>> Martin Kouba
>> Software Engineer
>> Red Hat, Czech Republic
>>
> _______________________________________________
> 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/20160511/d594c1aa/attachment-0001.html 


More information about the cdi-dev mailing list