Maven, Hibernate et Persistence provider...

Ce post a pour but d'expliquer les différentes raisons pour lesquelles, lors du lancement d'une application packagée sous forme de jar par Maven, est parfois levée l'erreur :

javax.persistence.PersistenceException: No Persistence provider for EntityManager named ...

Pour changer des mes habitudes, l'environnement de développement utilisé ici est Netbeans, mais les instructions que je vais donner sont valables également pour Eclipse.

Il y a 3 choses à vérifier pour corriger ce problème, de la plus simple à la plus compliquée :


  1. Vérifier la présence du fichier de configuration hibernate persistence.xml dans le projet, au bon endroit! Sous Netbeans, il doit se trouver à ce niveau :
    Pour le créer, il est possible d'utiliser l'assistant 'Nouveau fichier'>'Catégorie Persistence'>'Type Persitence Unit'

  2. Le contenu du fichier persistence.xml doit être de la forme :
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
      <persistence-unit name="PU_NAME" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>my.class.EntityName</class>
        <class>...</class>
        <properties>
          <property name="hibernate.connection.username" value="username"/>
          <property name="hibernate.connection.driver_class" value="driver_class"/>
          <property name="hibernate.connection.password" value="password"/>
          <property name="hibernate.connection.url" value="jdbc:..."/>
          <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
          <property name="hibernate.dialect" value="org.hibernate.dialect.TheDialect"/>
          <property name="hibernate.show_sql" value="false"/>
        </properties>
      </persistence-unit>
    </persistence>
    

  3. Si vous arrivez ici, c'est que les choses se compliquent pour vous! ;) En effet, malgré l'assurance du fait que le fichier de configuration soit placé au bon endroit, il se peut que l'erreur continue de se produire... C'est ce qui se passait dans mon cas : lorsque je lançait mon application depuis l'IDE, tout fonctionnait à merveille. Mais lorsque je voulais l'exécuter en ligne de commande depuis le jar produit par Maven, plus rien à faire... Et même si l'erreur renvoyée est toujours la même, le problème se situe en réalité du côté des dépendances que Maven n'a pas résolues. En effet, puisque nous avons déclaré dans le fichier de configuration hibernate, le provider org.hibernate.ejb.HibernatePersistence, il faut inclure de manière explicite la dépendance suivante dans le pom.xml du projet, comme indiqué ici Doc Hibernate :
    <dependency>
      <artifactId>hibernate-entitymanager</artifactId>
      <groupId>org.hibernate.jpa</groupId>
      <type>jar</type>
      <version>3</version>
    </dependency>
    
    Mais va maintenant se poser le problème de toutes les autres dépendances liées à celle-ci... Mais alors, comment cela fonctionne-t-il dans l'IDE et pas en ligne de commande? La réponse vient de la faculté assez vicieuse pratique de Netbeans à se coupler à Maven : il se peut que vous ayez défini, dans l'IDE, une librairie pointant directement sur votre repository local Maven, comme ceci par exemple :
    Ce qui a pour conséquence de permettre à l'IDE de facilement trouver les librairies dont vous avez besoin pour votre projet, mais de ne finalement pas les lui lier directement... D'où leur absence lors du build Maven... Pour régler ceci, il faut déclarer dans le pom TOUTES les dépendances nécessaires au projet! Afin que Maven puisse les récupérer tout seul comme un grand. Pour ce faire, dans Netbeans, vous pouvez sélectionner les librairies du projet et utiliser l'action "Declare as direct dependency" :
    Et le tour est joué! Le build Maven va maintenant pouvoir clairement récupérer tout le nécessaire au projet et permettre son exécution de manière indépendante en ligne de commande.

La morale de cette histoire est de toujours vérifier, lors de développements d'applications vouées à être utilisées aussi bien depuis un IDE que de manière autonomes (via un jar construit par Maven), que l'IDE n'a pas été un peu trop "zélé" dans son rôle de "facilitateur" dans la mise en place du projet...


Fichier(s) joint(s) :