[hibernate-dev] CDI integration in Hibernate ORM and the Application scope

Sanne Grinovero sanne at hibernate.org
Thu Jan 4 11:41:32 EST 2018


On 4 January 2018 at 16:39, Sanne Grinovero <sanne at hibernate.org> wrote:
> On 4 January 2018 at 14:19, Steve Ebersole <steve at hibernate.org> wrote:
>> Well there seems to be some disagreement about that.  I personally think we
>> do not need anything other than a pre-shutdown hook so that we can release
>> our CDI references.  Sanne seemed to think we needed something more
>> "integrated".  I think we should start with the simple and add deeper
>> integration (which requires actual CDI changes) only if we see that is
>> necessary.  Sanne?
>
> I guess it's totally possible that the current solution you all have
> been working on covers most practical use cases and most immediate
> user's needs, so that's great, but I wonder if we can clearly document
> the limitations which I'm assuming we have (I can't).
>
> I don't believe we can handle all complex dependency graphs that a CDI
> user might expect with before & after phases, however I had no time to
> prove this with a meaningful example.
>
> If someone with more CDI experience could experiment with complex
> dependency graphs then we should be able to better document the
> limitations - which I strongly suspect exist - and make a good case to
> need the JPA/CDI integration deeper at spec level, however "make it
> work as users expect" might not be worthwhile of a spec update, one
> could say it's the implementation's job so essentially a problem in
> how we deal with integration details.
>
> It's possible that there's no practical need for such a deeper
> integration but it makes me a bit nervous to not be able to specify
> the limitations to users.
>
> More concrete example: Steve mentions having a "PRE-shutdown hook" to
> release our references to managed beans; what if some other beans
> depend on these? What if these other beans have wider scopes, like app
> scope? Clearly the CDI engine is in the position to figure this out
> and might want to initiate a cascade shutdown of such other beans
> (which we don't manage directly) so this is essentially initiating a
> whole-shutdown (not just a PRE-shutdown).
>
> Vice-versa, same situation can arise during initialization; I'm afraid
> this would get hairy quickly, while supposedly any CDI implementation
> should have the means to handle ordering details appropriately, so I'd
> hope we delegate it all to it to happen during its normal phases
> rather than layering outer/inner phases around.
>
> I'm not sure who to ask for a better opinion; I'll add Stuart in CC as
> he's the only smart person I know with deep expertise in both
> Hibernate and CDI, with some luck he'll say I'm wrong and we're good
> :)

Lol, re-reading "Hibernate + CDI expertise" it's hilarious I forgot
the most obvious expert name :)
Not sure if Gavin is interested but I'll add him too.

Thanks,
Sanne

>
> Thanks,
> Sanne
>
>
>>
>> On Thu, Jan 4, 2018 at 7:58 AM Scott Marlow <smarlow at redhat.com> wrote:
>>>
>>> I can arrange to keep access to the specific
>>> ExtendedBeanManager/LifecycleListener, that is not difficult.
>>>
>>> What changes do we need from the CDI implementation?
>>>
>>>
>>> On Jan 3, 2018 4:36 PM, "Steve Ebersole" <steve at hibernate.org> wrote:
>>>
>>> If you have access to the specific ExtendedBeanManager/LifecycleListener,
>>> that should already be enough.  Those things are already properly scoped to
>>> the SessionFactory, unless you are passing the same instance to multiple
>>> SessionFactory instances.
>>>
>>> On Wed, Jan 3, 2018 at 10:09 AM Scott Marlow <smarlow at redhat.com> wrote:
>>>>
>>>> On Tue, Jan 2, 2018 at 2:42 PM, Steve Ebersole <steve at hibernate.org>
>>>> wrote:
>>>>>
>>>>> Scott, how would we register a listener for this event?
>>>>
>>>>
>>>> If we want a standard solution, we could ask for an earlier CDI
>>>> pre-destroy listener.
>>>>
>>>>> The problem we have had with most CDI "listeners" so far is that they
>>>>> are non-contextual, meaning there has been no way to link that back to a
>>>>> specific SessionFactory..  If I can register this listener with a reference
>>>>> back to the Sessionfactory, this should actually be fine.
>>>>
>>>>
>>>> I could pass the EMF to the
>>>> org.hibernate.jpa.event.spi.jpa.ExtendedBeanManager.LifecycleListener, if
>>>> that helps.
>>>>
>>>>>
>>>>>
>>>>> On Tue, Jan 2, 2018 at 1:39 PM Scott Marlow <smarlow at redhat.com> wrote:
>>>>>>
>>>>>> On Wed, Dec 20, 2017 at 9:48 AM, Sanne Grinovero <sanne at hibernate.org>
>>>>>> wrote:
>>>>>>
>>>>>> > Any dependency injection framework will have some capability to
>>>>>> > define
>>>>>> > the graph of dependencies across components, and such graph could be
>>>>>> > very complex, with details only known to the framework.
>>>>>> >
>>>>>> > I don't think we can solve the integration by having "before all
>>>>>> > others" / "after all others" phases as that's too coarse grained to
>>>>>> > define a full graph; we need to find a way to have the DI framework
>>>>>> > take in consideration our additional components both in terms of DI
>>>>>> > consumers and providers - then let the framework wire up things in
>>>>>> > the
>>>>>> > order it prefers. This is also to allow the DI engine to print
>>>>>> > appropriate warnings for un-resolvable situations with its native
>>>>>> > error handling, which would resolve in more familiar error messages.
>>>>>> >
>>>>>> > If that's not doable *or a priority* then all we can do is try to
>>>>>> > make
>>>>>> > it clear enough that there will be limitations and hopefully describe
>>>>>> > these clearly. Some of such limitations might be puzzling as you
>>>>>> > describe.
>>>>>> >
>>>>>> >
>>>>>> >
>>>>>> > On 20 December 2017 at 12:50, Yoann Rodiere <yoann at hibernate.org>
>>>>>> > wrote:
>>>>>> > > Hello all,
>>>>>> > >
>>>>>> > > TL;DR: Application-scoped beans cannot be used as part of the
>>>>>> > > @PreDestroy
>>>>>> > > method of ORM-instantiated CDI beans, and it's a bit odd because
>>>>>> > > they can
>>>>>> > > be used as part of the @PostConstruct method.
>>>>>> > >
>>>>>> > > I've been testing the CDI integration in Hibernate ORM for the past
>>>>>> > > few
>>>>>> > > days, trying to integrate it into Search. I think I've discovered
>>>>>> > something
>>>>>> > > odd: when CDI-managed beans are destroyed, they cannot access other
>>>>>> > > Application-scoped CDI beans anymore. Not sure whether this is a
>>>>>> > > problem
>>>>>> > or
>>>>>> > > not, so maybe we should discuss it a bit before going forward with
>>>>>> > > the
>>>>>> > > current behavior.
>>>>>> > >
>>>>>> > > Short reminder: scopes define when CDI beans are created and
>>>>>> > > destroyed.
>>>>>> > > @ApplicationScoped is pretty self-explanatory: created when the
>>>>>> > application
>>>>>> > > starts and destroyed when it stops. Some other scopes are a bit
>>>>>> > > more
>>>>>> > > convoluted: @Singleton basically means created *before* the
>>>>>> > > application
>>>>>> > > starts and destroyed *after* the application stops (and also means
>>>>>> > > "this
>>>>>> > > bean shall not be proxied"), @Dependent means created when an
>>>>>> > > instance is
>>>>>> > > requested and destroyed when the instance is released, etc.
>>>>>> > >
>>>>>> > > The thing is, Hibernate ORM is typically started very early and
>>>>>> > > shut down
>>>>>> > > very late in the CDI lifecycle - at least within WildFly. So when
>>>>>> > Hibernate
>>>>>> > > starts, CDI Application-scoped beans haven't been instantiated yet,
>>>>>> > > and
>>>>>> > it
>>>>>> > > turns out that when Hibernate ORM shuts down, CDI has already
>>>>>> > > destroyed
>>>>>> > > Application-scoped beans.
>>>>>> > >
>>>>>> > > Regarding startup, Steve and Scott solved the problem by delaying
>>>>>> > > bean
>>>>>> > > instantiation to some point in the future when the Application
>>>>>> > > scope is
>>>>>> > > active (and thus Application-scoped beans are available). This
>>>>>> > > makes it
>>>>>> > > possible to use Application-scoped beans within ORM-instantiated
>>>>>> > > beans as
>>>>>> > > soon as the latter are constructed (i.e. within their
>>>>>> > > @PostConstruct
>>>>>> > > methods).
>>>>>> > > However, when Hibernate ORM shuts down, the Application scope has
>>>>>> > > already
>>>>>> > > been terminated. So when ORM destroys the beans it instantiated,
>>>>>> > > those
>>>>>> > > ORM-instantiated beans cannot call a method on referenced
>>>>>> > > Application-scoped beans (CDI proxies will throw an exception).
>>>>>> > >
>>>>>> > > All in all, the only type of beans we can currently use in a
>>>>>> > > @PreDestroy
>>>>>> > > method of an ORM-instantiated bean is @Dependent beans. @Singleton
>>>>>> > > beans
>>>>>> > > will work, but only because they are not proxied and thus you can
>>>>>> > > cheat
>>>>>> > and
>>>>>> > > use them even after they have been destroyed... which I definitely
>>>>>> > wouldn't
>>>>>> > > recommend.
>>>>>> > >
>>>>>> > > I see two ways to handle the issue:
>>>>>> > >
>>>>>> > >    1. We don't change anything, and simply document somewhere that
>>>>>> > > beans
>>>>>> > >    instantiated as part of the CDI integration are instantiated
>>>>>> > > within
>>>>>> > the
>>>>>> > >    Application scope, but are destroyed outside of it. And we
>>>>>> > > suggest
>>>>>> > that any
>>>>>> > >    bean used in @PostDestroy method in an ORM-instantiated bean
>>>>>> > (directly or
>>>>>> > >    not) must have either a @Dependent scope, or a @Singleton scope
>>>>>> > > and no
>>>>>> > >    @PostDestroy method.
>>>>>> > >    2. We implement an "early shut-down" somehow, which would bring
>>>>>> > forward
>>>>>> > >    bean destruction to some time when the Application scope is
>>>>>> > > still
>>>>>> > active.
>>>>>> >
>>>>>>
>>>>>> org.hibernate.jpa.event.spi.jpa.ExtendedBeanManager mentions that we
>>>>>> could
>>>>>> look at introducing a beanManagerDestroyed notification, if that is
>>>>>> useful
>>>>>> and we can find a way to implement it
>>>>>> (javax.enterprise.spi.BeforeShutdown
>>>>>> [1] is not early enough to meet your requirements).
>>>>>>
>>>>>> Scott
>>>>>>
>>>>>> [1]
>>>>>>
>>>>>> https://docs.oracle.com/javaee/7/api/javax/enterprise/inject/spi/BeforeShutdown.html
>>>>>>
>>>>>>
>>>>>> > >
>>>>>> > > #1 may be enough for now, even though the behavior feels a bit odd,
>>>>>> > > and
>>>>>> > > forces users to resort to less-than-ideal practices (using a
>>>>>> > > @Singleton
>>>>>> > > bean after it has been destroyed).
>>>>>> > >
>>>>>> > > #2 would require changes in WildFly and may be a bit complex. In
>>>>>> > > particular, if we aren't careful, Application-scoped beans may not
>>>>>> > > be
>>>>>> > able
>>>>>> > > to use Hibernate ORM from within their @PreDestroy methods... Which
>>>>>> > > is
>>>>>> > > probably not a good idea. So we would have to find a solution
>>>>>> > > together
>>>>>> > with
>>>>>> > > the WildFly team. Also to be considered: Hibernate Search would
>>>>>> > > have to
>>>>>> > be
>>>>>> > > shut down just before the "early shut-down" of Hibernate ORM
>>>>>> > > occurs,
>>>>>> > > because Hibernate Search cannot function at all without the beans
>>>>>> > > it
>>>>>> > > retrieves from the CDI context.
>>>>>> > >
>>>>>> > > Thoughts?
>>>>>> > >
>>>>>> > >
>>>>>> > > Yoann Rodière
>>>>>> > > Hibernate NoORM Team
>>>>>> > > yoann at hibernate.org
>>>>>> > > _______________________________________________
>>>>>> > > hibernate-dev mailing list
>>>>>> > > hibernate-dev at lists.jboss.org
>>>>>> > > https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>>>>> >
>>>>>> _______________________________________________
>>>>>> hibernate-dev mailing list
>>>>>> hibernate-dev at lists.jboss.org
>>>>>> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>>
>>>
>>



More information about the hibernate-dev mailing list