package com.smartgwt.client.docs; /** * <h3>Integration with JPA</h3> * 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 <code>com.isomorphic.jpa.JPADataSource</code>. * The implementation class for JPA 2.0 is <code>com.isomorphic.jpa.JPA2DataSource</code>. * Both implementations support search with simple {@link com.smartgwt.client.data.Criteria} and {@link * com.smartgwt.client.data.AdvancedCriteria}.</br> * JPA 1.0 and JPA 2.0 implementations use JPQL for data fetch. <b>Note:</b> MySQL DB - 'like' operator is used in a case * insensitive manner. Check * <a href="http://dev.mysql.com/doc/refman/5.5/en/case-sensitivity.html">MySQL Reference Manual :: C.5.5.1 Case * Sensitivity in String Searches</a> * for more information.<p/> * JPA 2.0 implementation uses Metadata API for data source generation from mapped entities. * <p/> * <b>JPA configuration</b> * <p/> * JPA configuration should be specified in the <code>persistence.xml</code> file and placed * in the <code>/WEB-INF/classes/META-INF</code> directory.<br/> For JPA 2.0 make sure you correctly * declare its usage in <code>persistence.xml</code>:<pre> * <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></pre><br/> * To use JPA annotated entities you have to * {@link com.smartgwt.client.docs.DataSourceDeclaration create a DataSource} with these properties<ul> * <li><b><code>{@link com.smartgwt.client.docs.serverds.DataSource#serverConstructor serverConstructor}</code></b> - * either JPA 1.0 * DataSource implementation: <code>com.isomorphic.jpa.JPADataSource</code> or JPA 2.0 * implementation: <code>com.isomorphic.jpa.JPA2DataSource</code></li>. * <li><b><code>{@link com.smartgwt.client.docs.serverds.DataSource#beanClassName beanClassName}</code></b> - fully * qualified * class name of JPA entity</li></ul> * For example:<pre> * <DataSource * ID="countryDS" * serverConstructor="com.isomorphic.jpa.JPA2DataSource" * beanClassName="com.smartgwt.sample.showcase.server.jpa.Country" * > * <fields> * <!-- ... Fields definition ... --> * </fields> * </DataSource> * </pre> * Supports field definitions with <code>{@link com.smartgwt.client.data.DataSourceField#getValueXPath valueXPath}</code> * settings. * Entity property is accessed (by priority):<ol> * <li><code>{@link com.smartgwt.client.data.DataSourceField#getValueXPath valueXPath}</code> - supports only simple XPath * definitions: * "property/subProperty/subSubProperty"</li> * <li><code>{@link com.smartgwt.client.data.DataSourceField#getName name}</code> - most often used when data source field * name * is the same as entity property name</li></ol> * <p/> * <b>JPA transactions</b> * <p/> * JPA provides three mechanisms for transactions: for JEE applications JPA provides integration * with JTA (Bean Managed Transactions and Container Managed Transactions); for JSE applications JPA has a native * <code>EntityTransaction</code> implementation (Locally Managed Transactions). * The transaction mechanism should be configured in the <code>server.properties</code> file by setting * property <b><code>jpa.emfProvider</code></b> to the fully qualified class name of the provider * (implementation of <code>com.isomorphic.jpa.EMFProviderInterface</code>). Smart GWT comes * with three implementations:<ul> * <li><b><code>com.isomorphic.jpa.EMFProviderLMT</code></b> - for Locally Managed Transactions. * Every fetch or DML operation starts a new transaction and commits after successful * execution.<br/> * This implementation reads the <b><code>jpa.persistenceUnitName</code></b> property from * the <code>server.properties</code> file. The value of this property needs to be set to * the name of the persistence unit configured in <code>persistence.xml</code> file. For example:<pre> * jpa.persistenceUnitName: PERSISTENCE_UNIT_NAME * </pre></li> * <li><b><code>com.isomorphic.jpa.EMFProviderBMT</code></b> - for Bean Managed Transactions. * Every fetch or DML operation acquires the transaction object from the container and starts it.<br/> * This implementation reads two properties from the <code>server.properties</code> file: * <b><code>jpa.entityManager</code></b> and <b><code>jpa.entityManagerFactory</code></b> * containing appropriate resource name references configured in * <code>/WEB-INF/web.xml</code>. Configuration example:<pre> * <!-- 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> * * <!-- EntityManagerFactory resource reference name declaration --> * <persistence-unit-ref> * <persistence-unit-ref-name>persistence/emf</persistence-unit-ref-name> * <persistence-unit-name>PERSISTENCE_UNIT_NAME</persistence-unit-name> * </persistence-unit-ref> * * #Property values for sample references: * jpa.entityManager: persistence/em * jpa.entityManagerFactory: persistence/emf * </pre></li> * <li><b><code>com.isomorphic.jpa.EMFProviderCMT</code></b> - 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 <code>tx.setRollbackOnly()</code> is used to notify container to rollback the * transaction.<br/> * This implementation reads two properties from the <code>server.properties</code> file: * <b><code>jpa.entityManager</code></b> and <b><code>jpa.entityManagerFactory</code></b> * containing appropriate resource name references configured in * <code>/META-INF/ejb-jar.xml</code>. Configuration example:<pre> * <?xml version="1.0" encoding="UTF-8"?> * <ejb-jar * version = "3.0" * xmlns = "http://java.sun.com/xml/ns/javaee" * xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" * xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"> * <enterprise-beans> * <session> * <ejb-name>TestEJB</ejb-name> * <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> * <persistence-unit-ref> * <persistence-unit-ref-name>persistence/emf</persistence-unit-ref-name> * <persistence-unit-name>PERSISTENCE_UNIT_NAME</persistence-unit-name> * </persistence-unit-ref> * </session> * </enterprise-beans> * </ejb-jar> * * #Property values for sample references: * jpa.entityManager: persistence/em * jpa.entityManagerFactory: persistence/emf * </pre></li> * <li><b><code>com.isomorphic.jpa.EMFProviderNoTransactions</code></b> - transactions are * not used.<br/> * From the <code>server.properties</code> file this implementation reads the * <b><code>jpa.persistenceUnitName</code></b> property which must containt the name of persistence unit * configured in <code>persistence.xml</code> file. For example:<pre> * jpa.persistenceUnitName: PERSISTENCE_UNIT_NAME * </pre></li> * </ul> * You can set <b><code>jpa.emfProvider</code></b> to your own implementation of * <code>com.isomorphic.jpa.EMFProviderInterface</code> if you have specific requirements for * transaction handling. <code>EMF</code> will instantiate provided implementation on initialization (static) and * will use same instance every time. By using own implementation you can have complete control over creating/using * <code>EntityManagerFactory</code> and <code>EntityManager</code> instances. For example: you can create * <code>EMFProviderSpring</code> which will look-up <code>EntityManagerFactory</code> and <code>EntityManager</code> * instances in Spring and will feed it to <code>JPADataSource</code>.<p/> * <b>Additional configurations:</b><p/> * In case you have several persistence units defined in your <code>persistence.xml</code> you can have additional * configurations in <code>server.properties</code> file. Additional configurations * (prefixed with <b><code>jpa.</code></b>) should have name, <b><code>emfProvider</code></b> property and other * properties required by specified EMF provider implementation. * For example:<pre> * jpa.configName.emfProvider: com.isomorphic.jpa.EMFProviderLMT * jpa.configName.persistenceUnitName: ANOTHER_PERSISTENCE_UNIT_NAME</pre> * To use additional JPA configuration you have to set <b><code>jpaConfig</code></b> property in data source * definition:<pre> * <DataSource * ID="countryDS" * serverConstructor="com.isomorphic.jpa.JPA2DataSource" * beanClassName="com.smartgwt.sample.showcase.server.jpa.Country" * jpaConfig="configName" * ></pre> * <b>Transaction management:</b> * <p/><ul> * <li>Operating under {@link com.smartgwt.client.rpc.RPCManager} (<code>{@link com.smartgwt.client.data.DSRequest}</code> * has reference to * <code>{@link com.smartgwt.client.rpc.RPCManager}</code>):<ul> * <li>If participating in automatic transactions:<ul> * <li>retrieves existing transaction from <code>{@link com.smartgwt.client.rpc.RPCManager}</code> (if available);</li> * <li>starts new transaction (if not found in <code>{@link com.smartgwt.client.rpc.RPCManager}</code>);</li></ul></li> * <li>If one transaction per operation is used - starts new transaction;</li> * <li>Registers itself to <code>DSRequest.registerCallback()</code> for <code>onSuccess()</code>/ * <code>onFailure()</code> execution to commit/roll back transaction;</li> * <li>Sets <code>DSRequest.setFreeOnExecute()</code> to <code>false</code> to postpone releasing * of <code>EntityManager</code> avoiding lazy loading exceptions when creating JS response and * traversing through persistent object tree;</li> * <li>Registers itself to <code>RPCManager.registerFreeResourcesHandler()</code> for <code>freeResources()</code> * execution to release <code>EntityManager</code>.</li></ul><br/> * If you want to use same <code>EntityManager</code> and transaction in your custom data source implementation you can * acquire it by <pre>JPAConnectionHolder holder = DataSource.getTransactionObject(req, EMF.TRANSACTION_ATTR);</pre> * <code>JPAConnectionHolder</code> instance contains references to entity manager and transaction object * used by <code>JPADataSource</code>. You should never commit/rollback automatic transaction. * Overall commit/rollback will be issued by <code>RPCManager</code> and will be handled by <code>JPADataSource</code> * object which started transaction. * </li> * <li>Operating without {@link com.smartgwt.client.rpc.RPCManager}:<ul> * <li>starts new transaction;</li> * <li>commits/rolls back transaction and releases <code>EntityManager</code> if * <code>DSRequest.setFreeOnExecute()</code> is set to <code>true</code> (defalut);</li> * <li>relies on calling code to call <code>onSuccess()</code>/<code>onFailure()</code> to commit/roll back * transaction and to call <code>freeResources()</code> to release <code>EntityManager</code>.<br/> * Example code for data source operation execution with manual transaction handling: * <pre> * 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); * </pre></li></ul> * </li></ul> * <p/> * <b>JPA relations</b> * <p/> * JPA data sources transparently support JPA relations:<ul> * <li>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: * <pre> * <field name="country" foreignKey="countryManyToOne.countryId"/> * </pre> * Client-side will recieve only ID of related entity while server-side will use real related entity loaded from data * base.<p/> * 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: * <pre> * <field name="country" type="countryManyToOne" foreignKey="countryManyToOne.countryId"/> * </pre> * </li> * <li>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 <code>true<code>: * <pre> * <field name="cities" multiple="true" foreignKey="cityOneToMany.cityId"/> * </pre> * Client-side will recieve only list of related ID's while server-side will use real related entity list loaded from * the database.<p/> * 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: * <pre> * <field name="cities" multiple="true" type="cityOneToMany" foreignKey="cityOneToMany.cityId"/> * </pre> * Saving parent entity automatically makes all required JPA calls to synchronize the underlying list. * </li> * </ul> * <b>Notes on bidirectional relations</b>:<ul> * <li>When the encapsulated related entity is sent to the client it will not have * a reference to the parent object (to avoid recursion).</li> * <li>When performing updates, make sure you update the entity that "owns" the relation. All * changes to "non-owning" relations are silently discarded.</li></ul><p/> * </p><strong>Implementations are not thread-safe. Datasource acquiring mechanism ensures * that a single instance of this class will be used in one thread only.</strong> */ public interface JpaIntegration { }