One outcome of the missing standardized modularization concept in the java platform is the need to deal with incompatible release distributions for infrastructure libraries, used in our everyday project life.
An infamous and illustrative example for the resulting mess is the combination of the O/R-mapping framework Hibernate and SpringDM (today aka Eclipse Gemini).
Hibernate is widely used because of many reasons like licensing, availability, supported features set, implementation quality, support and much more. Same goes to usage of Spring Beans and SpringDM. Hibernate also supports the actual Java standard persistence API (JPA 2) with higher versions than 3.6.
The problem starts if you try to combine all of that, to create a good old “best of breed solution” – the enterprise Java platform was so famous for (at least within the last decade).
The architectural foundation of SpringDM is the OSGi-Specification which is basically defining modules as OSGi-bundles. The Hibernate project does not support the OSGi-bundle concept neither by offering compliant binary distributions nor by offering an easy way to build those from the sources.
The intended solution of the SpringDM-team was the SpringSource Enterprise Bundle Repository (EBR), where the guys from VMWare (formly know as Springsource) provide the solution as simple binary download that solves all the more or less tricky details.
Unfortunately the EBR only offers Hibernate bundles for version 3.4 or 4.0CR which are not viable options for customers seeking production stable JPA2 releases.
As a matter of fact, we actually have four very good solutions (JPA, Hibernate, Spring, OSGi) that are not able to run together out of the box.
All that could be (hopefully) solved if the Java platform would have a standartized module concept.
To make things worse, in fact there is nobody of the providers (VMware, Red Hat, Oracle, OSGi-Foundation) to blame for the mess. They are all doing a very good job, but it seems not to be enough for todays project requirements. What we have here is a major cross-cutting-concern that cannot be solved single sided.
There are many solutions and advices for that problem to find in world wide web (at least I was able to spend a lot of time reading them). Most of them focus on omitting or substituting at least one requirement (e.g. don´t use OSGi so you don´t need bundles or use eclipselink instead of hibernate because they provide JPA2 in bundles), others are talking about solutions without actually showing any running code.
After a long and time consuming search I found a description how to repackage hibernate as a OSGi bundle here. It did not work out of the box, but it was relatively easy to fix some typos and change or add missing OSGi-dependency declarations.
So, to the point, here are simple instructions to follow, and you will build an Hibernate 3.6.8 OSGI Bundle:
- download and unpack the Release Distribution Bundle (e.g. hibernate-distribution-3.6.8.Final-dist.zip ) from here…
- don´t use Maven Artefacts because their packaging is not OSGi compliant!
- install Bundlor…
- repackage the hibernate artefacts within the “Release Distribution” as OSGi Bundles, more details follow…
Repackaging the artefacts consists of two steps (4.1 and 4.2 for consistency)
4.1. repackage hibernate3.jar
Use the following command line:
bundlor.bat -i hibernate3.jar -o ./org.hibernate-3.6.8.Final.jar -m template-hibernate3.mf
The content of the template-hibernate3.mf file for the hibernate3.jar
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: JBoss Hibernate Object-Relational Mapper Built-By: OIO Bundle-Vendor: Orientation In Objetcs GmbH Implementation-Vendor-Id: org.hibernate Bundle-SymbolicName: org.hibernate Bundle-Version: 3.6.8.Final Eclipse-BuddyPolicy: registered Excluded-Exports: *.internal* Import-Template: antlr*;version="[2.7.6,3)", com.ibm.*;resolution:=optional, javassist.*;version="[3.12.0,4.0.0)", javax.naming*, javax.persistence*;version="[2,2.1)",javax.security.auth*, java.sql*, javax.transaction*;resolution:=optional;version="[1.1,2)", javax.xml*, net.sf.cglib*;version="[2.2,3]", org.slf4j*;version="[1.6.1,2.0)", org.dom4j*;version="[1.6.1,2)", org.apache.commons.collections*;version="[3.1,4)", org.w3c.dom*, org.xml.sax*, *;resolution:=optional Export-Template: org.hibernate.*;version=3.6.8 Unversioned-Imports: *
4.2. repackage hibernate-jpa-2.0-api-1.0.0.Final.jar
Now repackage the hibernate-jpa api jar with the following command line:
bundlor.bat -i ./lib/jpa/hibernate-jpa-2.0-api-1.0.0.Final.jar -o ./javax.persistence2-1.0.0.Final.jar -m template-hibernate-jpa.mf
Again, the required content of the template-hibernate-jpa.mf for the hibernate-jpa-2.0-api-1.0.0.Final.jar is as follows:
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: JBoss Hibernate JPA 2 API Built-By: OIO Bundle-Vendor: Orientation in Objetcs GmbH Implementation-Vendor-Id: org.hibernate Bundle-SymbolicName: org.hibernate.jpa Bundle-Version: 2.0.0 Eclipse-BuddyPolicy: registered Excluded-Exports: *.internal* Import-Template: * Export-Template: javax.persistence.*;version=2.0.0 Unversioned-Imports: *
You created a working hibernate OSGI-bundle that supports JPA2-annotations based on the actual hibernate 3.6.8 version.
Just for the record: when it comes to modularity in java, I still feel my self in Dante Alighieries “Divine Comedy – Welcome to the fourth ring of the hell!”