Google App Engine (for Java) umożliwia uruchamianie aplikacji webowych na serwerach Google. Używając jednego konta można zarejestrować do 10 aplikacji, każda z nich może wykorzystywać do 1GB przestrzeni dyskowej, po 1GB transferu wychodzącego i przychodzącego oraz 6.5 godziny znormalizowanego 1) czasu procesora na dobę. I to wszystko za darmo. Całkiem nieźle, prawda? Jest jednak jedno ale: Google'owa maszyna wirtualna Javy i serwer aplikacji mają trochę ograniczeń, na które można trafić próbując uruchomić coś więcej niż "Hello World".
Nie wnikając w zbędne szczegóły: moja aplikacja miała rejestrować obiekty w bazie danych (za pośrednictwem JPA) oraz udostępniać je w postaci zserializowanej do XMLa. Trafiłem na kilka mniej lub bardziej poważnych problemów.
[1] Klasa utrwalana za pomocą JPA nie może być powiązana z kilkoma obiektami tego samego typu. W poniższej sytuacji:
@Entitydostaniemy wyjątek:
class A {
}
@Entity
class B {
@ManyToOne
A pole1;
@ManyToOne
A pole2;
}
Error in meta-data for B.pole2: Class B has multiple relationship fields of type A: pole1
and pole2. This is not yet supported.
[2] Nie jest obsługiwana strategia dziedziczenia SINGLE_TABLE. W przykładzie:
@Entitydostaniemy wyjątek:
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
class A {
}
@Entity
class B extends A {
}
Found inheritance strategy 'SINGLE_TABLE' on B. This strategy is not supported in this
context.
[3] Google App Engine dopuszcza jako identyfikatory obiektów typy Long, String oraz własny typ com.google.appengine.api.datastore.Key. Jednak gdy obiekt ma być powiązany z innym:
@Entityjego klucz nie może być typu Long. W powyższym przykładzie dostaniemy wyjątek:
class A {
@Id
Long id;
}
@Entity class B {
@ManyToOne
A a;
}
Cannot have a java.lang.Long primary key and be a child object
[4] Nie jest obsługiwane zachłanne wczytywanie powiązanych obiektów. Przy mapowaniu:
@Entityserwer zapisze do logu ostrzeżenie:
class A {
}
@Entity
class B {
@ManyToOne(fetch = FetchType.EAGER)
A a;
}
WARNING: Meta-data warning for B.a: The datastore does not support joins and thereforei zgodnie z jego treścią, obiekt powiązany trzeba będzie jawnie doczytać.
cannot honor requests to eagerly load related objects.
The field will be fetched lazily on first access.
[5] Niedostępna jest klasa sun.reflect.ReflectionFactory, która wbrew nazwie nie jest specyficzna dla Sunowskiej implementacji JVM (jest dostępna także w maszynach wirtualnych IBMa i Apple). Co prawda nie próbowałem jej używać bezpośrednio, ale pośrednie owszem. Próba wykorzystania biblioteki XStream do serializacji obiektów do XMLa kończy się wyjątkiem:
java.lang.NoClassDefFoundError: sun.reflect.ReflectionFactory is a restricted class.
[6] W niektórych przypadkach uprawnienia nie pozwalają na akcje, które w typowych maszynach wirtualnych są dopuszczalne. Przykładem może być dziedziczenie z klasy java.io.ObjectOutputStream (wykorzystywane np. przez Apache Wicket i XStream) - App Engine zgłasza wyjątek:
java.security.AccessControlException: access denied
(java.io.SerializablePermission enableSubclassImplementation)
(*)Znormalizowana jednostka zużycia mocy obliczeniowej jest - dość mgliście - określona jako wydajność 1.2 GHz procesora z serii x86 Intela.


