Destroying @Stateless proxies obtained via CDI.current().select()

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

Destroying @Stateless proxies obtained via CDI.current().select()

arjan tijms
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
[hidden email]
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.
Reply | Threaded
Open this post in threaded view
|

Re: Destroying @Stateless proxies obtained via CDI.current().select()

John D. Ament
Arjan,

So this recently came up as well with a PR raised to clarify how instance is used to destroy references: https://github.com/cdi-spec/cdi/pull/286


John

On Tue, May 10, 2016 at 11:11 AM arjan tijms <[hidden email]> wrote:
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
[hidden email]
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.

_______________________________________________
cdi-dev mailing list
[hidden email]
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.
Reply | Threaded
Open this post in threaded view
|

Re: Destroying @Stateless proxies obtained via CDI.current().select()

Martin Kouba
In reply to this post by arjan tijms
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
> [hidden email]
> 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
_______________________________________________
cdi-dev mailing list
[hidden email]
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.
Reply | Threaded
Open this post in threaded view
|

Re: Destroying @Stateless proxies obtained via CDI.current().select()

Mark Struberg
In reply to this post by John D. Ament
Imo the proxy is under the full control of the user.

Note that it is _not_ necessary to create a new proxy instance for each usage of a bean. All of the usages could really re-use the same proxy instance. Which of course internally points to different Contextual Instances...


In OWB we have a single proxy instance which we share across all Contextual Instances of the same Bean<T>.
You will hit the same issue when serialising the proxy, etc.
Sounds like an implementation glitch. But it should be easy to fix for Martin and Co.


LieGrue,
strub



On Wednesday, 11 May 2016, 1:36, John D. Ament <[hidden email]> wrote:


>
>
>Arjan,
>
>
>So this recently came up as well with a PR raised to clarify how instance is used to destroy references: https://github.com/cdi-spec/cdi/pull/286
>
>
>Take a look at the last paragraph here: http://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#dynamic_lookup
>
>
>John
>
>On Tue, May 10, 2016 at 11:11 AM arjan tijms <[hidden email]> wrote:
>
>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
>>[hidden email]
>>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.
>
>_______________________________________________
>cdi-dev mailing list
>[hidden email]
>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.
>
>
_______________________________________________
cdi-dev mailing list
[hidden email]
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.
Reply | Threaded
Open this post in threaded view
|

Re: Destroying @Stateless proxies obtained via CDI.current().select()

Martin Kouba
Just to be clear: we're not talking about client proxies (contextual
references) but contextual instances. For a SLSB when
Contextual.create() is called the container should create an internal
reference to the session bean and when the destroy() method is called,
the container should discard this internal reference.

See also 7.3.3. Lifecycle of stateless and singleton session beans [1].

Martin

[1]
http://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#stateless_lifecycle

Dne 11.5.2016 v 09:30 Mark Struberg napsal(a):

> Imo the proxy is under the full control of the user.
>
> Note that it is _not_ necessary to create a new proxy instance for each usage of a bean. All of the usages could really re-use the same proxy instance. Which of course internally points to different Contextual Instances...
>
>
> In OWB we have a single proxy instance which we share across all Contextual Instances of the same Bean<T>.
> You will hit the same issue when serialising the proxy, etc.
> Sounds like an implementation glitch. But it should be easy to fix for Martin and Co.
>
>
> LieGrue,
> strub
>
>
>
> On Wednesday, 11 May 2016, 1:36, John D. Ament <[hidden email]> wrote:
>
>
>>
>>
>> Arjan,
>>
>>
>> So this recently came up as well with a PR raised to clarify how instance is used to destroy references: https://github.com/cdi-spec/cdi/pull/286
>>
>>
>> Take a look at the last paragraph here: http://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#dynamic_lookup
>>
>>
>> John
>>
>> On Tue, May 10, 2016 at 11:11 AM arjan tijms <[hidden email]> wrote:
>>
>> 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
>>> [hidden email]
>>> 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.
>>
>> _______________________________________________
>> cdi-dev mailing list
>> [hidden email]
>> 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.
>>
>>
> _______________________________________________
> cdi-dev mailing list
> [hidden email]
> 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
_______________________________________________
cdi-dev mailing list
[hidden email]
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.
Reply | Threaded
Open this post in threaded view
|

Re: Destroying @Stateless proxies obtained via CDI.current().select()

arjan tijms
In reply to this post by Martin Kouba
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 <[hidden email]> 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
[hidden email]
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


_______________________________________________
cdi-dev mailing list
[hidden email]
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.
Reply | Threaded
Open this post in threaded view
|

Re: Destroying @Stateless proxies obtained via CDI.current().select()

Martin Kouba
Hi Arjan,

the test attached to WELD-2148 is wrong. We can not inspect an actual
SLSB instance. The only thing we could test is that Instance.destroy()
does not throw UnsupportedException for SLSB CDI reference.

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 <[hidden email]
> <mailto:[hidden email]>> 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
>         [hidden email] <mailto:[hidden email]>
>         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
_______________________________________________
cdi-dev mailing list
[hidden email]
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.
Reply | Threaded
Open this post in threaded view
|

Re: Destroying @Stateless proxies obtained via CDI.current().select()

arjan tijms
Hi,

On Wed, May 11, 2016 at 10:54 AM, Martin Kouba <[hidden email]> wrote:
Hi Arjan,

the test attached to WELD-2148 is wrong. We can not inspect an actual SLSB instance. The only thing we could test is that Instance.destroy() does not throw UnsupportedException for SLSB CDI reference.

I see, thanks for the clarification!

Going forward, would it not be convenient if an Instance was AutoCloseable, so that one could do:

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 <[hidden email]
<mailto:[hidden email]>> 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
        [hidden email] <mailto:[hidden email]>
        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


_______________________________________________
cdi-dev mailing list
[hidden email]
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.
Reply | Threaded
Open this post in threaded view
|

Re: Destroying @Stateless proxies obtained via CDI.current().select()

Martin Kouba

Dne 11.5.2016 v 11:20 arjan tijms napsal(a):

> Hi,
>
> On Wed, May 11, 2016 at 10:54 AM, Martin Kouba <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     Hi Arjan,
>
>     the test attached to WELD-2148 is wrong. We can not inspect an
>     actual SLSB instance. The only thing we could test is that
>     Instance.destroy() does not throw UnsupportedException for SLSB CDI
>     reference.
>
>
> I see, thanks for the clarification!
>
> Going forward, would it not be convenient if an Instance
> was AutoCloseable, so that one could do:

I don't think so. Remember that Instace is more like a "factory" and not
only for @Dependent objects. What would actually close() do? 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 <[hidden email]
>         <mailto:[hidden email]>
>         <mailto:[hidden email] <mailto:[hidden email]>>> 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
>         [hidden email] <mailto:[hidden email]>
>         <mailto:[hidden email] <mailto:[hidden email]>>
>         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
[hidden email]
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.
Reply | Threaded
Open this post in threaded view
|

Re: Destroying @Stateless proxies obtained via CDI.current().select()

arjan tijms
Hi,

On Wed, May 11, 2016 at 11:43 AM, Martin Kouba <[hidden email]> 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();
}

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 <[hidden email]
        <mailto:[hidden email]>
        <mailto:[hidden email] <mailto:[hidden email]>>> 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
        [hidden email] <mailto:[hidden email]>
        <mailto:[hidden email] <mailto:[hidden email]>>
        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
[hidden email]
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.
Reply | Threaded
Open this post in threaded view
|

Re: Destroying @Stateless proxies obtained via CDI.current().select()

John D. Ament


On Wed, May 11, 2016 at 5:58 AM arjan tijms <[hidden email]> wrote:
Hi,

On Wed, May 11, 2016 at 11:43 AM, Martin Kouba <[hidden email]> 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 <[hidden email]
        <mailto:[hidden email]>
        <mailto:[hidden email] <mailto:[hidden email]>>> 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
        [hidden email] <mailto:[hidden email]>
        <mailto:[hidden email] <mailto:[hidden email]>>
        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
[hidden email]
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.

_______________________________________________
cdi-dev mailing list
[hidden email]
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.
Reply | Threaded
Open this post in threaded view
|

Re: Destroying @Stateless proxies obtained via CDI.current().select()

Martin Kouba
In reply to this post by arjan tijms
Dne 11.5.2016 v 11:56 arjan tijms napsal(a):

> Hi,
>
> On Wed, May 11, 2016 at 11:43 AM, Martin Kouba <[hidden email]
> <mailto:[hidden email]>> 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();
}

>
> 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
>         <[hidden email] <mailto:[hidden email]>
>                  <mailto:[hidden email] <mailto:[hidden email]>>
>                  <mailto:[hidden email] <mailto:[hidden email]>
>         <mailto:[hidden email] <mailto:[hidden email]>>>> 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
>         [hidden email] <mailto:[hidden email]>
>         <mailto:[hidden email] <mailto:[hidden email]>>
>                  <mailto:[hidden email]
>         <mailto:[hidden email]> <mailto:[hidden email]
>         <mailto:[hidden email]>>>
>         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
[hidden email]
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.
Reply | Threaded
Open this post in threaded view
|

Re: Destroying @Stateless proxies obtained via CDI.current().select()

John D. Ament


On Wed, May 11, 2016 at 7:05 AM Martin Kouba <[hidden email]> wrote:
Dne 11.5.2016 v 11:56 arjan tijms napsal(a):
> Hi,
>
> On Wed, May 11, 2016 at 11:43 AM, Martin Kouba <[hidden email]
> <mailto:[hidden email]>> 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
>         <[hidden email] <mailto:[hidden email]>
>                  <mailto:[hidden email] <mailto:[hidden email]>>
>                  <mailto:[hidden email] <mailto:[hidden email]>
>         <mailto:[hidden email] <mailto:[hidden email]>>>> 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
>         [hidden email] <mailto:[hidden email]>
>         <mailto:[hidden email] <mailto:[hidden email]>>
>                  <mailto:[hidden email]
>         <mailto:[hidden email]> <mailto:[hidden email]
>         <mailto:[hidden email]>>>
>         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
[hidden email]
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.

_______________________________________________
cdi-dev mailing list
[hidden email]
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.