Meeting on?
by John D. Ament
Just wanted to check, is today's meeting still planned?
John
8 years, 7 months
BeanManager visiblity and container archives
by Christian Kaltepoth
Hey all,
I would like to bring up an issue that we ran into while preparing Ozark
(the MVC 1.0 RI) to be usable as a container module in Glassfish. We
discussed this issue on Slack and discovered that Mojarra (JSF) and Soteria
(Security) had similar issues.
MVC 1.0 defines some extension points that users and 3rd party libraries
can implement to provide additional functionality. MVC uses CDI for looking
up all implementations of these extension point interfaces. Similar
concepts are used in in JSF. Historically JSF uses factories which users
can implement and register via faces-config.xml. Now for Java EE 8 it was
decided to prefer CDI to obtain such custom extension point implementations
(ViewHandler, NavigationHandler, etc). So basically JSF uses a similar
mechanism to lookup implementations of certain interfaces like MVC does.
As of today Ozark is basically a standard bean archive deployed together
with the application (in /WEB-INF/lib). Now we want to prepare Ozark to be
usable as a Glassfish module which is provided by the container. As CDI
doesn't discover bean archives installed as part of the container, we
wanted to basically remove beans.xml and provide an portable extension
which registers the required annotated types required for Ozark. AFAIK
Mojarra and Soteria are also doing it this way. Now as soon as we do this,
things are getting weird.
There are various ways to get a BeanManager to lookup beans provided by the
application:
- CDI.current().getBeanManager()
- @Inject BeanManager
- JNDI lookup
Now if we try to lookup beans deployed with the application (in
/WEB-INF/classes or in a library in /WEB-INF/lib) we don't get consistent
results (many thanks to Arjan Tijms for doing all the testing):
- In Glassfish we don't see application beans if we use the injected
BeanManager. Looking up the BeanManager via JNDI or using
CDI.current().getBeanManager() works fine.
- In Wildfly CDi.current() doesn't seem to find beans deployed with the
application. The injected BeanManager and the one looked up via JNDI works
fine.
So it looks like there are quite some inconsistencies between
implementations here.
*To sum it up:* In Java EE 8 more and more specs rely heavily on CDI. And
many specs allow the user and 3rd party libraries to implement interfaces
to extend functionality. But it looks like looking up such beans deployed
with the application from a container archive isn't working in a consistent
way.
I hope my explanation of this complicated topic isn't too bad. I hope that
we can start some discussion around this. Some of you already joined the
discussion on Slack and the corresponding pull request, but I would prefer
to discuss this here. :)
Christian
--
Christian Kaltepoth
Blog: http://blog.kaltepoth.de/
Twitter: http://twitter.com/chkal
GitHub: https://github.com/chkal
8 years, 7 months
[JBoss JIRA] (CDI-602) Unmanaged.UnmanagedInstance.disposed is never to true
by Martin Kouba (JIRA)
Martin Kouba created CDI-602:
--------------------------------
Summary: Unmanaged.UnmanagedInstance.disposed is never to true
Key: CDI-602
URL: https://issues.jboss.org/browse/CDI-602
Project: CDI Specification Issues
Issue Type: Bug
Affects Versions: 2.0-EDR1, 1.2.Final
Reporter: Martin Kouba
As a result an {{IllegalStateException}} is never thrown if any method is called on an instance that has already been disposed.
--
This message was sent by Atlassian JIRA
(v6.4.11#64026)
8 years, 7 months
CDI-519 notes
by Martin Kouba
Hi all,
John is questioning the clarification introduced in CDI-519. I think
it's correct although not quite intuitive.
Below are some notes we should consider (I know it's long but the topic
is quite complicated):
CreationalContext
=================
Besides other things, holds the references to all depenent bean
instances together with their CCs (for normal scopes this is the
responsibility of the context). So that these could be correctly
destroyed when CC.release() is called.
Note that the context must pass the same instance of CC to
Contextual.destroy() that it passed to Contextual.create() when it
created the instance.
Possible "leak" description
===========================
The problem is if an Instance is injected into a normal scoped bean Foo
and is used to get other @Dependent bean instances via Instance.get().
Each of this call returns a new depenent bean instance bound to the
lifecycle of the Instance, which is also depenent and so it's
effectively bound to the lifecycle of Foo. And that was the original
motivation to introduce Instance.destroy().
Instance.select()
=================
The spec states the select() method returns a child Instance. What is
that "child" is not defined though. In Weld, a child Instance shares the
CreationalContext of the parent Instance. And I think this makes sense.
CDI-519 summary
===============
Instance.destroy() cannot be used for dependent bean instances not
created by the same Instance object.
The reason: a dependent bean instance does not know the object it
depends on. So if we pass a dependent bean instance it must be "managed"
by the CC of the Instance. Otherwise, we would not be able to destroy
the bean instance and all its dependent dependencies correctly.
From the spec point of view it's clear:
"An instance of a bean with scope @Dependent obtained by direct
invocation of an Instance is a dependent object of the instance of
Instance." A dependent bean instance is bound to the lifecycle of
Instance (or one of its child) so the Instance should be responsible for
destroying it. Done.
From the user point of view: I don't think it's a big problem. BTW it
does not work in any CDI 1.1+ version of Weld. I'm not sure about OWB.
Impl notes
==========
If we allow this then we would probably have to create some central
registry of CCs and during Instance.destroy() iterate over all these CCs
and try to destroy given depenent bean instance. This will be
complicated, error-prone and inefficient.
Thanks,
--
Martin Kouba
Software Engineer
Red Hat, Czech Republic
8 years, 7 months
Meeting on today?
by John D. Ament
Hey guys
Wanted to make sure the meeting is scheduled for today.
If so, would like to broach the topic of the dependent scoped mess we have.
Second, if time permits, to discuss the new SE API PR.
John
8 years, 7 months
[JBoss JIRA] (CDI-414) Support for "self" injection or intercepted self invocation
by Pavel Pscheidl (JIRA)
[ https://issues.jboss.org/browse/CDI-414?page=com.atlassian.jira.plugin.sy... ]
Pavel Pscheidl commented on CDI-414:
------------------------------------
I think a good enough solution is to inject a Instance<T> object, where T is a generic type for the self-injecting bean.
{code:java}
public class Foo {
@Inject
private Instance<Foo> foo;
}
{code}
This works completely fine. Some kind of lazy-injecting proxy would be nice, but unnecessary. Since dependency injection is an acyclic graph, creating cycle dependecies is wrong. The code inside the bean should explicitely state (by calling foo.get()) that it wants to get "yet another" instance from the container.
Some (recursive) algorithms actually might want to use self-injected dependecies. However, the algorithm explicitely obtains the instance from the container and is in charge of stopping the recursion.
> Support for "self" injection or intercepted self invocation
> -----------------------------------------------------------
>
> Key: CDI-414
> URL: https://issues.jboss.org/browse/CDI-414
> Project: CDI Specification Issues
> Issue Type: Bug
> Components: Resolution
> Reporter: arjan tijms
> Fix For: 2.0 (discussion)
>
>
> Many features of CDI and EJB work by means of a proxy that intercepts calls and adds 'aspects'. In Java it's however not possible to decorate the {{this}} pointer, so methods called on the same bean instance from within a method in the bean do not get their 'aspects' applied.
> This is a well known limitation, but in EJB it's possible to work around this by injecting a bean into itself. E.g.
> {code}
> @Stateless
> public class Foo {
> @EJB
> private Foo self;
> // ...
> }
> {code}
> Also see http://adam-bien.com/roller/abien/entry/how_to_self_invoke_ejb
> Unfortunately using CDI and {{@Inject}} this doesn't work. Weld for instance fails the deployment and logs:
> {noformat}
> WELD-001443 Pseudo scoped bean has circular dependencies.
> {noformat}
> See also: http://adam-bien.com/roller/abien/entry/inject_vs_ejb
> Although there are workarounds, it would be great if {{@Inject}} in combination with CDI could support self injection as well.
> With that projects migrating from {{@EJB}} to {{@Inject}} can do so more easily and the capability can be convenient for new projects as well (e.g. calling two separate {{@Transactional}} methods from a single method without being required to create a new bean).
--
This message was sent by Atlassian JIRA
(v6.4.11#64026)
8 years, 7 months
[JBoss JIRA] (CDI-519) Instance.destroy() cannot be used for dependent bean instances not created by the same Instance object
by Antoine Sabot-Durand (JIRA)
[ https://issues.jboss.org/browse/CDI-519?page=com.atlassian.jira.plugin.sy... ]
Antoine Sabot-Durand reassigned CDI-519:
----------------------------------------
Fix Version/s: 2.0-EDR2
(was: 2.0 (discussion))
Assignee: Martin Kouba
Resolution: Done
> Instance.destroy() cannot be used for dependent bean instances not created by the same Instance object
> ------------------------------------------------------------------------------------------------------
>
> Key: CDI-519
> URL: https://issues.jboss.org/browse/CDI-519
> Project: CDI Specification Issues
> Issue Type: Clarification
> Affects Versions: 1.2.Final
> Reporter: Martin Kouba
> Assignee: Martin Kouba
> Fix For: 2.0-EDR2
>
>
> 5.6.1. The Instance interface:
> {quote}
> The method destroy() instructs the container to destroy the instance. The bean instance passed to destroy() should be *a dependent scoped bean instance*, or...
> {quote}
> I think this should be more obvious. E.g. this wouldn't work correctly even though it doesn't violate the spec:
> {code:java}
> @Dependent
> class Bar {
> }
> class Foo {
> @Inject
> Instance<Bar> instance;
> void ping() {
> instance.destroy(CDI.current().select(Bar.class).get());
> }
> }
> {code}
--
This message was sent by Atlassian JIRA
(v6.4.11#64026)
8 years, 7 months