Jump to: navigation, search

Gemini/JPA/Documentation/JPAServices

JPA Services

When a persistence bundle gets installed, the persistence units it defines will be discovered and processed by Gemini JPA. The first processing stage will occur before the bundle gets resolved, while the second one will occur after the bundle has been resolved. It is during the second processing step that Gemini JPA will normally register two services, the EntityManagerFactory service and the EntityManagerFactoryBuilder service, in the OSGi service registry for each persistence unit in the bundle.

EntityManagerFactory Service

The first service to get registered is the EntityManagerFactory service. It is the service that is typically looked up and used by JPA users. It will be registered under the fully qualified javax.persistence.EntityManagerFactory name and with the following properties:

Property Name Property Value
osgi.unit.name Name of the persistence unit
osgi.unit.version Bundle version of the persistence bundle
osgi.unit.provider Class name of assigned provider
osgi.managed.bundles Bundle id of the persistence bundle


The EntityManagerFactory (EMF) service will only be registered if the JDBC driver is accessible. Gemini JPA will check for JDBC accessibility in two ways. First, it will use the javax.persistence.jdbc.driver property to look for a DataSourceFactory service in the service registry. If Gemini DBAccess is running then it will register this service for the database driver. If the service is not found then a local load will be attempted, meaning that Gemini JPA will attempt to load the driver directly from the persistence bundle. If unsuccessful, no EMF service will be registered for the persistence unit.

Using the EntityManagerFactory Service

Gemini JPA users will normally look up the EMF service by specifying the name of the EntityManagerFactory class and filtering it with the persistence unit name property. The following example method illustrates how this can be done:

public EntityManagerFactory lookupEMF(String unitName) {
    ServiceReference[] refs = null;
    try {
        refs = context.getServiceReferences(
                              EntityManagerFactory.class.getName(), 
                              "(osgi.unit.name="+unitName+")");
    } catch (InvalidSyntaxException isEx) {
        throw new RuntimeException("Filter error", isEx);
    }
    return (refs == null)
        ? null
        : (EntityManagerFactory) context.getService(refs[0]);
}

It was mentioned earlier that an EMF service will be created when either the JDBC driver DataSourceFactory service is available for that persistence unit, or the driver is packaged locally in the persistence bundle. If the DataSourceFactory service was available but is later unregistered then the EMF service will similarly be unregistered. Users may want to be notified when this happens, since it implies that the EMF will no longer have database access and will become inoperative.

Service trackers are often used to detect when services come online or offline, and could similarly be used to track when an EMF service for a given persistence unit becomes available or unavailable.

EntityManagerFactoryBuilder Service

The second service to get registered for every persistence unit is the EntityManagerFactoryBuilder service. This service is registered regardless of whether the JDBC driver or datasource is accessible, and is used when the user wants to create an EMF and dynamically specify the JDBC properties at runtime. It is less commonly used and the user must rely on their own knowledge that the JDBC datasource they specify, or that is specified in the persistence descriptor, is available. The service will be registered under the fully qualified class name of org.osgi.service.jpa.EntityManagerFactoryBuilder and with the same properties as those listed above for the EntityManagerFactory service.

Using the EntityManagerFactoryBuilder Service

Users should look up the EMF Builder service by specifying the name of the EntityManagerFactoryBuilder class and filtering it with the persistence unit name property. Once the service is obtained, an entity manager factory can be acquired by invoking the createEntityManagerFactory() method on the builder.

The following example method shows how the builder can be looked up and used to obtain an EMF with a set of dynamic JDBC properties. It is assumed that the properties Map passed in contains the set of javax.persistence.jdbc connection properties:

 
public EntityManagerFactory getEMF(String unitName, 
                                   Map<String,String> props) {
    ServiceReference[] refs = null;
    EntityManagerFactoryBuilder emfb = null;
 
    try {
        refs = context.getServiceReferences(
                          EntityManagerFactoryBuilder.class.getName(),
                          "(osgi.unit.name="+unitName+")");
    } catch (InvalidSyntaxException isEx) {
        throw new RuntimeException("Filter error", isEx);
    }
    if (refs != null)
        emfb = 
           (EntityManagerFactoryBuilder)context.getService(refs[0]);
   return (emfb == null) 
        ? null 
        : emfb.createEntityManagerFactory(props);
}

Note that when creating an EMF from an EMFB the same process for locating a JDBC driver that was used in the EMF service is also used in the entity manager factory creation call. If the datasource factory is detected then it will be used. The difference is that when using an EMFB there is no tracking of the datasource factory by Gemini JPA, so users are responsible for tracking the availability of the datasource on their own.