Hibernate.orgCommunity Documentation
Abstract
The Open Services Gateway initiative (OSGi) specification describes a dynamic, modularized system. "Bundles" (components) can be installed, activated, deactivated, and uninstalled during runtime, without requiring a system restart. OSGi frameworks manage bundles' dependencies, packages, and classes. The framework is also in charge of ClassLoading, managing visibility of packages between bundles. Further, service registry and discovery is provided through a "whiteboard" pattern.
OSGi environments present numerous, unique challenges. Most notably, the dynamic nature of available bundles during runtime can require significant architectural considerations. Also, architectures must allow the OSGi-specific ClassLoading and service registration/discovery.
Table of Contents
Hibernate targets the OSGi 4.3 spec or later. It was necessary to start with 4.3, over 4.2, due to our
dependency on OSGi's BundleWiring
for entity/mapping scanning.
Hibernate supports three types of configurations within OSGi.
Rather than embed OSGi capabilities into hibernate-core, hibernate-entitymanager, and sub-modules, hibernate-osgi was created. It's purposefully separated, isolating all OSGi dependencies. It provides an OSGi-specific ClassLoader (aggregates the container's CL with core and entitymanager CLs), JPA persistence provider, SF/EMF bootstrapping, entities/mappings scanner, and service management.
The Enterprise OSGi specification includes container-managed JPA. The container is responsible for
discovering persistence units and creating the EntityManagerFactory
(one EMF per PU).
It uses the JPA provider (hibernate-osgi) that has registered itself with the OSGi
PersistenceProvider
service.
Quickstart tutorial project, demonstrating a container-managed JPA client bundle: managed-jpa
Your client bundle's manifest will need to import, at a minimum,
javax.persistence
org.hibernate.proxy
and javassist.util.proxy
, due to
Hibernate's ability to return proxies for lazy initialization (Javassist enhancement
occurs on the entity's ClassLoader during runtime).
No Enterprise OSGi JPA container currently supports JPA 2.1 (the spec is not yet released). For testing, the managed-jpa example makes use of Brett's fork of Aries. To work with Hibernate 4.3, clone the fork and build Aries JPA.
Typical Enterprise OSGi JPA usage includes a DataSource installed in the container. The client
bundle's persistence.xml
uses the DataSource through JNDI. For an example,
see the QuickStart's DataSource:
datasource-h2.xml
The DataSource is then called out in
persistence.xml's jta-data-source
.
Hibernate currently requires fairly specific bundle activation ordering. See the managed-jpa QuickStart's features.xml for the best supported sequence.
The easiest, and most supported, method of obtaining an EntityManager
utilizes OSGi's
blueprint.xml
. The container takes the name of your persistence unit, then injects
an EntityManager
instance into your given bean attribute. See the
dpService
bean in the managed-jpa QuickStart's
blueprint.xml
for an example.
Hibernate also supports the use of JPA through hibernate-entitymanager, unmanaged by the OSGi container. The client bundle is responsible for managing the EntityManagerFactory and EntityManagers.
Quickstart tutorial project, demonstrating an unmanaged JPA client bundle: unmanaged-jpa
Your client bundle's manifest will need to import, at a minimum,
javax.persistence
org.hibernate.proxy
and javassist.util.proxy
, due to
Hibernate's ability to return proxies for lazy initialization (Javassist enhancement
occurs on the entity's ClassLoader during runtime)
JDBC driver package (example: org.h2
)
org.osgi.framework
, necessary to discover the EMF (described below)
Hibernate currently requires fairly specific bundle activation ordering. See the unmanaged-jpa QuickStart's features.xml for the best supported sequence.
hibernate-osgi registers an OSGi service, using the JPA PersistenceProvider
interface
name, that bootstraps and creates an EntityManagerFactory
specific for OSGi
environments. It is VITAL that your EMF be obtained through the service, rather than creating it
manually. The service handles the OSGi ClassLoader, discovered extension points, scanning, etc. Manually
creating an EntityManagerFactory
is guaranteed to NOT work during runtime!
For an example on how to discover and use the service, see the unmanaged-jpa QuickStart's HibernateUtil.java.
Native Hibernate use is also supported. The client bundle is responsible for managing the SessionFactory and Sessions.
Quickstart tutorial project, demonstrating an unmanaged native client bundle: unmanaged-native
Your client bundle's manifest will need to import, at a minimum,
javax.persistence
org.hibernate.proxy
and javassist.util.proxy
, due to
Hibernate's ability to return proxies for lazy initialization (Javassist enhancement
occurs on the entity's ClassLoader during runtime)
JDBC driver package (example: org.h2
)
org.osgi.framework
, necessary to discover the SF (described below)
org.hibernate.*
packages, as necessary (ex: cfg, criterion, service, etc.)
Hibernate currently requires fairly specific bundle activation ordering. See the unmanaged-native QuickStart's features.xml for the best supported sequence.
hibernate-osgi registers an OSGi service, using the SessionFactory
interface
name, that bootstraps and creates an SessionFactory
specific for OSGi
environments. It is VITAL that your SF be obtained through the service, rather than creating it
manually. The service handles the OSGi ClassLoader, discovered extension points, scanning, etc. Manually
creating an SessionFactory
is guaranteed to NOT work during runtime!
For an example on how to discover and use the service, see the unmanaged-native QuickStart's HibernateUtil.java.
The unmanaged-native QuickStart project demonstrates the use of optional Hibernate modules. Each module adds additional dependency bundles that must first be activated (see features.xml). As of ORM 4.2, Envers is fully supported. Support for C3P0, Proxool, EhCache, and Infinispan were added in 4.3, however none of their 3rd party libraries currently work in OSGi (lots of ClassLoader problems, etc.). We're tracking the issues in JIRA.
Multiple contracts exist to allow applications to integrate with and extend Hibernate capabilities. Most apps utilize JDK services to provide their implementations. hibernate-osgi supports the same extensions through OSGi services. Implement and register them in any of the three configurations. hibernate-osgi will discover and integrate them during EMF/SF bootstrapping. Supported extension points are as follows. The specified interface should be used during service registration.
org.hibernate.integrator.spi.Integrator
(as of 4.2)
org.hibernate.boot.registry.selector.StrategyRegistrationProvider
(as of 4.3)
org.hibernate.metamodel.spi.TypeContributor
(as of 4.3)
javax.transaction.TransactionManager
and
javax.transaction.UserTransaction
(as of 4.2), however these are typically
provided by the OSGi container.
The easiest way to register extension point implementations is through a blueprint.xml
file. Add OSGI-INF/blueprint/blueprint.xml
to your classpath. Envers' blueprint
is a great example:
Example 17.1. Example extension point registrations in blueprint.xml
<blueprint default-activation="eager" xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <bean id="integrator" class="org.hibernate.envers.event.spi.EnversIntegrator" /> <service ref="integrator" interface="org.hibernate.integrator.spi.Integrator" /> <bean id="typeContributor" class="org.hibernate.envers.internal.entities.TypeContributorImpl" /> <service ref="typeContributor" interface="org.hibernate.metamodel.spi.TypeContributor" /> </blueprint>
Extension points can also be registered programmatically with
BundleContext#registerService
, typically within your
BundleActivator#start
.
Technically, multiple persistence units are supported by Enterprise OSGi JPA and unmanaged Hibernate JPA use. However, we cannot currently support this in OSGi. In Hibernate 4, only one instance of the OSGi-specific ClassLoader is used per Hibernate bundle, mainly due to heavy use of static TCCL utilities. We hope to support one OSGi ClassLoader per persistence unit in Hibernate 5.
Scanning is supported to find non-explicitly listed entities and mappings. However, they MUST be in the same bundle as your persistence unit (fairly typical anyway). Our OSGi ClassLoader only considers the "requesting bundle" (hence the requirement on using services to create EMF/SF), rather than attempting to scan all available bundles. This is primarily for versioning considerations, collision protections, etc.
Some containers (ex: Aries) always return true for
PersistenceUnitInfo#excludeUnlistedClasses
,
even if your persistence.xml explicitly has exclude-unlisted-classes
set
to false
. They claim it's to protect JPA providers from having to implement
scanning ("we handle it for you"), even though we still want to support it in many cases. The work
around is to set hibernate.archive.autodetection
to, for example,
hbm,class
. This tells hibernate to ignore the excludeUnlistedClasses value and
scan for *.hbm.xml
and entities regardless.
Scanning does not currently support annotated packages on package-info.java
.
Currently, Hibernate OSGi is primarily tested using Apache Karaf and Apache Aries JPA. Additional testing is needed with Equinox, Gemini, and other container providers.
Hibernate ORM has many dependencies that do not currently provide OSGi manifests.
The QuickStart tutorials make heavy use of 3rd party bundles (SpringSource, ServiceMix) or the
wrap:...
operator.
As previously mentioned, bundle activation is currently order specific. See the QuickStart
tutorials' features.xml
for example sequences.
No Enterprise OSGi JPA container currently supports JPA 2.1 (the spec is not yet released). For testing, the managed-jpa example makes use of Brett's fork of Aries. To work with Hibernate 4.3, clone the fork and build Aries JPA.