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.
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.
... <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.
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.
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:
- JDBC driver bundle
- DBAccess bundle(s) (org.eclipse.gemini.dbaccess.<database>)
- application persistence unit bundle
- 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.)
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.
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.
- java –DGEMINI_REFRESH=FALSE <framework start class>
If using Eclipse then this property can be included as a VM argument in a “Run Configuration”.