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

Sanne Grinovero sanne at hibernate.org
Wed Dec 20 10:20:09 EST 2017

On 20 December 2017 at 15:08, Yoann Rodiere <yoann at hibernate.org> wrote:
>> 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
> Not sure what you mean by that. Currently the DI framework doesn't know who
> uses these components, and therefore it's up to us to tell the DI framework
> when they can be "destroyed".
> Do you suggest that we make the DI framework aware of the Hibernate ORM =>
> <some beans> dependency, and let it do what it can to handle that
> dependency?


> I know this would work (and probably is already doable without much change)
> in Spring, because in Spring DI the EntityManagerFactory is viewed as just
> another type of bean, and therefore its whole lifecycle is already handled
> by Spring DI.
> In WildFly though, things are a little bit different: from what I
> understood, WildFly starts the persistence units (Hibernate ORM) explicitly,
> and only then it starts the CDI context (Weld). And the opposite when
> shutting down. The persistence units lifecycle really isn't integrated into
> CDI... But maybe it should be. In particular the ability to lazily load the
> persistence units when they are first requested by a CDI bean, and to
> automatically close a persistence unit when no CDI bean depends on it
> anymore, would solve a lot of dependency issues. Or at least it would move
> the problems out of our scope.
> However, I'm not sure that such behavior would be compatible with all the
> specs WildFly must comply with.

If WildFly does it like that there are consequences that I don't think
we should try to work around; as I said before having a "global"
before/after phase is not granular enough to be able to define a full
graph. If we go for the workaround - there will have to be limitations
to what we can do.

So either we - and our users - will have to live with such limitations
or we (eventually) figure out how to do the better integration.

> Yoann Rodière
> Hibernate NoORM Team
> yoann at hibernate.org
> On 20 December 2017 at 15:48, 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.
>> >
>> > #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

More information about the hibernate-dev mailing list