package com.smartgwt.client.docs;
/**
* <h3>Google Application Engine (GAE)</h3>
* <a href='http://code.google.com/appengine/' onclick="window.open('http://code.google.com/appengine/');return
* false;">GAE</a> supports
* <a href='http://code.google.com/appengine/docs/java/overview.html'
* onclick="window.open('http://code.google.com/appengine/docs/java/overview.html');return false;">Java applications</a>.
* Google provides a great infrastructure for web applications. It takes care of many web
* application developer's headaches: hardware, operating system support, backups, scaling,
* security, mail etc. To run under GAE your application has to comply to GAE rules.
* The biggest difference is GAE datastore - it is not a relational database - instead they use
* something called <a href='http://en.wikipedia.org/wiki/BigTable'
* onclick="window.open('http://en.wikipedia.org/wiki/BigTable');return false;">BigTable</a>. To simplify development,
* Google has adopted
* <a href='http://www.datanucleus.org/products/accessplatform/'
* onclick="window.open('http://www.datanucleus.org/products/accessplatform/');return false;">DataNucleus Access
* Platform</a>
* to provide
* <a href='http://code.google.com/appengine/docs/java/datastore/usingjpa.html'
* onclick="window.open('http://code.google.com/appengine/docs/java/datastore/usingjpa.html');return false;">JPA 1.0
* support</a>.
* Because GAE datastore is not a relational database
* <a href='http://code.google.com/appengine/docs/java/datastore/usingjpa.html#Unsupported_Features_of_JPA'
* onclick="window.open('http://code.google.com/appengine/docs/java/datastore/usingjpa.html#Unsupported_Features_of_JPA');return
* false;">some JPA features</a>
* are not supported by this JPA implementation.
* <p/>
* <b>Setting up Smart GWT application for GAE</b>
* <p/>
* Under the <code>/WEB-INF</code> directory you have to create a file named
* <a href='http://code.google.com/appengine/docs/java/config/appconfig.html'
* onclick="window.open('http://code.google.com/appengine/docs/java/config/appconfig.html');return
* false;"><code>appengine-web.xml</code></a>
* which will hold Google's specific settings.<br/>
* One important thing to note: static and dynamic contents will be served from different servers.
* There are
* <a href='http://code.google.com/appengine/docs/java/config/appconfig.html#Static_Files_and_Resource_Files'
* onclick="window.open('http://code.google.com/appengine/docs/java/config/appconfig.html#Static_Files_and_Resource_Files');return
* false;">special sections</a>
* in
* <a href='http://code.google.com/appengine/docs/java/config/appconfig.html'
* onclick="window.open('http://code.google.com/appengine/docs/java/config/appconfig.html');return
* false;"><code>appengine-web.xml</code></a>
* specifying static and dynamic resources. All resources are duplicated if not specified.
* A single GAE application is limited to 3000 files. A typical Smart GWT application consists of many
* resources and it exceeds the limit when duplicated (even with a single theme).
* To run a Smart GWT application we have to split resources. Here is an example configuration:<pre>
* <?xml version="1.0" encoding="UTF-8"?>
* <appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
* <application>GAE_APPLICATION_NAME</application>
* <version>1</version>
* <static-files>
* <include path="/index.jsp"/>
* <include path="/[MODULE_NAME]/**"/>
* <exclude path="/[MODULE_NAME]/**.xml"/>
* <exclude path="/[MODULE_NAME]/**.xsl"/>
* <exclude path="/[MODULE_NAME]/**.wsdl"/>
* </static-files>
* <resource-files>
* <include path="/[PATH_TO_DATA_SOURCE_FILES]/**"/>
* <include path="/[MODULE_NAME]/**.xml"/>
* <include path="/[MODULE_NAME]/**.xsl"/>
* <include path="/[MODULE_NAME]/**.wsdl"/>
* </resource-files>
* </appengine-web-app>
* </pre>
* To interact with DataSources an additional servlet mapping has to be added to
* <code>web.xml</code>:<pre>
* <servlet-mapping>
* <servlet-name>IDACall</servlet-name>
* <url-pattern>/[MODULE_NAME]/sc/IDACall</url-pattern>
* </servlet-mapping>
* </pre>
* <p/>
* <b>Setting up DataSources</b>
* <p/>
* GAE supports only four types as primary keys:<ul>
* <li><code>java.lang.Long</code></li>
* <li><code>java.lang.String</code></li>
* <li><code>java.lang.String</code> with additional annotations</li>
* <li><code>com.google.appengine.api.datastore.Key</code> <b>not supported by Smart GWT</b></li>
* </ul>
* Primary key can not be altered after entity is saved.<br/>
* Entities with primary keys <code>Long</code> or <code>String</code> can not participate in
* transactions and can not be used in relations.
* Here is an example how to declare primary key of type <code>String</code> with additional
* annotations:<pre>
* import java.io.Serializable;
* import javax.persistence.Entity;
* import javax.persistence.GeneratedValue;
* import javax.persistence.GenerationType;
* import javax.persistence.Id;
* import org.datanucleus.jpa.annotations.Extension;
*
* @Entity
* public class Bar
* implements Serializable
* {
* @Id
* @GeneratedValue (strategy = GenerationType.IDENTITY)
* @Extension (vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
* private String id;
* }
* </pre>
* DataSource creation is similar to {@link com.smartgwt.client.docs.JpaIntegration standard JPA} with one
* difference: property <b><code>{@link com.smartgwt.client.docs.serverds.DataSource#serverConstructor
* serverConstructor}</code></b>
* should be set to <b><code>com.isomorphic.jpa.GAEJPADataSource</code></b>.<br/>
* Because of
* <a href='http://code.google.com/intl/en/appengine/docs/java/datastore/queriesandindexes.html#Restrictions_on_Queries'
* onclick="window.open('http://code.google.com/intl/en/appengine/docs/java/datastore/queriesandindexes.html#Restrictions_on_Queries');return
* false;">GAE queries limitations</a>
* this DataSource implementation supports only single inequality criteria in filter.<br/>
* Only <code>TextMatchStyle.STARTS_WITH</code> filtering mode is supported for text fields.<br/>
* All queries are case sensitive because GAE does not support <code>upper()/lower()</code> functions in criterias.<br/>
* <code>TextMatchStyle.EXACT</code> is used for all number fields.<br/>
* <b><code>com.isomorphic.jpa.EMFProviderLMT</code></b> or
* <b><code>com.isomorphic.jpa.EMFProviderNoTransactions</code></b> should be used as
* transaction providers (depending whether you use transactions or not).<br/>
* To participate in a transaction, entities have
* to belong to the
* <a href='http://code.google.com/intl/en/appengine/docs/java/datastore/transactions.html'
* onclick="window.open('http://code.google.com/intl/en/appengine/docs/java/datastore/transactions.html');return
* false;">same group</a>.<br/>
* Note: entities of different type can not participate in a transaction even if these
* entities have GAE specific primary key (you can not even fetch (SELECT) entities belonging
* to different groups).
* <p/>
* <b><a href='http://code.google.com/intl/en/appengine/docs/java/datastore/relationships.html'
* onclick="window.open('http://code.google.com/intl/en/appengine/docs/java/datastore/relationships.html');return
* false;">Relationships</a></b>
* <p/>
* Entities are grouped by establishing owned relationships (where dependent entities are
* instantiated automatically by the JPA provider) between them. Entities in groups can form a
* chain of the following sort::<pre>
* ClassA has reference to ClassB,
* ClassB has reference to ClassC
* </pre>
* But it is impossible to have an entity referencing two other entities:<pre>
* ClassD has reference to ClassE,
* ClassD has reference to ClassF
* </pre>
* There are no foreign keys - the actual reference is encoded into the primary key of child entity.<br/>
* GAE datastore does not support many-to-many relationships.<br/>
* Unidirectional one-to-many relationships work only if the parent has a declaration of
* <code>List<ChildEntityClass></code>.<br/>
* Unidirectional relationships do not work if only the child entity has reference to the parent.<br/>
* Bidirectional relationship example:<pre>
* @Entity
* public class Country
* implements Serializable
* {
* @Id
* @Column (nullable = false)
* @GeneratedValue (strategy = GenerationType.IDENTITY)
* @Extension (vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
* private String countryId;
*
* @OneToMany
* private List<City> cities;
* //....
* }
*
* @Entity
* public class City
* implements Serializable
* {
* @Id
* @Column (nullable = false)
* @GeneratedValue (strategy = GenerationType.IDENTITY)
* @Extension (vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
* private String cityId;
*
* // This is fake column - it is calculated by provider and is not saved.
* // Actual reference to parent entity is encoded in primary key.
* @Column (nullable = false)
* @Extension (vendorName = "datanucleus", key = "gae.parent-pk", value = "true")
* private String countryId;
*
* @ManyToOne (fetch=FetchType.LAZY)
* private Country country;
* //....
* }
* </pre>
* Note: GAE does not support <code>FetchType.EAGER</code>.
* <p/> With
* <b><a href='http://code.google.com/intl/en/appengine/docs/java/datastore/relationships.html#Unowned_Relationships'
* onclick="window.open('http://code.google.com/intl/en/appengine/docs/java/datastore/relationships.html#Unowned_Relationships');return
* false;">Unowned Relationships</a></b>
* (when you save parent's primary key as simple child's property) you can model unsupported
* relationships. But this approach has drawbacks:<ul>
* <li>related entities are not instantiated automatically</li>
* <li>transactions can not be used</li>
* <li>you have to manually keep track of changes in case of bidirectional relationship</li>
* </ul>
*/
public interface GaeIntegration {
}