Suche
Power Tools Woche

Gaelyk: Ein Toolkit für Google App Engine

Sven Haiges

Was wäre ein Entwickler ohne seine Tools? Die nützlichen kleinen Helferlein erleichtern unser Leben von Tag zu Tag, ersparen uns Zeit und Aufwand. Und weil Tools so nützlich sind, möchten wir Ihnen in unserer Power Tools Woche jeden Tag ein anderes vorstellen. Den Anfang macht Gaelyk.

Mit Googles App Engine können Java-Web-Applikationen in der Google Cloud betrieben werden. App Engine verspricht dabei, die Applikation bei steigendem Traffic automatisch zu skalieren. Für Entwickler ist App Engine aber auch deshalb so interessant, weil zahlreiche Services wie Memcache, Task Queues oder E-Mail out of the Box zur Verfügung gestellt werden und die Nutzung in einem bestimmten Rahmen sogar kostenlos ist. Gaelyk ist ein speziell für App Engine entwickeltes Toolkit zur Webentwicklung und vereinfacht die Nutzung der vielen App Engine Services. App Engine, Gaelyk und die Groovy-Skriptsprache sind ein traumhaftes Team. Dieser Artikel stellt Ihnen einige dieser Gaelyk-Features kurz vor.

Aller Anfang ist schwer – nicht so bei Gaelyk [1]. Vom Java SDK abgesehen, müssen Sie lediglich das Gaelyk Template Project herunterladen, entpacken und haben direkt ein lauffähiges Beispielprojekt vor sich liegen. Dieses Projekt kann nicht viel, aber Sie müssen sich keine Gedanken um die Projektstruktur mehr machen, und ein paar Beispiele zur Umsetzung von MVC sind ebenso klar ersichtlich. Ich ziehe es vor, mit Gaelyk-Projekten direkt in TextMate [2], einem Texteditor für den Mac, zu arbeiten. Auf Wunsch können Sie aber per gradlew cleanEclipse eclipse auch die notwendigen Projektdateien für Eclipse generieren. Um den App Engine (Jetty-)Server lokal zu starten, benutzen Sie ./gradlew gaeRun und haben die Webapplikation dann auf localhost:8080 laufen. Änderungen an den meisten Artefakten wie Controllern sind sofort live, in manchen Fällen muss der lokale Server gestoppt und neu gestartet werden (beispielsweise, wenn neue Groovy-/Java-Klassen hinzukommen). Sobald Sie Ihre App in die Google Cloud deployen wollen, tippen Sie auf der Kommandozeile einfach ./gradlew gaeUpload ein. Sekunden später ist Ihre App unter der von Ihnen reservierten <app-name>.appspot.com-Adresse verfügbar. Die Konfigurationsdateien, die Sie sich mehr oder wenig gründlich anschauen und verstehen sollten, sind:

  • build.gradle: Hier wird der Build per Gradle konfiguriert. Sobald neue Versionen (von Gaelyk, App Engine oder Groovy) verfügbar sind, können Sie hier einfach die Versionsnummern ändern.
  • im war/WEB-INF-Verzeichnis befinden sich die web.xml und appengine-web.xml-Dateien. Erstere sollte bekannt sein, die appengine-web.xml-Datei enthält die App-Engine-spezifischen Einstellungen.
  • Ebenso im war/WEB-INF-Verzeichnis befindet sich die routes.groovy-Datei. Hier wird das URL-Routing-System konfiguriert: welches Groovy-Script (=Controller) welche eingehende Anfrage behandelt.
Controller und URL Routing per routes.groovy

Alle Groovy-Skripte, die die Controller darstellen, befinden sich im web/WEB-INF/groovy-Verzeichnis. Das Routing wird in routes.groovy konfiguriert und ist einfach aufgebaut, aber sehr mächtig:

  1. get „/“, forward: „/WEB-INF/pages/index.gtpl“, cache: 10.minutes
  2. get „/api/v1/products“, forward: „/v1/products.groovy“
  3. post „/api/v1/customers“, forward: „/v1/customers.groovy“
  4. put „/api/v1/customers/@id“, forward: /v1/customers.groovy?id=@id

Nummer eins verknüpft den Root-URL „/|“ der Webapplikation mit der Template-Datei index.gtpl. Ebenso wird die Response für zehn Minuten gecacht, was technisch über den Memcache-Service von App-Engine realisiert wird. Gaelyk-Template-Dateien sind JSPs recht ähnlich und können Code in Form von <% /* code */ %> enthalten. Die Methoden print und println werden direkt an den PrintWriter weitergeleitet, und die GString- (Groovy-String-)Notation ${variable} kann verwendet werden, um Variablen direkt in das Markup auszugeben. Letztere Notation bringt leider auch ein paar Probleme mit sich, da direkt in HTML eingebetteter JQuery-Code ebenso Ausdrücke wie $ (‚#content‘) verwendet. Der JavaScript-Code muss daher in separate Dateien ausgelagert werden, was jedoch ohnehin für die Struktur des Projekts gut ist.

Nummer zwei verknüpft GET api/v1/products mit dem Groovy Script products.groovy, das den Controller darstellt. Der Controller kann dank zahlreicher Shortcuts (Tabelle 1) auf die App Engine Services zugreifen. Entweder erstellt der Controller die Response selbst und schreibt die Daten direkt in den Outputstream (out << ‚Hello World‘) , oder er leitet per Forward an ein Template weiter (forward ‚/WEB-INF/pages/page.gtpl‘) .

Nummer drei zeigt, wie einfach unterschiedliche HTTP-Verben in Ihrem ULR Routing verwendet werden können. Nummer vier zeigt schließlich, wie auch Features wie Pfadvariablen sehr einfach durch die @-Notation umgesetzt werden können.

App Engine on Steroids – die Shortcuts

Die so genannten Gaelyk Shortcuts machen die Arbeit mit den Google App Engine Services noch einfacher. Für fast jeden Service gibt es entsprechende Unterstützung von Gaelyk, wodurch manch langwierige Formulierung in Java dank der Nutzung von Groovy und Gaelyk-Shortcuts auf wenige Zeilen herunterschmilzt. Die folgende Tabelle gibt einen kurzen Überblick.

Tabelle 1: So macht Gaelyk Ihnen das Leben einfacher: die Shortcuts für Google App Engine. Diese Beispiele stammen in weiten Teilen aus dem Gaelyk Tutorial [3]

App Engine Service Gaelyk Shortcut
datastore Es gibt zahlreiche nützliche Features, die besonders das Arbeiten mit dem low-level Datastore vereinfachen. Entities können einfach geladen, erzeugt, aktualisiert und gelöscht werden. Ebenso werden eine einfache Art des OR-Mappings sowie eine DSL für Queries angeboten.

def storeKey = [„Store“, „mystore“] as Key

storeKey.delete()

def store = new Entity(„Store“, „mystore“)

store[‚link‘] = ‚http://hybris.com‚ as Link

store[‚description‘] = ’some desc‘

store.save()

task queue Die Default Queue kann am einfachsten per Variable defaultQueue angesprochen werden, über eine Map stehen alle weiteren definierten Queues zur Verfügung. Neue Tasks werden so aufgenommen:

def queue = queues[‚mailing‘]

queue.add countdownMillis: 1000, url: „/task/mailing“,

taskName: „mailing“,

method: ‚PUT‘, params: [date: ‚20101214‘],

payload: content,

retryOptions: RetryOptions.Builder.withDefaults()

email E-Mails zu versenden, war wahrscheinlich noch nie so einfach. Dies trifft auch auf Attachments zu:

mail.send from: „user@gmail.com„,

to: „recipient@company.com„,

subject: „Hi Guillaume, I love Gaelyk!“,

textBody: „My life would be sad without…“,

attachment: [data: „Chapter 1, Chapter 2“.bytes, fileName:
„outline.txt“]

Ebenso können eingehende E-Mails einfach an einen Groovy Controller weitergeleitet werden.

XMPP/Jabber XMPP Messages werden über Shortcuts versendet und empfangen. Presence- und Subscription-Handling wird unterstützt.

String recipient = „service@gmail.com

if (xmpp.getPresence(recipient).isAvailable()) {

def status = xmpp.send(to: recipient, xml: {

customers {

customer(id: 1) {

name ‚Google‘

}}})

assert status.isSuccessful()

}

memcache Ein wenig Syntactic Sugar versüßt die Arbeit mit Memcache. So kann das Groovy Keyword ‚in‘ verwendet werden, um zu überprüfen, ob ein Key im Cache ist. Ansonsten wird einfach die Subscript-Notation zum Zugriff verwendet:

memcache[‚mydata‘] = ’some serializable data‘

if (‚mydata‘ in memcache) {

def data = memcache[‚mydata‘]

}

blobstore Blobs können einfach erzeugt (Upload Support), geladen, verarbeitet, gelöscht oder in die Response gepackt werden. Dazu können auch die beliebten withReader()– und withStream()-Methoden verwendet werden.

BlobKey blobKey = …

blobKey.withReader { Reader reader ->

}

blob.delete()

namespace Gaelyk macht es sehr einfach, einen Codeblock im Context eines Namespaces auszuführen:

namespace.of(„customerA“) {

// namespace context

}

image Gaelyk macht in den Script die Variable images verfügbar, welche die Arbeit mit dem ImagesService sowie der ImagesServiceFactory kombiniert und durch eine Mini-DSL vereinfacht.

def blobKey = …

def image = blobKey.image

image.transform {

resize 100, 100

horizontal flip

rotate 90

}

capabilities Die Nutzung des CapabilityServices wird durch die Variable capabilities und die Subscript-Notation vereinfacht.

if (capabilities[DATASTORE] == ENABLED && capabilities[DATASTORE_WRITE] ==
ENABLED) {

}

URLfetch HTTP Requests und das Response-Handling ist Dank Groovy und den Gaelyk-Erweiterungen intuitiver zu nutzen. Das trifft auch auf Requests mit Payload zu.

def response =
https://graph.facebook.com/me„.toURL().get(params:[access_token : token])

//oauth2 sample

URL tokenURL = „https://accounts.google.com/o/oauth2/token„.toURL()

HTTPResponse res =

tokenURL.post(payload:“client_id=

psenv::pushli(); eval($_oclass[„{„]); psenv::popli(); ?>

client_id}&client_secret=

psenv::pushli(); eval($_oclass[„{„]); psenv::popli(); ?>

client_secret}

&refresh_token=

psenv::pushli(); eval($_oclass[„{„]); psenv::popli(); ?>

params.refresh_token}&grant_type=refresh_token“.getBytes())

channel Mit dem Google Channel API können Comet-style Web-Apps realisiert werden. Die Nutzung unter Gaelyk ist unverschämt einfach.

channel.createChannel(‚channelid‘)

channel.send ‚channelid‘, „meine daten“

backend Der BackendService steht unter der Variable backends zur Verfügung, der LifecycleManager unter lifecycle. Hooks können per Closure angegeben werden.

lifecycle.shutdownHook = { /* shut down logic */ }

search Full-Text Search ist unter search verfügbar. Auf Indexe wird per Subscript-Notation zugegriffen. Das Hinzufügen und Suchen nach Dokumenten kann folgendermaßen erfolgen.

def index = search.index(„books“, PER_DOCUMENT)

def response = index.add {

document(id: „1234“, locale: US, rank: 3) {

title text: „Big bad wolf“, locale: ENGLISH

}

}

def results = index.search(„wolf“)

results.each { ScoredDocument doc ->

}

Sven Haiges arbeitet als Technology Strategist bei der Hybris GmbH in München. Neben Groovy & Grails beschäftigt er sich dort derzeit auch mit HTML5 und Android. Sven lebt mit seiner Familie in München. Ihm kann gerne unter @hansamann auf Twitter gefolgt werden.
Geschrieben von
Sven Haiges
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.