We have a number of resources whose references are valid only during
bootstrap. This includes things like:
- JPA temp ClassLoader
- Scanner and related
- HCANN ReflectionManager (eventually Jandex)
The problem is that as currently handled (via
MetadataBuilder/MetadataBuildingOptions) these resources actually are
available at runtime as well, since the MetadataBuildingOptions lives on as
part of the SessionFactory.
The idea of a "bootstrap only" ServiceRegistry has been discussed a few
times as a way to solve this. That would work, except that it would
potentially get confusing in regards to being sure we are passing the
correct ServiceRegistry all the time IMO.
Lately I started thinking of an alternative solution: splitting up
into 2 distinct contracts: one with the same idea/scope as now, and another
whose lifecycle is scoped to the bootstrap process. I am tentatively
calling this org.hibernate.boot.spi.BootstrapContext.
For the most part these changes are isolated internally. Currently I
building both the MetadataBuildingOptions and this new BootstrapContext.
Some of the applyXYZ calls on MetadataBuilder are now directed to
BootstrapContext instead of the MetadataBuildingOptions.
MetadaBuildingContext was changed to add exposing the BootstrapContext in
addition to the MetadataBuildingOptions. For the most part this works very
well, and like I said is pretty well isolated internally. However, it does
affect any existing usages of those methods removed
from MetadataBuildingOptions. The biggest disconnect there so far is in
JpaIntegrator which tries to access the HCANN ReflectionManager during its
JpaIntegrator#integrate call to process entity callbacks/listeners. With
JPA support being integrated into hibernate-core, we could probably work
around that one by consuming that bit-of-logic into the transformation of
InFlightMetadataCollector -> MetadataImpl. IMO this is a "win" anyway as
it would allow users to leverage JPA entity callbacks/listeners in native
Hibernate apps as well; so this change would not necessarily be a "bad
thing". Another option would be to change the signature of
Integrator#integrate. To be honest it was probably always a mistake to not
use a "parameter object" to pass in to #integrate.
This also has a tie-in with the 3-phases for TypeConfiguration discussed on
HipChat. To recap, TypeConfiguration (see 6.0 type system design if
unfamiliar with TypeConfiguration) has the following "phases":
1. TypeConfiguration initialization - this is initialization of the
TypeConfiguration itself. During this phase no "context" is available to
2. Metadata building - essentially this is the time spent transitioning
from MetadataSources to Metadata.
3. live SessionFactory - from the point we instantiate the
The first discussion here is exactly how to handle the period from the end
of phase 2 to the beginning of phase 3. Ideally (from an OO encapsulation
perspective) we'd end the second phase after we have built the MetadataImpl
from the InFlight variety. However that leaves a "gap" in terms of the
TypeConfiguration having any context. The other option is to carry the
BootstrapContext along into the MetadataImpl, along into the
SessionFactoryBuilder and to release the BootstrapContext and scope the
TypeConfiguration to the SessionFactory only after the SF is built. So
we'd still not carry that information in the SessionFactory, but we'd keep
it around until the SessionFactory is built. Basically this allows types
and descriptors access to the scoped context (MetadataBuildingContext here
specifically) during that small gap of transitioning from Metadata -> SF.
This is what I propose we do; just want to make sure no one has objections.
A last part I want to consider is integrations with other Hibernate
projects. Initially I spoke with Gunnar about this a lot in terms of OGM.
I think it is important that we allow the same paradigm we do now for
bootstrapping for the sake of continuity. However I do wonder if, in terms
of integrations, it might also be beneficial to allow an alternate way to
bootstrap as well. Gunnar, back when we developed this you had mentioned a
central "bootstrap delegate builder" contract. That also could fit really
nicely with these new changes. Is that something that would help OGM at
this point? Or should we stick with what we have for the sake of
Sorry this got so long, but there is a lot of discuss here :)