com.smartgwt.client.docs

## Interface GaeIntegration

-     public interface GaeIntegration

  ### Google Application Engine (GAE)

  GAE supports Java applications. 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 BigTable. To simplify development, Google has adopted DataNucleus Access Platform to provide JPA 1.0 support. Because GAE datastore is not a relational database some JPA features are not supported by this JPA implementation.

  Setting up Smart GWT application for GAE

  Under the `/WEB-INF` directory you have to create a file named `appengine-web.xml` which will hold Google's specific settings.
  One important thing to note: static and dynamic contents will be served from different servers. There are special sections in `appengine-web.xml` 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:

        <?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>

  To interact with DataSources an additional servlet mapping has to be added to `web.xml`:

        <servlet-mapping>
            <servlet-name>IDACall</servlet-name>
            <url-pattern>/[MODULE_NAME]/sc/IDACall</url-pattern>
        </servlet-mapping>

  Setting up DataSources

  GAE supports only four types as primary keys:
  - `java.lang.Long`
  - `java.lang.String`
  - `java.lang.String` with additional annotations
  - `com.google.appengine.api.datastore.Key` not supported by Smart GWT
  Primary key can not be altered after entity is saved.
  Entities with primary keys `Long` or `String` can not participate in transactions and can not be used in relations. Here is an example how to declare primary key of type `String` with additional annotations:

        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;
        }

  DataSource creation is similar to `standard JPA` with one difference: property ``serverConstructor`` should be set to `com.isomorphic.jpa.GAEJPADataSource`.
  Because of GAE queries limitations this DataSource implementation supports only single inequality criteria in filter.
  Only `TextMatchStyle.STARTS_WITH` filtering mode is supported for text fields.
  All queries are case sensitive because GAE does not support `upper()/lower()` functions in criterias.
  `TextMatchStyle.EXACT` is used for all number fields.
  `com.isomorphic.jpa.EMFProviderLMT` or `com.isomorphic.jpa.EMFProviderNoTransactions` should be used as transaction providers (depending whether you use transactions or not).
  To participate in a transaction, entities have to belong to the same group.
  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).

  Relationships

  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::

        ClassA has reference to ClassB,
        ClassB has reference to ClassC

  But it is impossible to have an entity referencing two other entities:

        ClassD has reference to ClassE,
        ClassD has reference to ClassF

  There are no foreign keys - the actual reference is encoded into the primary key of child entity.
  GAE datastore does not support many-to-many relationships.
  Unidirectional one-to-many relationships work only if the parent has a declaration of `List<ChildEntityClass>`.
  Unidirectional relationships do not work if only the child entity has reference to the parent.
  Bidirectional relationship example:

        @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 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;
        //....
        }

  Note: GAE does not support `FetchType.EAGER`.

  With Unowned Relationships (when you save parent's primary key as simple child's property) you can model unsupported relationships. But this approach has drawbacks:
  - related entities are not instantiated automatically
  - transactions can not be used
  - you have to manually keep track of changes in case of bidirectional relationship