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