Imagine we have acme.jar. acme.jar provides a new TransactionFactory
to Hibernate for a new way to integrate with transactions. For
hopefully obvious reasons Hibernate jars/bundles cannot name acme.jar
as a import nor as a dependency (whatever the correct OSGi parlance is
there). So under normal circumstances, Hibernate would have no
knowledge of the ClassLoader that would allow access to acme.jar
resources. Therefore, "out of the box" discovery will not work here.
Further lets say that a user wants to make use of this Hibernate+acme
integration. So in order to build a
SessionFactory/EntityManagerFactory we would need to know about this
acme.jar supplied service.
So my last reply on this thread was about what needs to happen given
this situtation.
The first approach would be that acme.jar gets registered with
Hibernate as a service (however that happens). Meaning a call would be
made to
org.hibernate.boot.registry.selector.spi.StrategySelector#registerStrategyImplementor
based on the work I have done for this under HHH-7552. The problem
here is that this is not the service exposed by the Hibernate bundle; a
SessionFactory/EntityManagerFactory is. But in order to build a
SessionFactory/EntityManagerFactory we need the acme.jar
TransactionFactory service. This is the chicken-egg.
The other approach I saw was that Hibernate could be aware of the
acme.jar bundle through the ClassLoader(s) that get registered with its
ClassLoaderService. Then auto-discovery would work.
On Tue 28 Aug 2012 02:13:15 PM CDT, mailing(a)bibbernet.org wrote:
On 08/28/2012 02:39 PM, Steve Ebersole wrote:
> The problem there is timing. Hibernate already has to be started in
> order
> for "this" to work. But what "this" is doing is providing
things
> Hibernate
> needs to start. Its chicken-egg.
>
> Interestingly this is very similar to the proposal Scott Marlow and I
> made
> to the JPA group. And in fact that could be leveraged here.
> Essentially
> that proposal was to make JPA bootstrapping a 2-phase process rather
> than
> just a single "build it" phase. Here however that would mean (iiuc, and
> please correct me if I do not) Hibernate needing 2 OSGi services.
> One that
> builds the BootstrapServiceRegistry and MetadataSources/Configuration
> and
> then another that builds the SessionFactory/EntityManagerFactory.
> The type
> of things you discuss here would depends on the first service but
> somehow
> need to be ordered before the second Hibernate service.
I have seen (and developed) many services which use a kind of
iterative process. If they discover a service A which is interesting
for them and realize they need another service B which is not yet
available, they put the service A on hold (whatever on hold means),
until a bundle, which announce service B is available (or they wait
forever if no bundle ever announces a service B) and then continue
with the handling of service A.
This could be implemented with the help of
ServiceTracker,ServiceListener and/or BundleListener (and other
standard osgi classes and interfaces)
I normally implement it in the following way:
The BundleActivator implements the ServiceListener and or
BundleListener and reacts on Service-Events(modified properties,
service registered, service unregistered) or Bundle-Events (bundle
installed, uninstalled, resolved, unresolved, starting, stopping,
etc.). This could be used to initiate a scan of the bundle for
resources, register/unregister interesting services, etc.
So hibernate in the osgi framework could do a multi step bootstrap like:
- On Bundle start (when the BundleActivator gets called), register
Bundle- , ServiceListeners and ServiceTrackers to get hold on
modifications which occur from now on (and track the services and/or
bundles of interest if events got passed to the listeners).
- Next step would be to look if there are already interesting services
(and bundles) which got activated before the hibernate bundle got
activated (and add them to the list of tracked bundles and/or service
if they are not already tracked ).
From now on, you could then react on life-cycle changes for bundles
and services and modify the internal registries accordingly ( or do
some other meaningful things with the information)
this means you have two phases:
- Initialisation and discovery of bundles and service which are
already present.
- Dynamic life cycle which react on bundle and service changes.
> Of course assuming we even want to go that route in Hibernate
> source. The
> other option is the OSGi container adding that bundle to the
> ClassLoader it
> passes Hibernate so Hibernate can do the auto-discovery. Maybe I am
> missing some options?
Please correct me, but if you have a Bundle (or ServiceReference which
could be used to get the implementing Bundle) you can use the bundle
to load classes and resources which are contained in the bundle (yes I
know there are also Permissions in OSGI, but you can grant the
hibernate bundle(s) the appropriate permissions to be allowed to load
classes in that way - but the permission system is another issue which
shouldn't cause problems here)
--
steve(a)hibernate.org
http://hibernate.org