Jump to: navigation, search

Gemini/JPA/Documentation/OtherTopics

Other Topics

Multiple Persistence Unit Versions

If there are multiple versions of a persistence bundle that are active at the same time, Gemini JPA will treat them as different bundles. However, if they have the same persistence unit name then the EntityManagerFactory services that get built by Gemini JPA for each of them will have the same value for its osgi.unit.name service property. Clients must distinguish between them by first ensuring they control which persistence unit bundle version they get resolved to, and then filtering for that bundle version using the osgi.unit.version property during the EntityManagerFactory service lookup. This will avert the possibility of getting resolved to one version of the persistence unit and then looking up a different version and getting a ClassCastException when operating on an entity class of the same name but from a different persistence unit bundle version.

Weaving

Certain kinds of lazy mappings make weaving of the entity classes necessary. In other cases, turning on weaving can be a way to optimize performance. Weaving is used by EclipseLink for various kinds of state management, from fetch groups to change tracking. The relevant documented EclipseLink weaving properties apply similarly in a Gemini JPA environment, except that by default they are all disabled in Gemini JPA. In general, to enable weaving the eclipselink.weaving persistence unit property should be set to true in the persistence unit.

For example:

...
    <properties>
        ...
        <property name="eclipselink.weaving" value="true"/>
        ...
    </properties>
...

For more information on EclipseLink weaving properties refer to the section of the EclipseLink documentation on weaving properties.

Non-relational Databases

EclipseLink provides support for a number of NoSQL databases, EIS connectors, and other kinds of backend data sources. These features are enabled within Gemini JPA by setting a special Gemini JPA property in addition to the connection properties needed to connect to the data source.

The gemini.jpa.providerConnectedDataSource property is a persistence unit level property that can be specified either in the persistence descriptor or as a property passed to the EntityManagerFactoryBuilder createEntityManagerFactory method. The property value may be anything. Defining the property name will be enough to cause it to be in force. Setting the value to true is considered good style, though.

Once this property is set, Gemini JPA will not try to look up the usual JDBC properties, but leave it to EclipseLink to do the connecting. It assumes that EclipseLink can access and load the driver classes if a driver class is necessary. If the usual JDBC properties are specified then EclipseLink will use them and look up the JDBC driver, but the driver will be accessed directly, not tracked through an OSGi service so, again, it must be accessible to EclipseLink bundles.

An example of configuring for a MongoDB database is as follows:

...
    <properties>
        ...
        <property name="gemini.jpa.providerConnectedDataSource" value="true"/>
        <property name="eclipselink.target-database" 
                  value="org.eclipse.persistence.nosql.adapters.mongo.MongoPlatform"/>
        <property name="eclipselink.nosql.connection-spec" 
                  value="org.eclipse.persistence.nosql.adapters.mongo.MongoConnectionSpec"/>
        <property name="eclipselink.nosql.property.mongo.host" value="localhost"/>
        <property name="eclipselink.nosql.property.mongo.port" value="27017"/>
        <property name="eclipselink.nosql.property.mongo.db" value="myDB"/>        
        ...
    </properties>
...

Depending upon the data source being used, additional EclipseLink bundles may be necessary. See the EclipseLink documentation for configuring different types of data sources, and how they can be used in combination with JPA applications. The Gemini JPA part of the equation is just the gemini.jpa.providerConnectedDataSource property.

Installing and Starting Applications

One of the hard parts of starting a dynamic environment like OSGi is the ordering of the bundles that are being “deployed”. In theory, and when developed correctly, an OSGi bundle should be able to adapt to the coming and going of bundles that it relies upon. In practice, however, it may be more difficult, and unless your application goes the extra mile, it may be less resilient than you thought. Applications often have some base expectations that make it difficult, and possibly not even worth the effort, to handle complete dynamism. Here are some hints to help you start your application.

Start Order

While having a start order is not absolutely necessary, if no start order is specified then the door is open to the possibility of a certain class of timing problems. While small in number, there are a couple of things that could happen. For example, when the javax.persistence bundle is started, its activator sets its resolver (that it uses to find persistence providers) to be a special resolver that makes use of the OSGi service registry to find providers. If an application invokes the Persistence.createEntityManagerFactory() method before the javax.persistence bundle has been started then the correct resolver will not be set and the provider lookup will fail.

If a start order can be appropriately imposed, the following bundle order is recommended:

  1. javax.persistence
  2. osgi.enterprise
  3. JDBC driver bundle
  4. DBAccess bundle(s) (org.eclipse.gemini.dbaccess.<database>)
  5. org.eclipse.gemini.jpa
  6. application persistence unit bundle
  7. other application bundles

This allows the Gemini infrastructure bundles to already be in place when the persistence unit bundles come along. Failure to do this will not often be catastrophic, but can cause some spurious errors, such as the one mentioned above.

More commonly, if application bundles are resolved before the Gemini JPA bundle then all that will happen is they will be refreshed by Gemini JPA. (See Refreshing for more on this.)

Datasource Availability

A related side effect of start ordering is the availability of the DataSourceFactory service that Gemini DBAccess registers. When using Gemini DBAccess the JDBC driver will be assumed to be exported as a service from the service registry and Gemini JPA will try to look it up. If the service is not available because the Gemini DBAccess bundle has not started yet then Gemini JPA will not register the EMF service, only the EMFBuilder service. When the DataSourceFactory does eventually come online then the EMF service will get registered. If, in the meantime, before the DataSourceFactory is registered, the EMF Builder is used by an application to try to create an EMF then it will fail because the datasource is not yet available. Once again, the moral is that even though there is no resolved dependency on the datasource, its presence is rather critical unless direct JDBC driver access is being assumed.

Refreshing

When Gemini JPA starts up it makes the assumption that it is going to be weaving the persistence unit bundles. In order to be able to insert a weaving hook the persistence unit bundle must not already be resolved. If it was found to already be resolved then Gemini JPA will refresh the persistence unit bundle. This means it will stop and unresolve the bundle, and then begin the resolving process again on it. All bundles that are wired to some part if it will also be unresolved and then re-resolved.

If it turns out that weaving is not required then you may want to disable this refreshing behavior. This can be done by disabling the GEMINI_REFRESH system property that is enabled by default. Use the –D command line option to set this property to FALSE and cause Gemini JPA to not refresh bundles when it discovers persistence unit bundles that have already been resolved.

e.g.

java –DGEMINI_REFRESH=FALSE <framework start class>

If using Eclipse then this property can be included as a VM argument in a “Run Configuration”.

Configuration Admin

JPA developers are typically very familiar with JPA persistence descriptors and the configuration that must be contained in them. In OSGi the Configuration Admin service makes dynamic configuration possible. Gemini JPA 1.1 and up has support for integrating certain types of JPA configuration information from OSGi configurations. Two different kinds of configurations are supported: standalone configurations and incremental configurations. These are discussed in the sections below.

An OSGi configuration is created using the ConfigurationAdmin service, obtaining a configuration, setting dictionary properties in it, and then updating it. For Gemini JPA configurations the following rules are mandatory when creating either a standalone or incremental configuration:


  1. Always create a factory configuration using the createFactoryConfiguration() method.
    • Always set the first createFactoryConfiguration parameter (the factory pid) to "gemini.jpa.punit".
    • Always set the second createFactoryConfiguration parameter (the location) to null.
  2. Always specify the unit name property, with the key GeminiPersistenceUnitProperties.PUNIT_NAME ("gemini.jpa.punit.name").
  3. Only create a single configuration per persistence unit.


The following code snippet assumes that the ConfigurationAdmin service has been obtained from the service registry. For more information on the config admin service refer to the documentation of the framework you are using.

import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.Configuration;
...
 
void createConfiguration(ConfigurationAdmin configAdmin) {
    try {
        // For Gemini JPA always create a factory config and set the factory pid to "gemini.jpa.punit" 
        Configuration config = configAdmin.createFactoryConfiguration("gemini.jpa.punit", null);
 
        // Create a dictionary and insert config properties (must include the punit name property)
        Dictionary props = new Hashtable();
        props.put("gemini.jpa.punit.name", "Library");
        ...
 
        // Causes config to be updated, or created if it did not already exist
        config.update(props);
 
    } catch (Exception ex) {
        ex.printStackTrace();
        throw new RuntimeException(ex);
    }
}    
...
Standalone Configuration

A standalone configuration is one that an application creates with the purpose of supplying persistence information that is not present in the persistence bundle. Thus, a standalone configuration is only used when there is no persistence descriptor in the persistence bundle. If a persistence descriptor does exist in the persistence bundle then an incremental configuration should be used instead.

The following properties may be specified in standalone configurations:


Property Name Value Description Optional/Mandatory
gemini.jpa.punit.name Name of the persistence unit Mandatory
gemini.jpa.punit.bsn Bundle symbolic name of the persistence bundle Mandatory
gemini.jpa.punit.classes Comma-separated list of fully qualified class names of entities/managed classes Optional
gemini.jpa.punit.excludeUnlistedClasses When set to false, indicates that classes are to be detected automatically by EclipseLink Optional
gemini.jpa.providerConnectedDataSource When set to true, indicates that the data source will be obtained using native EclipseLink provider properties Optional
<EclipseLink native properties> Any EclipseLink property Optional


Note that when creating a standalone configuration an additional mandatory bsn (bundle symbolic name) property must be included in the configuration to specify the bsn of the persistence bundle to which the persistence configuration should applied.

Incremental Configuration