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.
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. For example, when the javax.persistence bundle is started its activator sets the 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.
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”.