All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.smartgwt.client.docs.JpaIntegration Maven / Gradle / Ivy

The newest version!

package com.smartgwt.client.docs;

/**
 * 

Integration with JPA

* JPA 1.0 and JPA 2.0 annotated entities can be used as Smart GWT data sources. * The implementation class for JPA 1.0 is com.isomorphic.jpa.JPADataSource. * The implementation class for JPA 2.0 is com.isomorphic.jpa.JPA2DataSource. * Both implementations support search with simple {@link com.smartgwt.client.data.Criteria} and {@link * com.smartgwt.client.data.AdvancedCriteria}.
* The primary difference between JPA 1.0 and JPA 2.0 implementations is how data is fetched: * the JPA 1.0 implementation creates * a JPQL query string for fetching while the JPA 2.0 implementation uses Criteria API. *

* Tested JPA 2.0 providers *

    *
  • Hibernate 3.6.1 - PASS. Minimum version 3.6.1 - older versions * have a bug in the Criteria API * implementation which prevents correct negation of conjunction and disjunction predicates.
  • *
  • EclipseLink 2.2.0 - PASS.
  • *
  • OpenJPA 2.1.0 - FAIL. Does not support "lower(FIELD_NAME) LIKE lower('value')". * According to the exception message only "lower(FIELD_NAME) LIKE 'value'" is supported: *
    org.apache.openjpa.persistence.ArgumentException: The filter listener "matches" requires a constant
     * argument.
  • *
  • DataNucleus 2.2.2 - FAIL. Was not able to create even a simple query with Criteria API.
  • *
  • ObjectDB 2.1.0 - FAIL. Does not support Criteria API: *
    java.lang.UnsupportedOperationException: Unsupported feature - JPA Criteria Builder
  • *
* Note: MySQL DB - 'like' operator is used in a case insensitive manner. Check * MySQL Reference Manual :: C.5.5.1 Case * Sensitivity in String Searches * for more information. *

* JPA configuration *

* JPA configuration should be specified in the persistence.xml file and placed * in the /WEB-INF/classes/META-INF directory.
For JPA 2.0 make sure you correctly * declare its usage in persistence.xml:

 *  <persistence
 *      version="2.0"
 *      xmlns="http://java.sun.com/xml/ns/persistence"
 *      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 *   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
 *  >
 *  ...
 *  </persistence>

* To use JPA annotated entities you have to * {@link com.smartgwt.client.docs.DataSourceDeclaration create a DataSource} with these properties
    *
  • {@link com.smartgwt.client.docs.serverds.DataSource#serverConstructor serverConstructor} - * either JPA 1.0 * DataSource implementation: com.isomorphic.jpa.JPADataSource or JPA 2.0 * implementation: com.isomorphic.jpa.JPA2DataSource
  • . *
  • {@link com.smartgwt.client.docs.serverds.DataSource#beanClassName beanClassName} - fully * qualified * class name of JPA entity
* For example:
 *  <DataSource
 *      ID="countryDS"
 *      serverConstructor="com.isomorphic.jpa.JPA2DataSource"
 *      beanClassName="com.smartgwt.sample.showcase.server.jpa.Country"
 *  >
 *      <fields>
 *  <!-- ... Fields definition ... -->
 *      </fields>
 *  </DataSource>
 *  
* Supports field definitions with {@link com.smartgwt.client.data.DataSourceField#getValueXPath valueXPath} * settings. * Entity property is accessed (by priority):
    *
  1. {@link com.smartgwt.client.data.DataSourceField#getValueXPath valueXPath} - supports only simple XPath * definitions: * "property/subProperty/subSubProperty"
  2. *
  3. {@link com.smartgwt.client.data.DataSourceField#getName name} - most often used when data source field * name * is the same as entity property name
*

* JPA transactions *

* JPA provides two mechanisms for transactions: for JEE applications JPA provides integration * with JTA (Container Managed Transactions); for JSE applications JPA has a native * EntityTransaction implementation (Locally Managed Transactions). * The transaction mechanism should be configured in the server.properties file by setting * property jpa.emfProvider to the fully qualified class name of the provider * (implementation of com.isomorphic.jpa.EMFProviderInterface). Smart GWT comes * with three implementations:

    *
  • com.isomorphic.jpa.EMFProviderLMT - for Locally Managed Transactions. * Every fetch or DML operation starts a new transaction and commits after successful * execution.
    * This implementation reads the jpa.persistenceUnitName property from * the server.properties file. The value of this property needs to be set to * the name of the persistence unit configured in persistence.xml file. For example:
     *  jpa.persistenceUnitName: PERSISTENCE_UNIT_NAME
     *       
  • *
  • com.isomorphic.jpa.EMFProviderCMT - for Container Managed Transactions. * Every fetch or DML operation acquires the transaction object from the JEE container. * After successful method execution the container commits the transaction. In case of execution * failure tx.setRollbackOnly() is used to notify container to rollback the * transaction.
    * This implementation reads two properties from the server.properties file: * jpa.cmt.entityManager and jpa.cmt.transaction * containing appropriate resource name references configured in * /WEB-INF/web.xml. Configuration example:
     *  <!-- EntityManager resource reference name declaration -->
     *  <persistence-context-ref>
     *     <persistence-context-ref-name>persistence/em</persistence-context-ref-name>
     *     <persistence-unit-name>PERSISTENCE_UNIT_NAME</persistence-unit-name>
     *  </persistence-context-ref>
     * 
     *  <!-- Transaction resource reference name declaration -->
     *  <resource-env-ref>
     *      <resource-env-ref-name>persistence/tx</resource-env-ref-name>
     *      <resource-env-ref-type>javax.transaction.UserTransaction</resource-env-ref-type>
     *  </resource-env-ref>
     * 
     *  #Property values for sample references:
     *  jpa.cmt.entityManager: persistence/em
     *  jpa.cmt.transaction: persistence/tx
     *       
  • *
  • com.isomorphic.jpa.EMFProviderNoTransactions - transactions are * not used.
    * From the server.properties file this implementation reads the * jpa.persistenceUnitName property which must containt the name of persistence unit * configured in persistence.xml file. For example:
     *  jpa.persistenceUnitName: PERSISTENCE_UNIT_NAME
     *       
  • *
* You can provide your own implementation of * com.isomorphic.jpa.EMFProviderInterface if you have specific requirements for * transaction handling. *

* Transaction management: *

    *
  • Operating under {@link com.smartgwt.client.rpc.RPCManager} ({@link com.smartgwt.client.data.DSRequest} * has reference to * {@link com.smartgwt.client.rpc.RPCManager}):
      *
    • If participating in automatic transactions:
        *
      • retrieves existing transaction from {@link com.smartgwt.client.rpc.RPCManager} (if available);
      • *
      • starts new transaction (if not found in {@link com.smartgwt.client.rpc.RPCManager});
    • *
    • If one transaction per operation is used - starts new transaction;
    • *
    • Registers itself to DSRequest.registerCallback() for onSuccess()/ * onFailure() execution to commit/roll back transaction;
    • *
    • Sets DSRequest.setFreeOnExecute() to false to postpone releasing * of EntityManager avoiding lazy loading exceptions when creating JS response and * traversing through persistent object tree;
    • *
    • Registers itself to RPCManager.registerFreeResourcesHandler() for freeResources() * execution to release EntityManager.
  • *
  • Operating without {@link com.smartgwt.client.rpc.RPCManager}:
      *
    • starts new transaction;
    • *
    • commits/rolls back transaction and releases EntityManager if * DSRequest.setFreeOnExecute() is set to true (defalut);
    • *
    • relies on calling code to call onSuccess()/onFailure() to commit/roll back * transaction and to call freeResources() to release EntityManager.
      * Example code for data source operation execution with manual transaction handling: *
       *               DSRequest req = new DSRequest("myDS", "fetch");
       *               req.setFreeOnExecute(false);
       *               DSResponse resp = req.execute();
       *               List dataList = resp.getDataList();
       *               //... traverse through persistent object tree
       *               // Commit current transaction.
       *               ((JPADataSource) r.getDataSource()).onSuccess();
       *               // Release entity manager.
       *               ((JPADataSource) r.getDataSource()).freeResources(req);
       *           
    *
*

* JPA relations *

* JPA data sources transparently support JPA relations:

    *
  • To specify many-to-one relation you have to declare it in data source definition with property * {@link com.smartgwt.client.data.DataSourceField#getForeignKey foreignKey} pointing to releted data source's primary key: *
     *               <field name="country" foreignKey="countryManyToOne.countryId"/>
     *           
    * Client-side will recieve only ID of related entity while server-side will use real related entity loaded from data * base.

    * You can instruct data source to send encapsulated related entity by setting * {@link com.smartgwt.client.data.DataSourceField#getType type} property to the name of related data source: *

     *               <field name="country" type="countryManyToOne" foreignKey="countryManyToOne.countryId"/>
     *           
    *
  • *
  • To specify one-to-many relation you have to declare it in data source definition with property * {@link com.smartgwt.client.data.DataSourceField#getForeignKey foreignKey} pointing to releted data source's primary key * and * property {@link com.smartgwt.client.data.DataSourceField#getMultiple multiple} set to true: *
     *               <field name="cities" multiple="true" foreignKey="cityOneToMany.cityId"/>
     *           
    * Client-side will recieve only list of related ID's while server-side will use real related entity list loaded from * the database.

    * You can instruct the datasource to send a list of encapsulated related entities by setting * {@link com.smartgwt.client.data.DataSourceField#getType type} property to the name of related datasource: *

     *               <field name="cities" multiple="true" type="cityOneToMany" foreignKey="cityOneToMany.cityId"/>
     *           
    * Saving parent entity automatically makes all required JPA calls to synchronize the underlying list. *
  • *
* Notes on bidirectional relations:
    *
  • When the encapsulated related entity is sent to the client it will not have * a reference to the parent object (to avoid recursion).
  • *
  • When performing updates, make sure you update the entity that "owns" the relation. All * changes to "non-owning" relations are silently discarded.

*

Implementations are not thread-safe. Datasource acquiring mechanism ensures * that a single instance of this class will be used in one thread only. */ public interface JpaIntegration { }