[cdi-dev] Destroying @Stateless proxies obtained via CDI.current().select()
John D. Ament
john.d.ament at gmail.com
Wed May 11 20:49:32 EDT 2016
On Wed, May 11, 2016 at 7:05 AM Martin Kouba <mkouba at redhat.com> wrote:
> Dne 11.5.2016 v 11:56 arjan tijms napsal(a):
> > Hi,
> >
> > On Wed, May 11, 2016 at 11:43 AM, Martin Kouba <mkouba at redhat.com
> > <mailto: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();
> > }
>
> Well, I'm not sure it's worth adding a new interface + method in CDI API
> if the only purpose is to call Instance.destroy() (or possibly release()
> - see cdi/pull/286) automatically.
>
> Even now it's possible to have a wrapper/helper class for this, e.g.
> something like:
>
> class AutoDestroyable<T> implements AutoCloseable {
>
> static AutoDestroyable<T> from(Instance<T> instance) {
> return new AutoDestroyable(instance);
> }
>
> private final Instance<T> instance;
>
> private final T value;
>
> private AutoDestroyable(Instance<T> instance) {
> this.instance = instance;
> this.value = instance.get();
> }
>
> T get() {
> return value;
> }
>
> void close() {
> instance.destroy(value);
> }
>
> }
>
> try (AutoDestroyable<Foo> destroyableFoo =
> AutoDestroyable.from(CDI.current().select(Foo.class))) {
> Foo foo = destroyableFoo.get();
> foo.bar();
> }
>
>
To accomplish this without a spec change, means that essentially every app
in the world needs this utility. Its more scalable to write the fix once
and get it in the spec.
> >
> > 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>>
> > <mailto: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
> >>
> > <mailto: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
> >
> >
>
> --
> 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/20160512/0eae9af6/attachment-0001.html
More information about the cdi-dev
mailing list