<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Wed, May 11, 2016 at 7:05 AM Martin Kouba &lt;<a href="mailto:mkouba@redhat.com">mkouba@redhat.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Dne 11.5.2016 v 11:56 arjan tijms napsal(a):<br>
&gt; Hi,<br>
&gt;<br>
&gt; On Wed, May 11, 2016 at 11:43 AM, Martin Kouba &lt;<a href="mailto:mkouba@redhat.com" target="_blank">mkouba@redhat.com</a><br>
&gt; &lt;mailto:<a href="mailto:mkouba@redhat.com" target="_blank">mkouba@redhat.com</a>&gt;&gt; wrote:<br>
&gt;<br>
&gt;     I don&#39;t think so. Remember that Instace is more like a &quot;factory&quot; and<br>
&gt;     not only for @Dependent objects. What would actually close() do?<br>
&gt;<br>
&gt;<br>
&gt; I&#39;d intuitively say release and where appropriate destroy all beans that<br>
&gt; were created from that particular instance of uhm Instance. But maybe<br>
&gt; the existing semantics of Instance aren&#39;t a good fit for that.<br>
&gt;<br>
&gt; Thinking out loud, maybe an AutoInstance variant?<br>
&gt;<br>
&gt; try (AutoInstance&lt;Foo&gt; fooInstance = CDI.current().autoSelect(Foo.class)) {<br>
&gt;<br>
&gt;       Foo foo = fooInstance.get();<br>
&gt;       foo.bar();<br>
&gt; }<br>
<br>
Well, I&#39;m not sure it&#39;s worth adding a new interface + method in CDI API<br>
if the only purpose is to call Instance.destroy() (or possibly release()<br>
- see cdi/pull/286) automatically.<br>
<br>
Even now it&#39;s possible to have a wrapper/helper class for this, e.g.<br>
something like:<br>
<br>
class AutoDestroyable&lt;T&gt; implements AutoCloseable {<br>
<br>
   static AutoDestroyable&lt;T&gt; from(Instance&lt;T&gt; instance) {<br>
     return new AutoDestroyable(instance);<br>
   }<br>
<br>
   private final Instance&lt;T&gt; instance;<br>
<br>
   private final T value;<br>
<br>
   private AutoDestroyable(Instance&lt;T&gt; instance) {<br>
     this.instance = instance;<br>
     this.value = instance.get();<br>
   }<br>
<br>
   T get() {<br>
     return value;<br>
   }<br>
<br>
   void close() {<br>
      instance.destroy(value);<br>
   }<br>
<br>
}<br>
<br>
try (AutoDestroyable&lt;Foo&gt; destroyableFoo =<br>
AutoDestroyable.from(CDI.current().select(Foo.class))) {<br>
   Foo foo = destroyableFoo.get();<br>
   foo.bar();<br>
}<br>
<br></blockquote><div><br></div><div>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.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
&gt;<br>
&gt; autoSelect could even throw early if the selected bean is not dependent<br>
&gt; scoped. But as mentioned, just thinking out loud here.<br>
&gt;<br>
&gt; Kind regards,<br>
&gt; Arjan Tijms<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;     Also the users would be tempted to use this for injected Instance<br>
&gt;     which does not make sense.<br>
&gt;<br>
&gt;<br>
&gt;         try (Instance&lt;Foo&gt; fooInstance =CDI.current().select(Foo.class)) {<br>
&gt;<br>
&gt;               Foo foo = fooInstance.get();<br>
&gt;               foo.bar();<br>
&gt;         }<br>
&gt;<br>
&gt;         Kind regards,<br>
&gt;         Arjan Tijms<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;              Martin<br>
&gt;<br>
&gt;              Dne 11.5.2016 v 10:40 arjan tijms napsal(a):<br>
&gt;<br>
&gt;                  Hi Martin,<br>
&gt;<br>
&gt;                  Thanks for the swift action and the reference. I do<br>
&gt;         have one more<br>
&gt;                  question looking at the test that was added. It now<br>
&gt;         uses this SLSB:<br>
&gt;<br>
&gt;                  @Stateless<br>
&gt;                  public class SLSessionBean {<br>
&gt;<br>
&gt;                        public void ping(){<br>
&gt;                        }<br>
&gt;<br>
&gt;                        static final AtomicBoolean DESTROYED = new<br>
&gt;         AtomicBoolean();<br>
&gt;<br>
&gt;                        @PreDestroy<br>
&gt;                        public void destroy() {<br>
&gt;                            DESTROYED.set(true);<br>
&gt;                        }<br>
&gt;                  }<br>
&gt;<br>
&gt;                  The assertion in the test is that the (a?) SLSB is actually<br>
&gt;                  destroyed,<br>
&gt;                  but wasn&#39;t the idea that only the internal reference is<br>
&gt;                  destroyed, and<br>
&gt;                  the bean just stays in the pool?<br>
&gt;<br>
&gt;                  Here it looks like the code intends to destroy a random<br>
&gt;         SLSB<br>
&gt;                  instance<br>
&gt;                  from the pool. (random, since I guess an internal<br>
&gt;         reference doesn&#39;t<br>
&gt;                  stick to the same actual instance of a SLSB, otherwise<br>
&gt;         you would get<br>
&gt;                  stateful like semantics).<br>
&gt;<br>
&gt;                  Or did I miss something?<br>
&gt;<br>
&gt;                  Kind regards,<br>
&gt;                  Arjan Tijms<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;                  On Wed, May 11, 2016 at 9:11 AM, Martin Kouba<br>
&gt;         &lt;<a href="mailto:mkouba@redhat.com" target="_blank">mkouba@redhat.com</a> &lt;mailto:<a href="mailto:mkouba@redhat.com" target="_blank">mkouba@redhat.com</a>&gt;<br>
&gt;                  &lt;mailto:<a href="mailto:mkouba@redhat.com" target="_blank">mkouba@redhat.com</a> &lt;mailto:<a href="mailto:mkouba@redhat.com" target="_blank">mkouba@redhat.com</a>&gt;&gt;<br>
&gt;                  &lt;mailto:<a href="mailto:mkouba@redhat.com" target="_blank">mkouba@redhat.com</a> &lt;mailto:<a href="mailto:mkouba@redhat.com" target="_blank">mkouba@redhat.com</a>&gt;<br>
&gt;         &lt;mailto:<a href="mailto:mkouba@redhat.com" target="_blank">mkouba@redhat.com</a> &lt;mailto:<a href="mailto:mkouba@redhat.com" target="_blank">mkouba@redhat.com</a>&gt;&gt;&gt;&gt; wrote:<br>
&gt;<br>
&gt;                       Hi Arjan,<br>
&gt;<br>
&gt;                       I believe it&#39;s a Weld bug - you should be able to use<br>
&gt;                       Instance.destroy() to discard an internal SLSB<br>
&gt;         proxy. See also<br>
&gt;                       &quot;Lifecycle of stateless and singleton session<br>
&gt;         beans&quot; [1]. Tomas<br>
&gt;                       Remes created WELD-2148 to track this issue [2].<br>
&gt;<br>
&gt;                       Also the &quot;leak&quot; is an expected behaviour. See for<br>
&gt;         example<br>
&gt;                  WELD-920<br>
&gt;                       [3] discussion.<br>
&gt;<br>
&gt;                       Martin<br>
&gt;<br>
&gt;                       [1]<br>
&gt;         <a href="http://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#stateless_lifecycle" rel="noreferrer" target="_blank">http://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#stateless_lifecycle</a><br>
&gt;<br>
&gt;                       [2]<br>
&gt;         <a href="https://issues.jboss.org/browse/WELD-2148" rel="noreferrer" target="_blank">https://issues.jboss.org/browse/WELD-2148</a><br>
&gt;<br>
&gt;                       [3]<br>
&gt;         <a href="https://issues.jboss.org/browse/WELD-920" rel="noreferrer" target="_blank">https://issues.jboss.org/browse/WELD-920</a><br>
&gt;<br>
&gt;                       Dne 10.5.2016 v 17:11 arjan tijms napsal(a):<br>
&gt;<br>
&gt;                           Hi,<br>
&gt;<br>
&gt;                           Given a simple @Stateless bean:<br>
&gt;<br>
&gt;                           @Stateless<br>
&gt;                           public class Foo {<br>
&gt;                                 public void bar() {}<br>
&gt;                           }<br>
&gt;<br>
&gt;                           Then requesting an instance of this via CDI as<br>
&gt;         follows:<br>
&gt;<br>
&gt;                           Foo foo = CDI.current().select(Foo.class).get();<br>
&gt;<br>
&gt;                           Causes a lot of leaked proxy instances (at<br>
&gt;         least on<br>
&gt;                  Weld). Now<br>
&gt;                           what I<br>
&gt;                           guess needs to be done is destroying the<br>
&gt;         proxy, taking<br>
&gt;                  Antoine&#39;s<br>
&gt;                           answer<br>
&gt;                           here as a lead:<br>
&gt;         <a href="http://stackoverflow.com/questions/28767536/scope-of-stateless-bean" rel="noreferrer" target="_blank">http://stackoverflow.com/questions/28767536/scope-of-stateless-bean</a><br>
&gt;<br>
&gt;                           Only the following throws an<br>
&gt;                  UnsupportedOperationException (on Weld<br>
&gt;                           2.3.2, haven&#39;t tested OWB yet)<br>
&gt;<br>
&gt;                           Instance&lt;Foo&gt; fooInstance<br>
&gt;         =CDI.current().select(Foo.class);<br>
&gt;                           Foo foo = fooInstance.get();<br>
&gt;                           foo.bar();<br>
&gt;                           fooInstance.destroy(foo);<br>
&gt;<br>
&gt;                           The question is, is this how it&#39;s supposed to<br>
&gt;         be done<br>
&gt;                  via the spec?<br>
&gt;<br>
&gt;                           Implementation wise, what happens in Weld is<br>
&gt;         that the<br>
&gt;                  CDI/EJB proxy<br>
&gt;                           (com.test.Foo$Proxy$_$$_Weld$EnterpriseProxy$)<br>
&gt;         in the<br>
&gt;                  following code<br>
&gt;                           doesn&#39;t hit the check for a dependent instance<br>
&gt;                  (comments in capitals<br>
&gt;                           added by me):<br>
&gt;<br>
&gt;<br>
&gt;                                 public void destroy(T instance) {<br>
&gt;                                     Preconditions.checkNotNull(instance);<br>
&gt;<br>
&gt;                                     // check if this is a proxy of a<br>
&gt;                  normal-scoped bean<br>
&gt;                                     if (instance instanceof ProxyObject) {<br>
&gt;<br>
&gt;                                         // THIS BRANCH IS TAKEN FOR<br>
&gt;         CDI/EJB PROXY<br>
&gt;<br>
&gt;                                         ProxyObject proxy =<br>
&gt;         (ProxyObject) instance;<br>
&gt;                                         if (proxy.getHandler() instanceof<br>
&gt;                           ProxyMethodHandler) {<br>
&gt;                                             ProxyMethodHandler handler =<br>
&gt;                  (ProxyMethodHandler)<br>
&gt;                           proxy.getHandler();<br>
&gt;                                             Bean&lt;?&gt; bean =<br>
&gt;         handler.getBean();<br>
&gt;                                             Context context =<br>
&gt;                           getBeanManager().getContext(bean.getScope());<br>
&gt;                                             if (context instanceof<br>
&gt;                  AlterableContext) {<br>
&gt;                                                 AlterableContext<br>
&gt;         alterableContext =<br>
&gt;                           (AlterableContext) context;<br>
&gt;<br>
&gt;                                                 // CONTEXT IS A<br>
&gt;                  DEPENDENTCONTEXTIMPL THAT<br>
&gt;                           THROWS<br>
&gt;                                                 //<br>
&gt;         UnsupportedOperationException<br>
&gt;                  FROM ITS<br>
&gt;                           DESTROY()<br>
&gt;                           METHOD<br>
&gt;<br>
&gt;           alterableContext.destroy(bean);<br>
&gt;                                                 return;<br>
&gt;                                             } else {<br>
&gt;                                                 throw<br>
&gt;                           BeanLogger.LOG.destroyUnsupported(context);<br>
&gt;                                             }<br>
&gt;                                         }<br>
&gt;                                     }<br>
&gt;<br>
&gt;                                     // check if this is a dependent instance<br>
&gt;                                     CreationalContext&lt;? super T&gt; ctx =<br>
&gt;                  getCreationalContext();<br>
&gt;                                     if (ctx instanceof<br>
&gt;         WeldCreationalContext&lt;?&gt;) {<br>
&gt;                                         WeldCreationalContext&lt;? super T&gt;<br>
&gt;         weldCtx<br>
&gt;                  = cast(ctx);<br>
&gt;<br>
&gt;                                         // PROXY REFERENCES ARE KEPT<br>
&gt;         HERE IN A<br>
&gt;                                         // &quot;dependentInstances&quot; LIST,<br>
&gt;         AND WOULD<br>
&gt;                  BE CLEARED<br>
&gt;                           HERE<br>
&gt;                                         // BUT THIS CODE IS NEVER REACHED<br>
&gt;<br>
&gt;           weldCtx.destroyDependentInstance(instance);<br>
&gt;                                     }<br>
&gt;                                 }<br>
&gt;<br>
&gt;                           Now I wonder, am I doing something wrong<br>
&gt;         (according to<br>
&gt;                  the CDI<br>
&gt;                           spec), or<br>
&gt;                           could this be a bug in the Weld code?<br>
&gt;<br>
&gt;                           Kind regards,<br>
&gt;                           Arjan Tijms<br>
&gt;<br>
&gt;<br>
&gt;                           _______________________________________________<br>
&gt;                           cdi-dev mailing list<br>
&gt;         <a href="mailto:cdi-dev@lists.jboss.org" target="_blank">cdi-dev@lists.jboss.org</a> &lt;mailto:<a href="mailto:cdi-dev@lists.jboss.org" target="_blank">cdi-dev@lists.jboss.org</a>&gt;<br>
&gt;         &lt;mailto:<a href="mailto:cdi-dev@lists.jboss.org" target="_blank">cdi-dev@lists.jboss.org</a> &lt;mailto:<a href="mailto:cdi-dev@lists.jboss.org" target="_blank">cdi-dev@lists.jboss.org</a>&gt;&gt;<br>
&gt;                  &lt;mailto:<a href="mailto:cdi-dev@lists.jboss.org" target="_blank">cdi-dev@lists.jboss.org</a><br>
&gt;         &lt;mailto:<a href="mailto:cdi-dev@lists.jboss.org" target="_blank">cdi-dev@lists.jboss.org</a>&gt; &lt;mailto:<a href="mailto:cdi-dev@lists.jboss.org" target="_blank">cdi-dev@lists.jboss.org</a><br>
&gt;         &lt;mailto:<a href="mailto:cdi-dev@lists.jboss.org" target="_blank">cdi-dev@lists.jboss.org</a>&gt;&gt;&gt;<br>
&gt;         <a href="https://lists.jboss.org/mailman/listinfo/cdi-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/cdi-dev</a><br>
&gt;<br>
&gt;                           Note that for all code provided on this list,<br>
&gt;         the provider<br>
&gt;                           licenses the code under the Apache License,<br>
&gt;         Version 2<br>
&gt;<br>
&gt;           (<a href="http://www.apache.org/licenses/LICENSE-2.0.html" rel="noreferrer" target="_blank">http://www.apache.org/licenses/LICENSE-2.0.html</a>). For<br>
&gt;                  all other<br>
&gt;                           ideas provided on this list, the provider<br>
&gt;         waives all<br>
&gt;                  patent and<br>
&gt;                           other intellectual property rights inherent in<br>
&gt;         such<br>
&gt;                  information.<br>
&gt;<br>
&gt;<br>
&gt;                       --<br>
&gt;                       Martin Kouba<br>
&gt;                       Software Engineer<br>
&gt;                       Red Hat, Czech Republic<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;              --<br>
&gt;              Martin Kouba<br>
&gt;              Software Engineer<br>
&gt;              Red Hat, Czech Republic<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;     --<br>
&gt;     Martin Kouba<br>
&gt;     Software Engineer<br>
&gt;     Red Hat, Czech Republic<br>
&gt;<br>
&gt;<br>
<br>
--<br>
Martin Kouba<br>
Software Engineer<br>
Red Hat, Czech Republic<br>
_______________________________________________<br>
cdi-dev mailing list<br>
<a href="mailto:cdi-dev@lists.jboss.org" target="_blank">cdi-dev@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/cdi-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/cdi-dev</a><br>
<br>
Note that for all code provided on this list, the provider licenses the code under the Apache License, Version 2 (<a href="http://www.apache.org/licenses/LICENSE-2.0.html" rel="noreferrer" target="_blank">http://www.apache.org/licenses/LICENSE-2.0.html</a>). For all other ideas provided on this list, the provider waives all patent and other intellectual property rights inherent in such information.<br>
</blockquote></div></div>