Dienstag, 29. Dezember 2009

Grails App Engine Ant-Macro Exception

Die DataNucleus EnhancerTask der App Engine macht mir in meinen Grails Projekten relativ häufig Probleme. Das ganze sieht so aus, dass ich beim kompilieren der sourcen auf folgende Fehlermeldung stoße:

C:\Programmier-Tools\appengine-java-sdk-1.3.0\config\user\ant-macros.xml:95: java.io.IOException: Cannot run program "C:\Program Files\Java\jdk1.6.0_14\jre\bin\java.exe": CreateProcess error=87, Falscher Parameter
gant.TargetExecutionException: : The following error occurred while executing this line:
C:\Programmier-Tools\appengine-java-sdk-1.3.0\config\user\ant-macros.xml:95: java.io.IOException: Cannot run program "C:\Program Files\Java\jdk1.6.0_14\jre\bin\java.exe": CreateProcess error=87, Falscher Parameter
...
...
...
Caused by: C:\Programmier-Tools\appengine-java-sdk-1.3.0\config\user\ant-macros.xml:95: java.io.IOException: Cannot run program "C:\Program Files\Java\jdk1.6.0_14\jre\bin\java.exe": CreateProcess error=87, Falscher Parameter
at org.apache.tools.ant.taskdefs.Java.fork(Java.java:774)
at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:194)
at org.apache.tools.ant.taskdefs.Java.execute(Java.java:104)
at com.google.appengine.tools.enhancer.EnhancerTask.execute(EnhancerTask.java:99)
...
...
...

Diesen Fehler kann man beheben, wenn man in der ant-marcos.xml, die sich im $APPENGINE_HOME$/config/user Verzeichnis befindet, eine Anpassung in der macrodef "enhance_war" vornimmt. Diese beginnt (in der Version 1.3.0) in der Zeile 90.
In der macrodef wird folgendes fileset definiert (Z.102):

<fileset dir="@{war}/WEB-INF/classes" includes="**/*.class"/>

Wenn wir dieses fileset auf die Klassen für unsere Anwendung einschränken, dann taucht die Fehlermeldung nichtmehr auf und das kompilieren und enhancen der Domain Klassen läuft wieder durch.

Liegen die Klassen unserer Anwendung also in einem Package de.myproject, dann sieht das fileset folgendermaßen aus:

<fileset dir="@{war}/WEB-INF/classes/de/myproject" includes="**/*.class"/>

Achtung: Nicht vergessen diese Zeile bei einer neuen Version des App-Engine SDKs wieder anzupassen!

Montag, 7. September 2009

Update der App Engine Version innerhalb eines Grails Projekts

Da ja in regelmäßigen, recht kurzen Abständen immer mal wieder eine neue App Engine Version zum download bereit steht, empfiehlt es sich auch auf seinem Entwicklungsrechner immer die entsprechende Version zu haben.

Allerdings ist es mit neuer Version runterladen und den Pfad zum APPENGINE_HOME anpassen nicht unbedingt getan, denn mein Grails Projekt wollte sich danach mit folgender begründung nichtmehr starten lassen:

\appengine-java-sdk-1.2.5\config\user\ant-macros.xml:94: Java returned: 1
at gant.Gant$_dispatch_closure4.doCall(Gant.groovy:331)
at gant.Gant$_dispatch_closure6.doCall(Gant.groovy:334)
at gant.Gant$_dispatch_closure6.doCall(Gant.groovy)
at gant.Gant.withBuildListeners(Gant.groovy:344)
at gant.Gant.this$2$withBuildListeners(Gant.groovy)
at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
at gant.Gant.dispatch(Gant.groovy:334)
at gant.Gant.this$2$dispatch(Gant.groovy)
at gant.Gant.invokeMethod(Gant.groovy)
at gant.Gant.processTargets(Gant.groovy:495)
at gant.Gant.processTargets(Gant.groovy:480)
at grails.util.GrailsMain.run(GrailsMain.groovy:31)
at grails.util.GrailsMain.main(GrailsMain.groovy)
Error executing script AppEngine: No such property: appEngineSDK for class:
AppEngine
gant.TargetMissingPropertyException: No such property: appEngineSDK for
class: AppEngine
at gant.Gant$_dispatch_closure4.doCall(Gant.groovy:329)

und noch vieles mehr...

Ein clean in Eclipse hat nicht ausgereicht und das Löschen des classes und stage Ordners in ../.grails/1.1.1/projects/myproject hat auch nix gebracht.
Erst als ich den gesamten Ordner einmal gelöscht hatte und das App-Engine Plugin nochmal neu im Projekt installiert habe wollte es auch mit dem neuen App Engine SDK starten.

Montag, 3. August 2009

Grails App Engine auf Eclipse starten

Die Vorbereitungen sind abgeschlossen:
Auf der Grails Plugin Seite ist beschrieben, wie man seine erste App Engine Applikation erstellt.

Dabei ergaben sich bei mir folgende Fehler:

  1. Beim deployen der Applikation mit grails app-engine deploy hatte ich manchmal Probleme bei der Nutzername/Passwort Eingabe, ausserdem ists eh nicht schön jedes Mal die Daten wieder und wieder einzugeben.
  2. Bei Versuch die App-Engine aus Eclipse heraus zu starten (debug oder run Configuration) erscheint die Fehlermeldung 'grails run-app' is not supported with AppEngine.
  3. Einmal die App Engine gestartet, lässt sich die AppEngine nichtmehr stoppen, ausser gewaltsam über den Taskmanager
Ersteres Problem lässt sich dadurch lösen, dass in der Config.groovy die entsprechenden Daten eingetragen werden. Über die keys google.appengine.email und google.appengine.password können die Werte festgesetzt werden.

Um das zweite Problem gleich mit zu lösen hab ich diese Datei in mein Projektordner mit dem eigentlichen Projekt in das Verzeichnis projektname\scripts kopiert und in RunApp.groovy umbenannt. Jetzt fragt Eclipse immer welche RunApp beim Starten der Applikation verwendet werden soll und man kann die aus dem Projektverzeichnis wählen, hinter der sich eigentlich die AppEngine.groovy verbirgt.

Zum Dritten hab ich noch nichts sinnvolles gefunden... auch beim Starten und vor allem Stoppen aus Eclipse raus bleibt noch ein Java-Prozess über, den man abschießen muss. Auch scheint das Debuggen der Applikation mit Eclipse nicht möglich. Dazu soll wohl NetBeans in der Version 6.7 besser sein Link

Objekte in der Google Database suchen

Mit der Google App Engine erhält man Zugang zu der skalierbaren Infrastruktur von Google.
Um diese Skalierbarkeit effektiv auszunutzen, gibt es von Jason Cooper eine Reihe von Artikel über dieses Thema mit dem Titel: "Effectively scaling your App Engine-based apps"
Die orginal Artikel sind unter: Scaling zu finden.

Hier eine Zusammenfassung der Artikel mit einigen Erläuterungen dazu.

Direct lookups vs. Querys

Zusammenfassung:
Direct lookups statt Querys benutzen sofern möglich!

pm.getObjectById(Klasse.class,
key) statt
Query q = pm.newQuery(Klasse.class);
q.setFilter("key == mykey")
q.declareParameters("
com.google.appengine.api.datastore.Key key")
q.execute(mykey);

Der Googe App Engine Datastore ist für Lesezugriffe optimiert. Auf der System Status Seite von Google (unter Datastore) lässt sich nachschaun, dass
Querys im Vergleich direct lookups (get) zu eine deutlich höhere (~4x) Latenz haben.
Für die Umsetzung in Java bedeutet dies, dass die getObjectById Methode des PersistenceManager ausgerufen wird, statt newQuery. Dies geht natürlich nur, wenn auch die ID des Objects bekannt ist.

Fortsetzung folgt...



Google App Engine

Da ich mich seit kurzem mit der Google App Engine beschäftige, habe ich beschlossen einen Blog aufzumachen, in dem ich über meine Erfahrungen damit berichte.

Ich werd über Konfigurationsprobleme, Programmiertipps und sonstwas berichten, nicht zuletzt um selbst eine Art FAQ zu bekommen, in dem ich nochmal nachschlagen kann.

Da ich mit Grails vertraut bin, wird mein ersten Projekt auch mit Gails 1.1.1 umgesetzt, wofür es auch schon ein entsprechendes Plugin gibt. App-Engine Plugin

Als Entwicklungsumgebung kommt Eclipse 3.5 zum Einsatz