Dans le cadre d’un projet j’avais besoin de mettre en place un bundle OSGI (implémentation EQUINOX) qui utilise JPA / Hibernate.

Les versions de départs sont les suivantes :

  • OSGI Equinox org.eclipse.osgi_3.5.2
  • Hibernate : hibernate-4.2.6.Final
  • Hibernate envers : hibernate-envers-4.2.6.Final

Ici : l’utilisation hibernate-envers n’est pas obligatoire

Lorsque vous voulez mettre en place Hibernate dans un bundle vous avez plusieurs possibilités :

  • Container-Managed JPA
  • Unmanaged JPA
  • Unmanaged Native

(cf doc hibernate)

Pour mon cas j’ai utilisé la solution du « Unmanaged JPA », pas besoin d’ajouter la couche « blueprint » pour l’instant.

Il y a des modifications à apporter au niveau du code (pour le chargement de entitymanager) ainsi qu’au niveau du MANIFEST.MF de votre bundle.

Pour le MANIFEST.MF il faut ajouter les Import-Package nécéssaire et le chemin dans le Meta-Persistence :
[sourcecode language= »plain » title= »Fichier META-INF/MANIFEST.MF »]…
Export-Package: …
Import-Package: …
Meta-Persistence: META-INF/persistence.xml
[/sourcecode]

Voici le code pour pouvoir créer l’EntityManager dans le contexte d’un bundle OSGI. (Exemple de code issue de la doc d’hibernate).

[java title= »Fichier Registry.java »] package fr.mydevworld.webapp.util;

import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceProvider;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;

public class Registry {

private static Registry instance;

public static Registry getInstance(){
if(instance == null ) instance = new Registry();
return instance;
}

private EntityManagerFactory emf;

private Registry() {
if ( this.emf == null ) {
Bundle thisBundle = FrameworkUtil.getBundle( Registry.class );
// Could get this by wiring up OsgiTestBundleActivator as well.
BundleContext context = thisBundle.getBundleContext();

ServiceReference serviceReference = context.getServiceReference( PersistenceProvider.class.getName() );
PersistenceProvider persistenceProvider = (PersistenceProvider) context.getService( serviceReference );
this.emf = persistenceProvider.createEntityManagerFactory( "mydevworld", null );
}
}

public EntityManagerFactory getEmf() {
return emf;
}
}
[/java]

Dans le constructeur du Registry on récupère le contexte du bundle courant pour pouvoir récupérer les services enregistrés de type « javax.persistence.spi.PersistenceProvider ». Une fois le service récupérer on va pouvoir créer notre entityManager définit dans le fichier META-INF/persistence.xml de notre bundle (voilà pour l’explication du code).

La problématique que j’ai rencontré suite à la modification du code est que la version d’hibernate que j’utilisais n’était plus compatible (packages manquants). J’ai du faire une monté de version d’hibernate 4.2.6.Final -> 4.3.0.Final.

La monté en version d’hibernate ma obligé à faire ma monté de version d’Equinox de 3.5.2 -> 3.8.2.

Une fois qu’on à résolu toutes les dépendances on obtient les versions principales suivantes :

  • OSGI Equinox org.eclipse.osgi_3.8.2
  • Hibernate : hibernate-4.3.0.Final
  • Hibernate OSGI: hibernate-osgi-4.3.0.Final
  • Hibernate envers : hibernate-envers-4.3.0.Final

Et l’on peut relancer notre bundle.
Attention : si vous avez un NullPointException au niveau de la résolution des services de référence dans votre registry. C’est que vous avez oublié de démarrer le bundle Hibernate-OSGI. En effet c’est lui qui est en charge d’enregistrer les services de type « javax.persistence.spi.PersistenceProvider ».

Donc démarrer ce bundle (hibernate-osgi) avant le votre.

Après avoir redémarrer dans le bon ordre les bundles, j’ai rencontré l’erreur suivante :


java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Lorg.hibernate.integrator.spi.Integrator;
at org.hibernate.osgi.OsgiPersistenceProvider.generateSettings(OsgiPersistenceProvider.java:126)

La piste de la solution est ici : Hibernate OSGi 4.3.0.CR1 can’t discover services

Cette erreur je l’ai résolu en faisant une dernière montée de version d’hibernate de 4.3.0.Final -> 4.3.1.Final.

Après cette montée de version j’ai pu accéder au fichier persistence.xml de mon bundle et créer mon entitymanager.

Mon environnement final étant celui-ci :

  • OSGI Equinox org.eclipse.osgi_3.8.2
  • Hibernate : hibernate-4.3.1.Final
  • Hibernate OSGI: hibernate-osgi-4.3.1.Final
  • Hibernate envers : hibernate-envers-4.3.1.Final

A noté aussi : je rappel que hibernate-envers n’est aucunement obligatoire, mais que si vous l’avez utilisé (comme moi) vous devez obligatoirement faire sa montée de version aussi en 4.3.1 car il y aura un problème de compatibilité sinon.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Vous devez remplir ce champ
Vous devez remplir ce champ
Veuillez saisir une adresse e-mail valide.
Vous devez accepter les conditions pour continuer

Menu