EclipseLink/Development/JPA 2.0/properties processing

From Eclipsepedia

Jump to: navigation, search

JPA 2.0: Property Processing

JPA 2.0 Root | bug 249023 | bug 293354 | bug 294086

Date Committer(s) Description
March 24, 2009 gyorke Initial feature template

Summary

The JPA 2.0 Specification provides functionality to set properties on the EntityManager at runtime. Before that feature can be completed we must define what properties can be set on the Entity Manager and when. This will allow use to clearly communicate to our customers how and when certain configurations can be applied. We must also update our property processing to ensure properties can be processed on a per property basis and that the property processing functionality is complete and available.

Work Estimate

  • Define all properties and when they apply
    • 1 day
  • Update property processing to account for lifecycle and validation
    • 4 days
  • write tests to verify validation and lifecycle
    • 2 days

Functional Requirements

Entity Manager Factories and SeverSessions

Current behaviour

  1. Several EntityManagerFactories corresponding to the same persistence unit (and loaded from the same resource) share the same ServerSession.
    1. The ServerSession is configured according to the properties of the first factory to create EntityManager.
      1. That mean the properties specified by all other EntityManagerFactories are ignored.
props1.put(PersistenceUnitProperties.JDBC_USER, "user1");
EntityManagerFactory emf1 = Persistence.createEntityManagerFactory("default", props1);
props2.put(PersistenceUnitProperties.JDBC_USER, "user2");
EntityManagerFactory emf2 = Persistence.createEntityManagerFactory("default", props2);
EntityManager em1 = emf1.createEntityManager();
EntityManager em1 = emf2.createEntityManager();
// Both emf1 and emf2 share the same ServerSession, which is connected through "user1".
// Session name is either defined in persistence.xml or is the unique persistence unit name (concatination of puUrl and puName).
  1. The only way to create an EntityManagerFactory that uses a different ServerSession is to specify SESSION_NAME in createEntityManagerFactory properties.
props1.put(PersistenceUnitProperties.SESSION_NAME, "session1");
props1.put(PersistenceUnitProperties.JDBC_USER, "user1");
EntityManagerFactory emf1 = Persistence.createEntityManagerFactory("default", props1);
props2.put(PersistenceUnitProperties.SESSION_NAME, "session2");
props2.put(PersistenceUnitProperties.JDBC_USER, "user2");
EntityManagerFactory emf2 = Persistence.createEntityManagerFactory("default", props2);
EntityManager em1 = emf1.createEntityManager();
EntityManager em1 = emf2.createEntityManager();
// emf1 uses "session1", which is connected through "user1";
// emf2 uses "session2", which is connected through "user2";

New behaviour - generate session name from connection properties

  1. Session name is generated using connection properties' names and values passed to createEntityManagerFactory prefixed by unique persistence unit name, if
    1. either no SESSION_NAME defined in persistence.xml:
    2. or SESSION_NAME property with empty string value is passed to createEntityManagerFactory.
// set session name to empty string - only required in case SESSION_NAME is specified in perssitence.xml
props1.put(PersistenceUnitProperties.SESSION_NAME, "");
props1.put(PersistenceUnitProperties.JDBC_USER, "user1");
EntityManagerFactory emf1 = Persistence.createEntityManagerFactory("default", props1);
// set session name to empty string - only required in case SESSION_NAME is specified in perssitence.xml
props2.put(PersistenceUnitProperties.SESSION_NAME, "");
props2.put(PersistenceUnitProperties.JDBC_USER, "user2");
EntityManagerFactory emf2 = Persistence.createEntityManagerFactory("default", props2);
EntityManager em1 = emf1.createEntityManager();
EntityManager em1 = emf2.createEntityManager();
// emf1 uses "default_user=user1", which is connected through "user1";
// emf2 uses "default_user=user2", which is connected through "user2";
  1. Non-empty SESSION_NAME is used as session name if specified either in persistence.xml or passed to createEntityManagerFactory (the same as old behaviour);
  2. Unique persistnece unit name used as session name if neither SESSION_NAME specified nor connection properties passed to createEntityManagerFactory.
    1. Unique persistence unit name is
      1. persistence unit root url + persistence unit name (in case persistence unit name does not uniquely define the persistence unit):
        1. application server case (both container-managed and application-managed);
      2. persistence unit name (in case persistence unit mane uniquely defines the persistence unit):
        1. Standalone SE case using agent (globalInstrumentation);
        2. Curent implementation of OSGi support.
Connection properties

Defined in EntityManagerSetupImpl:

    public static String[] connectionPropertyNames = {
        PersistenceUnitProperties.TRANSACTION_TYPE,
        PersistenceUnitProperties.JTA_DATASOURCE,
        PersistenceUnitProperties.NON_JTA_DATASOURCE,
        PersistenceUnitProperties.JDBC_URL,
        PersistenceUnitProperties.JDBC_USER,
    };
Examples
// to override SESSION_NAME if one is specified in persistence.xml
properties.put(PersistenceUnitProperties.SESSION_NAME, "");
properties.put(PersistenceUnitProperties.TRANSACTION_TYPE, "RESOURCE_LOCAL");
// to override data source if one is specified in persistence.xml
properties.put(PersistenceUnitProperties.JTA_DATASOURCE, "");
// to override data source if one is specified in persistence.xml
properties.put(PersistenceUnitProperties.NON_JTA_DATASOURCE, "");
properties.put(PersistenceUnitProperties.JDBC_URL, myUrl);
properties.put(PersistenceUnitProperties.JDBC_USER, myUser);
properties.put(PersistenceUnitProperties.JDBC_DRIVER, myDriver);
properties.put(PersistenceUnitProperties.JDBC_PASSWORD, myPassword);
emf = Persistence.createEntityManagerFactory(puName, properties);
// emf uses session named default_transactionType=RESOURCE_LOCAL_url=myUrl_user=myUser
// to override SESSION_NAME if one is specified in persistence.xml
properties.put(PersistenceUnitProperties.SESSION_NAME, "");
properties.put(PersistenceUnitProperties.TRANSACTION_TYPE, "JTA");
properties.put(PersistenceUnitProperties.JTA_DATASOURCE, myJtaDS);
properties.put(PersistenceUnitProperties.NON_JTA_DATASOURCE, myNonJtaDS);
// to override user if one is specified in persistence.xml
properties.put(PersistenceUnitProperties.JDBC_USER, "");
// note that there is no need to override JDBC_URL, JDBC_DRIVER, JDBC_PASSWORD with an empty string, they will be ignored.
// JDBC_URL, JDBC_DRIVER - because data source(s) are specified; JDBC_PASSWORD - because JDBC_USER is not specified 
emf = Persistence.createEntityManagerFactory(puName, properties);
// emf uses session named default_transactionType=JTA_jtaDataSource=myJtaDS_nonJtaDataSource=myNonJtaDS

Entity Manager Properties

Two groups of properties

Only properties passed to createEM method guaranteed to take effect right away.

Some EntityManager properties could be applied to the unit of work which already exists, other can't. For each property that should be clearly listed in EntityManagerProperty class comments.

  1. For each property of the first group, property value processed immediately as setProperty called.
    1. Each time getActivePersistenceContext is called the processed property value is set in the uow.
      1. Obvious optimization to add a flag indicating whether any of first group properties has changed since being last time set into the uow.
  1. Properties of the second group processed and applied only when the new uow is created.
    1. User have to call em.clear() unless property applied to a brand new EntityManager.
      1. Even if the em is new, some application servers (was, oc4j) would have already created uow (they likely call em.joinTransaction()).
First group: properies applicable to existing uow
  1. JOIN_EXISTING_TRANSACTION
  2. PERSISTENCE_CONTEXT_CLOSE_ON_COMMIT
  3. PERSISTENCE_CONTEXT_PERSIST_ON_COMMIT
  4. PERSISTENCE_CONTEXT_COMMIT_WITHOUT_PERSIST_RULES
  5. PERSISTENCE_CONTEXT_FLUSH_MODE
  6. VALIDATE_EXISTENCE
  7. FLUSH_CLEAR_CACHE
Second group: properies that require new uow
  1. PERSISTENCE_CONTEXT_REFERENCE_MODE
  2. ORACLE_PROXY_TYPE
  3. EXCLUSIVE_CONNECTION_MODE
  4. EXCLUSIVE_CONNECTION_IS_LAZY
  5. JTA_DATASOURCE
  6. NON_JTA_DATASOURCE
  7. JDBC_DRIVER
  8. JDBC_URL
  9. JDBC_USER
  10. JDBC_PASSWORD
  11. CONNECTION_POLICY

Existing Feature Impact

Feature Supported Notes

Design

Documentation

Testing

Open Issues