Difference between revisions of "Gemini/JPA/Documentation/CreatingAnApplication"

From Eclipsepedia

Jump to: navigation, search
(Using Your Own DataSource)
(Using your own DataSource)
Line 64: Line 64:
  
 
Note that a Datasource specified in this property will override any configured JDBC properties-based datasource that may have been specified in the persistence descriptor.
 
Note that a Datasource specified in this property will override any configured JDBC properties-based datasource that may have been specified in the persistence descriptor.
 +
 +
See the [[Gemini/JPA/Documentation/OtherTopics#Non-relational_Databases | Non-relational Databases]] section to see how this property can be used to hook up to non-relational databases as well as relational ones.
  
 
See the [[Gemini/JPA/Documentation/OtherTopics#Configuration_Admin | Configuration Admin]] section for alternative ways to dynamically specify a datasource.
 
See the [[Gemini/JPA/Documentation/OtherTopics#Configuration_Admin | Configuration Admin]] section for alternative ways to dynamically specify a datasource.

Revision as of 13:21, 11 February 2013

Contents

Creating a Persistence Application

The following sections describe how to create and configure a JPA application using Gemini JPA.

Defining a Persistence Unit

When defining a persistence unit there are a few differences when using Gemini JPA in OSGi, as opposed to traditional JPA in a classpath-based environment. Traditional JPA dictates that a persistence descriptor called persistence.xml file must be placed in the META-INF folder of a JAR file. In OSGi, the limitations are not as stringent and the file may be given any name and placed anywhere in the persistence bundle, the bundle containing the persistence unit. The caveat is that a special manifest header, the Meta-Persistence header, must be added to the META-INF/MANIFEST.MF file and the named descriptor, with its location relative to the root of the bundle, indicated as the value of the header. Multiple descriptors may even be specified defining multiple persistence units. If the traditional META-INF/persistence.xml descriptor name and location is used then the Meta-Persistence header entry can be left with an empty value entry. The default descriptor, if it exists, is always added to the set of descriptors that are specified in the Meta-Persistence headers. The following are examples of valid Meta-Persistence entries:

  • Meta-Persistence: META-INF/persistence.xml
    Uses the default descriptor and (redundantly) indicates the name and location.
  • Meta-Persistence:
    Assumes the default META-INF/persistence.xml descriptor. Note that one or more spaces may need to be used as the value to satisfy the manifest parser.
  • Meta-Persistence: META-INF/jpa.xml
    Specifies a file named jpa.xml located in the META-INF folder of the bundle. If META-INF/persistence.xml exists in the bundle then the persistence units defined in it will also be processed.
  • Meta-Persistence: jpa1.xml, jpa2.xml
    Specifies two persistence descriptors, jpa1.xml and jpa2.xml, both located in the root of the bundle. If META-INF/persistence.xml exists in the bundle then the persistence units defined in it will also be processed.

Persistence Descriptor

The contents of the persistence descriptor for the most part follows the typical contents of a standard persistence.xml file in a Java SE environment. The following stipulations and rules also apply:

  1. The transaction type should be RESOURCE_LOCAL (if specified).
  2. If the mapping-file element is used the entry must be relative to the root of the bundle.
  3. Entities should be enumerated in class elements.
  4. The javax.persistence.jdbc.{driver,url,user,password} properties must be used to specify the JDBC connection properties.

In addition, EclipseLink-specific properties an be used as described in the EclipseLink documentation.

Declaring your Dependencies

As when using OSGi for any application, the dependencies that you specify in your persistence application must be carefully defined and properly specified. The first thing you must declare is a dependency on the set of JPA 2.0 javax.persistence packages that you use. (Note: Even if you are creating a persistence bundle with no annotations and using XML for all of the mapping you must import the javax.persistence package.)

When importing the JPA packages, the OSGi standard recommends that the “jpa” attribute be set to “2.0” to indicate the 2.0 version of the JPA specification. The EclipseLink javax.persistence jar does the exporting using this attribute. An example application import is:

Import-Package: javax.persistence;jpa=”2.0”;version=”1.1.0”, …

If EclipseLink API’s are used then additional EclipseLink package dependencies may also be required.

JDBC Access

There are a couple of common ways of getting to the JDBC driver, plus some additional ways that you can use (kind of as a last resort). the main way of accessing the database is through Gemini DBAccess. It will offer shared driver access across applications. Alternatively, a JDBC driver can be included in the bundle for localized access.

If you have obtained a datasource on your own and want the EMF to use it instead of creating one then you can pass your own datasource in to the EMF creation method along with a custom Gemini JPA property.

Using Gemini DBAccess

Gemini DBAccess offers modular sharable JDBC driver access to selected database drivers. By installing and starting the DBAccess support bundle, as well as the database driver bundle(s), Gemini JPA can be a consumer of the DataSourceFactory service defined by the OSGi JDBC specification.

DBAccess posts a DataSourceFactory service for the JDBC driver using the JDBC driver class name as the service name. When JPA needs a datasource it takes the driver class specified in the javax.persistence.jdbc.driver property and uses it to look up the datasource factory. Once it finds the factory it creates a datasource and holds onto it to obtain connections when required.

Using a local JDBC Driver

If DBAccess is not being used, the JDBC driver can be made accessible to Gemini JPA when it processes the persistence unit. The best way to do this is to package the driver in the persistence unit bundle, ensuring it is on the Bundle-ClassPath as well.

Using your own DataSource

If you already have the datasource that you want to use and don't want Gemini JPA to create one then you can pass in your own datasource by using the EMF builder to create your EMF. After you obtain the EntityManagerFactoryBuilder instance, call the createEntityManagerFactory() method and pass in a property named gemini.jpa.providerConnectedDataSource. Note that this property is better used by its constant definition: GeminiPersistenceUnitProperties.PROVIDER_CONNECTED_DATA_SOURCE. The value of the property should be the actual datasource object. See example below:

 DataSource myDS = ...;  // Get datasource from somewhere
 EntityManagerFactoryBuilder emfBuilder = ... ; // Look up builder from ServiceRegistry
 Map<String, Object> props = new HashMap<String,Object>();
 props.put(GeminiPersistenceUnitProperties.PROVIDER_CONNECTED_DATA_SOURCE, myDS);
 EntityManagerFactory emf = emfBuilder.createEntityManagerFactory(props);

Note that a Datasource specified in this property will override any configured JDBC properties-based datasource that may have been specified in the persistence descriptor.

See the Non-relational Databases section to see how this property can be used to hook up to non-relational databases as well as relational ones.

See the Configuration Admin section for alternative ways to dynamically specify a datasource.

Application Design

The structure of a persistence application is fairly constrained according to the OSGi JPA specification, and falls into one of the following three architectural options:

  1. Inlined Persistence Unit
    A common and simple application design is one that makes use of a JPA persistence unit that is co-resident (in the same bundle) with the application code that invokes it. In this design the application is packaged up into a single bundle, including both the persistence entities and the code that operates on them.
  2. Modular Persistence Unit
    A more reusable option is to package the persistence unit in a separate bundle and have the application code that needs to operate on the entities have a dependency on the persistence unit bundle or services it offers.
  3. Nested Persistence Unit

    A more advanced design is to nest a persistence unit JAR file inside the persistence bundle. While not common, it does allow a POJAR (Plain Old Java ARchive) containing a persistence unit to be easily incorporated into a bundle. The JAR must be placed on the bundle classpath, and the persistence descriptor must be qualified in the Meta-Persistence header using the embedded JAR syntax. For example, if a JAR named empUnit.jar contained a jpa.xml persistence descriptor in the META-INF folder, and the empUnit.jar file was placed in the jpa folder of the appBundle.jar application bundle, as shown in the following hierarchy:
 appBundle.jar
   jpa/
     empUnit.jar
       META-INF/
         jpa.xml

then the MANIFEST.MF file in the application bundle would include the following headers:

Meta-Persistence: jpa/empUnit.jar!/META-INF/jpa.xml
...
Bundle-ClassPath: ., jpa/empUnit.jar