Appendix C.2 Deployment-related contract

The deployment-related contract includes the responsibilities of the container and the responsibilities of the JPA provider.

Organization of this subsection
(1) Responsibilities of the container
(2) Responsibilities of the JPA provider
(3) javax.persistence.spi.PersistenceProvider interface
(4) javax.persistence.spi.PersistenceUnitInfo interface

(1) Responsibilities of the container

During deployment, the container searches persistence.xml packaged at a decided location within the application. If persistence.xml exists in the application, the container processes the definition of the persistence unit defined in persistence.xml. For details on the locations searched by the container, see 5.8 Definitions in persistence.xml.

The container verifies persistence.xml file using persistence_1_0.xsd. If the verification results in an error, the container reports to the user. If the provider and data source information is not specified in persistence.xml, the default value is used. For details on the default values used, see 5.8 Definitions in persistence.xml. When creating the entity manager factory of the persistence unit, the container passes the properties to the JPA provider.

The container creates the implementation class instance of javax.persistence.spi.PersistenceProvider defined for each persistence unit in persistence.xml, invokes the createContainerEntityManagerFactory method, and obtains EntityManagerFactory for creating the container-managed entity manager. The Meta data of the persistence unit is passed as the PersistenceUnitInfo object to the JPA provider using the argument of the createContainerEntityManagerFactory method. The container creates only one EntityManagerFactory for one persistence unit definition and creates multiple EntityManagers from that EntityManagerFactory.

When the persistence unit is re-deployed, the container invokes the close method of EntityManagerFactory that is already obtained and then invokes createContainerEntityManagerFactory along with the new PersistenceUnitInfo.

(2) Responsibilities of the JPA provider

The JPA provider must implement PersistenceProvider SPI, and when the createContainerEntityManagerFactory method of PersistenceProvider is invoked, the JPA provider must use the Meta data (PersistenceUnitInfo) of the persistence unit passed in the argument to create EntityManagerFactory, and return the created EntityManagerFactory to the container.

The JPA provider processes the Meta data annotation of the managed class (such as an entity class) included in the persistence unit. Also, when the O/R mapping file is used in the persistence unit, the JPA provider must interpret the file. At this time, the JPA provider verifies the O/R mapping file by using orm_1_0.xsd and must notify the user if an error occurs.

(3) javax.persistence.spi.PersistenceProvider interface

The JPA provider must implement the javax.persistence.spi.PersistenceProvider interface. This interface is invoked by the container and is not invoked from the application. The PersistenceProvider implementation class must be public and must have a constructor without argument.

The javax.persistence.spi.PersistenceProvider interface is as follows:

package javax.persistence.spi;

/**
* Interface implemented by the JPA provider.
* This interface is used for creating EntityManagerFactory.
* In the Java EE environment, the interface is invoked by the container
* and in the JavaSE environment, the interface is invoked by the
* persistence class.
*/
public interface PersistenceProvider {

/**
* Invoked when the persistence class creates EntityManagerFactory.
*
* @param emName Name of the persistence unit
* @param map property Map used by the JPA provider.
* The property specified here is used to overwrite the property
* corresponding to the persistence.xml file or to specify
* the property that is not specified in the persistence.xml file.
* (If the property need not be specified, null is passed)
* @return EntityManagerFactory of persistence unit
* If the JPA provider is incorrect, null is returned.
*/
public EntityManagerFactory createEntityManagerFactory(String
emName, Map map);

/**
* Invoked when the container creates EntityManagerFactory.
*
* @param info Meta data to be used by the JPA provider
* @param map Integration level property to be used by the JPA provider
* (if not specified, null is passed)
* @return EntityManagerFactory of the persistence unit specified
* in Meta data
*/
public EntityManagerFactory createContainerEntityManagerFactory(
PersistenceUnitInfo info, Map map);
}

(4) javax.persistence.spi.PersistenceUnitInfo interface

The javax.persistence.spi.PersistenceUnitInfo interface definition is as follows:

import javax.sql.DataSource;
/**
* This interface is implemented by the container and is passed to
* the JPA provider when EntityManagerFactory is created.
*/
public interface PersistenceUnitInfo {

/**
* @return Persistence unit name defined in persistence.xml
*/
public String getPersistenceUnitName();

/**
* @return Fully qualified class name of the JPA provider
* implementation class defined in the <provider> element of
* persistence.xml
*/
public String getPersistenceProviderClassName();

/**
* @return Returns the transaction type of EntityManager
* created by EntityManagerFactory
* Type specified in the transaction-type attribute of
* persistence.xml.
*/
public PersistenceUnitTransactionType getTransactionType();

/**
* @return Returns a data source with JTA enabled
* for use by the JPA provider.
* Data source specified in the <jta-data-source> element of
* persistence.xml or the data source determined by the container
* during deployment.
*/
public DataSource getJtaDataSource();

/**
* @return Returns a data source with JTA disabled for the JPA provider
* to access the data outside the JTA transaction.
* Data source specified in <non-jta-data-source> element of
* persistence.xml or the data source determined by the container
* during deployment.
*/
public DataSource getNonJtaDataSource();

/**
* @return List of mapping file names that must be loaded for the
* JPA provider to determine the entity class mapping.
* The mapping file must have the standard XML mapping format.
* The mapping file must have a unique name and must be
* loadable as a resource from the application class path.
* The mapping file names are specified in the
* <mapping-file> tag of persistence.xml.
*/
public List<String> getMappingFileNames();

/**
* Returns the URL list of JAR files or directory deploying the
* JAR files, required for searching the managed class of the
* persistence unit by the JPA provider.
* Each URL is specified in the <jar-file> tag of the persistence.xml
* file.
* The URL is in a file URL format indicating JAR files or directory
* deploying the JAR files or in another URL format that can obtain
* InputStream in the JAR format.
*
* @return List of URL objects indicating the JAR files or directories
*/
public List<URL> getJarFileUrls();

/**
* Returns the URL of the JAR file or directory forming the persistence
* unit root
* (If the persistence unit root is WEB-INF/classes directory,
* returns the URL of WEB-INF/classes directory)
* The URL is in a file URL format indicating JAR files or directory
* deploying the JAR files or in another URL format that can obtain
* InputStream in the JAR format.
*
* @return URL object indicating JAR files or directories
*/
public URL getPersistenceUnitRootUrl();

/**
* @return List of class names that the JPA provider must handle
* as managed classes.
* Each class name is specified in the <class> tag of the
* persistence.xml file
*/
public List<String> getManagedClassNames();

/**
* @return Returns whether to handle the class that is deployed
* in the persistence unit root and is not explicitly specified
* as managed class, as a managed class.
* This value is specified in the <exclude-unlisted-classes> tag
* of the persistence.xml file.
*/
public boolean excludeUnlistedClasses();

/**
* @return Properties object.
* Each property is specified in the <property> tag of the
* persistence.xml file.
*/
public Properties getProperties();

/**
* @return ClassLoader that can be used by the JPA provider
* to load classes and resources and to open URLs.
*/
public ClassLoader getClassLoader();

/**
* Class loader returned by the PersistenceUnitInfo.getClassLoader
* method and registers the JPA provider transformer that is invoked
* every time a new class is defined or a class is re-defined.
* This transformer is returned by the  * PersistenceUnitInfo.getNewTempClassLoader method
* and does not affect the classes loaded by the class loader.
* Even if some persistence units are defined in the class loading
* scope, the class is only converted once in the same class loading
* scope.
*
* @param transformer JPA provider transformer invoked by the
* container to define (re-define) a class.
*/
public void addTransformer(ClassTransformer transformer);

/**
* Returns a new instance of the class loader
* that can be used temporarily by the JPA provider to load classes
* and resources and to open the URLs.
* The scope and class path of this class loader
* is exactly similar to the class loader returned
* by PersistenceUnitInfo.getClassLoader.
* The classes loaded with this class loader cannot
* be referenced from the application components.
* The JPA provider can use this class loader only in
* the extended invocation of createContainerEntityManagerFactory.
*
* @return Temporary class loader having the same scope
* or class path as the current class loader.
*/
public ClassLoader getNewTempClassLoader();

}

Reference note
With Application Server, if the JTA data source and non-JTA data source are not defined in the persistence unit, getJtaDataSource() or getNonJtaDataSource() return null. The preceding text "if the JTA data source and non-JTA data source are not defined in the persistence unit" indicates the following state:
  • When <jta-data-source> and <non-jta-data-source> are omitted in persistence.xml and the default value is not defined in the system properties ejbserver.jpa.defaultJtaDsName and ejbserver.jpa.defaultNonJtaDsName
  • When the system properties ejbserver.jpa.overrideJtaDsName and ejbserver.jpa.overrideNonJtaDsName are also not defined