Search code examples
jpaeclipse-rcppersistenceentitymanagerjpa-2.1

Instanciate a JPA EntityManager in an Eclipse RCP (Java SE) environment


Context :

  • Eclipse RCP project, divided into plugins, each one devoted to a task (eg : HMI management, communications, ...)

Necessity to persist some data in a database

- ORM : hibernate's JPA (JPA 2.1, Hibernate 5.2.1 used throught an org.hibernate.core plugin as constructed  [here (page 8)][1]
- database : in mysql 
- constraint : Java SE environment, so the only way to obtain an EntityManager (for the persistence operations) is to create it through an EntityManagerFactory 

First step (that works!) :

Plugin that manages the database operations, its structure :

com.plugin.name
    JRE System Library
    Plug-in Dependencies 
    Referenced Libraries          (contains the mysql connector jar)
    src/
        com.plugin.name           (package containing the plugin activator)
        com.plugin.name.entities  (package containing all my entities)
        com.plugin.name.utils     (package containing my access functions and a main)
        META-INF/
            persistence.xml       
    META-INF/
        MANIFEST.MF

In com.plugin.name.utils I have my classes performing all the persistence functions.

In these classes, I create an EntityManagerFactory this way :

private static final EntityManagerFactory ENTITY_MANAGER_FACTORY = Persistence.createEntityManagerFactory("com.plugin.name");

where "com.plugin.name" is the persistence unit name defined in my persistence.xml

In one of those classes, I have a main running some database-related functions.

When I run this main as java application, everything works fine.

(to prevent future questions : my persistence.xml file was originally generated in the MANIFEST.MF META-INF folder but when running this main, it couldn't be found, so I moved it. I checked both configurations when calling the persistence functions from another plugin)


The problem :

I need to access my persistence functions from another plugin, let's call him com.plugin.other

So I added com.plugin.name as a dependency of this plugin. But when I try to run the application, I get the following error :

javax.persistence.PersistenceException: No Persistence provider for EntityManager named com.plugin.name
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:61)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)

When i run the main as standalone application, if there's any problem with the persistence.xml file (not found, incomplete, etc) it gets at least mentionned... Here I'm really stuck with no clue to understand where the problem comes from.


Solution

  • I finally made it without the persistence.xml by using the createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map) method in the PersistenceProvider.

    Code :

    Activator a = Activator.getDefault();
    Bundle b = a.getBundle();
    URL url = b.getResource("META-INF/persistence.xml");
    
    List<PersistenceProvider> providers = PersistenceProviderResolverHolder.getPersistenceProviderResolver().getPersistenceProviders();
    
    for (PersistenceProvider pp : providers) {
    
        PersistenceUnitInfoImpl pui = new PersistenceUnitInfoImpl();
        pui.setPersistenceUnitName("persistenceUnitName");
        pui.setTransactionType(PersistenceUnitTransactionType.RESOURCE_LOCAL);
        pui.setPersistenceUnitRootUrl(url);
    
        Properties prop = pui.getProperties();
        if (prop == null) {
            prop = new Properties();
        }
        prop.setProperty("javax.persistence.jdbc.url", "jdbc:mysql://ip:port/dbName");
        prop.setProperty("javax.persistence.jdbc.user", "dbUser");
        prop.setProperty("javax.persistence.jdbc.password", "dbPass");
        prop.setProperty("javax.persistence.jdbc.driver", "com.mysql.jdbc.Driver");
    
        pui.setProperties(prop);
    
        pui.setClassLoader(com.mysql.jdbc.Driver.class.getClassLoader());     
            emFactory = pp.createContainerEntityManagerFactory(pui, null);
        }
    }