HHH-8112 osgi devguide

This commit is contained in:
Brett Meyer 2013-05-21 18:03:37 -04:00 committed by Brett Meyer
parent af5e8c3869
commit ab11440331
4 changed files with 420 additions and 0 deletions

View File

@ -50,6 +50,12 @@
<surname>Badner</surname>
</personname>
</author>
<author>
<personname>
<firstname>Brett</firstname>
<surname>Meyer</surname>
</personname>
</author>
<othercredit>
<personname>

View File

@ -52,6 +52,7 @@
<xi:include href="JMX.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="Envers.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="chapters/multitenancy/Multi_Tenancy.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="chapters/osgi/OSGi.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="appendix-Configuration_Properties.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="appendices/legacy_criteria/Legacy_Criteria.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
</book>

View File

@ -0,0 +1,402 @@
<?xml version='1.0' encoding='utf-8'?>
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xl="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<info>
<title>OSGi</title>
<abstract>
<para>
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.
</para>
<para>
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.
</para>
</abstract>
</info>
<section>
<title>OSGi Specification and Environment</title>
<para>
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 <literal>BundleWiring</literal> for entity/mapping scanning.
</para>
<para>
Hibernate supports three types of configurations within OSGi.
<orderedlist>
<listitem>
<firstterm>Container-Managed JPA</firstterm>: <xref linkend="osgi-managed-jpa"/>
</listitem>
<listitem>
<firstterm>Unmanaged JPA</firstterm>: <xref linkend="osgi-unmanaged-jpa"/>
</listitem>
<listitem>
<firstterm>Unmanaged Native</firstterm>: <xref linkend="osgi-unmanaged-native"/>
</listitem>
</orderedlist>
</para>
</section>
<section>
<title>hibernate-osgi</title>
<para>
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.
</para>
</section>
<section xml:id="osgi-managed-jpa">
<title>Container-Managed JPA</title>
<para>
The Enterprise OSGi specification includes container-managed JPA. The container is responsible for
discovering persistence units and creating the <literal>EntityManagerFactory</literal> (one EMF per PU).
It uses the JPA provider (hibernate-osgi) that has registered itself with the OSGi
<literal>PersistenceProvider</literal> service.
</para>
<para>
Quickstart tutorial project, demonstrating a container-managed JPA client bundle:
<link xl:href="https://github.com/hibernate/hibernate-orm/tree/master/documentation/src/main/docbook/quickstart/tutorials/osgi/managed-jpa">managed-jpa</link>
</para>
<section>
<title>Client bundle imports</title>
<para>
Your client bundle's manifest will need to import, at a minimum,
<itemizedlist>
<listitem>
<literal>javax.persistence</literal>
</listitem>
<listitem>
<para>
<literal>org.hibernate.proxy</literal> and <literal>javassist.util.proxy</literal>, due to
Hibernate's ability to return proxies for lazy initialization
</para>
</listitem>
</itemizedlist>
</para>
</section>
<section>
<title>JPA 2.1</title>
<para>
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
<link xl:href="https://github.com/brmeyer/aries/tree/jpa21">Brett's fork of Aries</link>. To work
with Hibernate 4.3, clone the fork and build Aries JPA.
</para>
</section>
<section>
<title>DataSource</title>
<para>
Typical Enterprise OSGi JPA usage includes a DataSource installed in the container. The client
bundle's <literal>persistence.xml</literal> uses the DataSource through JNDI. For an example,
see the QuickStart's DataSource:
<link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/datasource-h2.xml">datasource-h2.xml</link>
The DataSource is then called out in
<link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/managed-jpa/src/main/resources/META-INF/persistence.xml">
persistence.xml's</link> <literal>jta-data-source</literal>.
</para>
</section>
<section>
<title>Bundle Ordering</title>
<para>
Hibernate currently requires fairly specific bundle activation ordering. See the managed-jpa
QuickStart's
<link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/managed-jpa/features.xml">features.xml</link>
for the best supported sequence.
</para>
</section>
<section>
<title>Obtaining an EntityManger</title>
<para>
The easiest, and most supported, method of obtaining an <literal>EntityManager</literal> utilizes OSGi's
<literal>blueprint.xml</literal>. The container takes the name of your persistence unit, then injects
an <literal>EntityManager</literal> instance into your given bean attribute. See the
<literal>dpService</literal> bean in the managed-jpa QuickStart's
<link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/managed-jpa/src/main/resources/OSGI-INF/blueprint/blueprint.xml">blueprint.xml</link>
for an example.
</para>
</section>
</section>
<section xml:id="osgi-unmanaged-jpa">
<title>Unmanaged JPA</title>
<para>
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.
</para>
<para>
Quickstart tutorial project, demonstrating an unmanaged JPA client bundle:
<link xl:href="https://github.com/hibernate/hibernate-orm/tree/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-jpa">unmanaged-jpa</link>
</para>
<section>
<title>Client bundle imports</title>
<para>
Your client bundle's manifest will need to import, at a minimum,
<itemizedlist>
<listitem>
<literal>javax.persistence</literal>
</listitem>
<listitem>
<para>
<literal>org.hibernate.proxy</literal> and <literal>javassist.util.proxy</literal>, due to
Hibernate's ability to return proxies for lazy initialization
</para>
</listitem>
<listitem>
<para>
JDBC driver package (example: <literal>org.h2</literal>)
</para>
</listitem>
<listitem>
<para>
<literal>org.osgi.framework</literal>, necessary to discover the EMF (described below)
</para>
</listitem>
</itemizedlist>
</para>
</section>
<section>
<title>Bundle Ordering</title>
<para>
Hibernate currently requires fairly specific bundle activation ordering. See the unmanaged-jpa
QuickStart's
<link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-jpa/features.xml">features.xml</link>
for the best supported sequence.
</para>
</section>
<section>
<title>Obtaining an EntityMangerFactory</title>
<para>
hibernate-osgi registers an OSGi service, using the JPA <literal>PersistenceProvider</literal> interface
name, that bootstraps and creates an <literal>EntityManagerFactory</literal> 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 <literal>EntityManagerFactory</literal> is guaranteed to NOT work during runtime!
</para>
<para>
For an example on how to discover and use the service, see the unmanaged-jpa
QuickStart's
<link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-jpa/src/main/java/org/hibernate/osgitest/HibernateUtil.java">HibernateUtil.java</link>.
</para>
</section>
</section>
<section xml:id="osgi-unmanaged-native">
<title>Unmanaged Native</title>
<para>
Native Hibernate use is also supported. The client bundle is responsible for managing the
SessionFactory and Sessions.
</para>
<para>
Quickstart tutorial project, demonstrating an unmanaged native client bundle:
<link xl:href="https://github.com/hibernate/hibernate-orm/tree/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-native">unmanaged-native</link>
</para>
<section>
<title>Client bundle imports</title>
<para>
Your client bundle's manifest will need to import, at a minimum,
<itemizedlist>
<listitem>
<literal>javax.persistence</literal>
</listitem>
<listitem>
<para>
<literal>org.hibernate.proxy</literal> and <literal>javassist.util.proxy</literal>, due to
Hibernate's ability to return proxies for lazy initialization
</para>
</listitem>
<listitem>
<para>
JDBC driver package (example: <literal>org.h2</literal>)
</para>
</listitem>
<listitem>
<para>
<literal>org.osgi.framework</literal>, necessary to discover the SF (described below)
</para>
</listitem>
<listitem>
<para>
<literal>org.hibernate.*</literal> packages, as necessary (ex: cfg, criterion, service, etc.)
</para>
</listitem>
</itemizedlist>
</para>
</section>
<section>
<title>Bundle Ordering</title>
<para>
Hibernate currently requires fairly specific bundle activation ordering. See the unmanaged-native
QuickStart's
<link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-native/features.xml">features.xml</link>
for the best supported sequence.
</para>
</section>
<section>
<title>Obtaining an SessionFactory</title>
<para>
hibernate-osgi registers an OSGi service, using the <literal>SessionFactory</literal> interface
name, that bootstraps and creates an <literal>SessionFactory</literal> 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 <literal>SessionFactory</literal> is guaranteed to NOT work during runtime!
</para>
<para>
For an example on how to discover and use the service, see the unmanaged-native
QuickStart's
<link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-native/src/main/java/org/hibernate/osgitest/HibernateUtil.java">HibernateUtil.java</link>.
</para>
</section>
</section>
<section>
<title>Optional Modules</title>
<para>
The <link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-native">unmanaged-native</link>
QuickStart project demonstrates the use of optional Hibernate modules. Each module adds additional
dependency bundles that must first be activated
(see <link xl:href="https://github.com/hibernate/hibernate-orm/blob/master/documentation/src/main/docbook/quickstart/tutorials/osgi/unmanaged-native/features.xml">features.xml</link>).
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.
</para>
</section>
<section>
<title>Extension Points</title>
<para>
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.
<itemizedlist>
<listitem>
<literal>org.hibernate.integrator.spi.Integrator</literal> (as of 4.2)
</listitem>
<listitem>
<literal>org.hibernate.boot.registry.selector.StrategyRegistrationProvider</literal> (as of 4.3)
</listitem>
<listitem>
<literal>org.hibernate.metamodel.spi.TypeContributor</literal> (as of 4.3)
</listitem>
<listitem>
JTA's <literal>javax.transaction.TransactionManager</literal> and
<literal>javax.transaction.UserTransaction</literal> (as of 4.2), however these are typically
provided by the OSGi container.
</listitem>
</itemizedlist>
</para>
<para>
The easiest way to register extension point implementations is through a <literal>blueprint.xml</literal>
file. Add <literal>OSGI-INF/blueprint/blueprint.xml</literal> to your classpath. Envers' blueprint
is a great example:
</para>
<example>
<title>Example extension point registrations in blueprint.xml</title>
<programlisting role="XML"><xi:include href="extras/extension_point_blueprint.xml" parse="text"/></programlisting>
</example>
<para>
Extension points can also be registered programmatically with
<literal>BundleContext#registerService</literal>, typically within your
<literal>BundleActivator#start</literal>.
</para>
</section>
<section>
<title>Caveats</title>
<itemizedlist>
<listitem>
<para>
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.
</para>
</listitem>
<listitem>
<para>
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.
</para>
</listitem>
<listitem>
<para>
Currently, Hibernate OSGi is primarily tested using Apache Karaf and Apache Aries JPA. Additional
testing is needed with Equinox, Gemini, and other container providers.
</para>
</listitem>
<listitem>
<para>
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
<literal>wrap:...</literal> operator.
</para>
</listitem>
<listitem>
<para>
As previously mentioned, bundle activation is currently order specific. See the QuickStart
tutorials' <literal>features.xml</literal> for example sequences.
</para>
</listitem>
<listitem>
<para>
The environment should be considered STATIC. Hibernate currently does not support the ability
to dynamically add and remove client bundles during runtime. Doing so is typically
catastrophic. We hope to better support at least partially-dynamic environments in
Hibernate 5.
</para>
</listitem>
<listitem>
<para>
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
<link xl:href="https://github.com/brmeyer/aries/tree/jpa21">Brett's fork of Aries</link>. To work
with Hibernate 4.3, clone the fork and build Aries JPA.
</para>
</listitem>
</itemizedlist>
</section>
</chapter>

View File

@ -0,0 +1,11 @@
<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>