39
Guillaume Laforge SpringSource, a division of VMWare F GAELYK a lightweight Groovy toolkit for Google App Engine mercredi 19 mai 2010

Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Embed Size (px)

Citation preview

Page 1: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Guillaume LaforgeSpringSource, a division of VMWare

F GAELYKa lightweight Groovy toolkit for Google App Engine

mercredi 19 mai 2010

Page 2: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Guillaume LaforgeGroovy Project Manager

on Groovy since 2003!

JSR-241 Spec Lead

Head of Groovy Developmentat SpringSource (division of VMWare)

Initiator of the Grails framework

Creator of the Gaelyk toolkit

Co-author of Groovy in Action

International speaker

mercredi 19 mai 2010

Page 3: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

CloudComputing

mercredi 19 mai 2010

Page 4: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

IaaS, PaaS, SaaS

Software as a ServiceGmail, SalesForce.com

Platform as a ServiceGoogle App Engine

Infrastructure as a ServiceAmazon EC2

SaaS

PaaS

IaaS

mercredi 19 mai 2010

Page 5: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

IaaS, PaaS, SaaS

Software as a ServiceGmail, SalesForce.com

Platform as a ServiceGoogle App Engine

Infrastructure as a ServiceAmazon EC2

SaaS

PaaS

IaaS

mercredi 19 mai 2010

Page 6: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

IaaS, PaaS, SaaS

Software as a ServiceGmail, SalesForce.com

Platform as a ServiceGoogle App Engine

Infrastructure as a ServiceAmazon EC2

SaaS

PaaS

IaaS

mercredi 19 mai 2010

Page 7: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

F

http://gaelyk.appspot.com

mercredi 19 mai 2010

Page 8: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

F

http://gaelyk.appspot.com

mercredi 19 mai 2010

Page 9: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

mercredi 19 mai 2010

Page 10: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

GaelykGaelyk is a lightweight Groovy toolkit on top of the Google App Engine Java SDK

Gaelyk builds on Groovy’s servlet supportGroovlets: Groovy scripts instead of raw servlets!

Groovy templates: JSP-like template engine

Both allow for a clean separation of views and logic

Gaelyk provides several enhancements around the GAE Java SDK to make life easier, thanks to Groovy’s dynamic nature

mercredi 19 mai 2010

Page 11: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Why Groovy?Groovy is a dynamic language for the JVM

very flexible, malleable, expressive and concise syntax

easy to learn for Java developersderiving from the Java 5 grammar

provides powerful APIs to simplify the life of developerspossibility to dynamically enrich existing APIs

support for Groovlets and its own template engine

The truth: We worked with the Google App Engine Java team before the official launch of the platform, to ensure Groovy would run well on this new environment

mercredi 19 mai 2010

Page 12: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

First steps...

• Go to http://gaelyk.appspot.com

• Download the template project

• Put your first Groovlet in /WEB-INF/groovy

• And your templates at the root

• And you’re ready to go!

mercredi 19 mai 2010

Page 13: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

The web.xml<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">

<servlet> <servlet-name>GroovletServlet</servlet-name> <servlet-class>groovyx.gaelyk.GaelykServlet</servlet-class> </servlet> <servlet> <servlet-name>TemplateServlet</servlet-name> <servlet-class>groovyx.gaelyk.GaelykTemplateServlet</servlet-class>

</servlet> <servlet-mapping> <servlet-name>GroovletServlet</servlet-name> <url-pattern>*.groovy</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>TemplateServlet</servlet-name> <url-pattern>*.gtpl</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.gtpl</welcome-file> </welcome-file-list></web-app>

mercredi 19 mai 2010

Page 14: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

MVC: Groovlets and templates

Groovlets(controllers)

Templates(views)

Entities(domain)

mercredi 19 mai 2010

Page 15: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

A groovletInstead of writing full-blown servlets, just write Groovy scripts (aka Groovlets)

def numbers = [1, 2, 3, 4]def now = new Date()

html.html { body { numbers.each { number -> p number } p now }}

mercredi 19 mai 2010

Page 16: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

A template<html> <body> <p><% def message = "Hello World!" print message %> </p> <p><%= message %></p> <p>${message}</p> <ul> <% 3.times { %> <li>${message}</li> <% } %> </ul> </body></html>

mercredi 19 mai 2010

Page 17: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

ShortcutsGoogle services

datastore

blobstore

memcache

urlFetch

mail

userService / user

defaultQueue / queues

xmpp

Variables availablerequest / response

context / applicaiton

session

params / header

out / sout / html

localMode / app.*

Methods availableinclude / forward / redirect

print / println

mercredi 19 mai 2010

Page 18: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Groovy sugar!

mercredi 19 mai 2010

Page 20: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

...compared to Java

Properties props = new Properties();

Session session = Session.getDefaultInstance(props, null);

String msgBody = "...";

try { Message msg = new MimeMessage(session);

    msg.setFrom(new InternetAddress("[email protected]", "Admin"));

    msg.addRecipient(Message.RecipientType.TO,

                     new InternetAddress("[email protected]", "Mr. User"));

    msg.setSubject("Your Example.com account has been activated");

    msg.setText(msgBody);

    Transport.send(msg);} catch (AddressException e) {}

} catch (MessagingException e) {}

mercredi 19 mai 2010

Page 21: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Accessing the datastoreDirect interaction with the low-level datastore API

import com.google.appengine.api.datastore.Entity

 Entity entity = new Entity("person") // subscript notation, like when accessing a map

entity['name'] = "Guillaume Laforge" // normal property access notationentity.age = 32

entity.save()entity.delete()

datastore.withTransaction { // do stuff with your entities // within the transaction}

mercredi 19 mai 2010

Page 22: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Querying to be improved...import com.google.appengine.api.datastore.*import static com.google.appengine.api.datastore.FetchOptions.Builder.* // query the scripts stored in the datastoredef query = new Query("savedscript") // sort results by descending order of the creation datequery.addSort("dateCreated", Query.SortDirection.DESCENDING) // filters the entities so as to return only scripts by a certain authorquery.addFilter("author", Query.FilterOperator.EQUAL, params.author)

 PreparedQuery preparedQuery = datastore.prepare(query) // return only the first 10 resultsdef entities = preparedQuery.asList( withLimit(10) )

mercredi 19 mai 2010

Page 23: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

...into something groovier?

def entities = datastore.createQuery { select from: savedscript sort DESC, on: dateCreated where author == params.author limit 10} as List

mercredi 19 mai 2010

Page 24: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

...into something groovier?

def entities = datastore.createQuery { select from: savedscript sort DESC, on: dateCreated where author == params.author limit 10} as List

Not Yet Im

plemented!

mercredi 19 mai 2010

Page 25: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Task queue API// access a configured queue using the subscript notationqueues['dailyEmailQueue'] // or using the property access notationqueues.dailyEmailQueue // you can also access the default queue with:queues.defaultdefaultQueue

// add a task to the queuequeue << [ countdownMillis: 1000, url: "/task/dailyEmail", taskName: "sendDailyEmailNewsletter", method: 'PUT', params: [date: '20090914'], payload: content]

mercredi 19 mai 2010

Page 26: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Jabber / XMPP support (1/3)Sending instant messages

String recipient = "[email protected]" // check if the user is onlineif (xmpp.getPresence(recipient).isAvailable()) { // send the message def status = xmpp.send(to: recipient, body: "Hello, how are you?")  // checks the message was successfully // delivered to all the recipients assert status.isSuccessful()}

mercredi 19 mai 2010

Page 27: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Jabber / XMPP support (2/3)Sending instant messages with an XML payload

String recipient = "[email protected]" // check if the service is onlineif (xmpp.getPresence(recipient).isAvailable()) { // send the message def status = xmpp.send(to: recipient, xml: { customers { customer(id: 1) { name 'Google' } } })  // checks the message was successfully delivered to the service assert status.isSuccessful()}

mercredi 19 mai 2010

Page 28: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Jabber / XMPP support (2/3)Sending instant messages with an XML payload

String recipient = "[email protected]" // check if the service is onlineif (xmpp.getPresence(recipient).isAvailable()) { // send the message def status = xmpp.send(to: recipient, xml: { customers { customer(id: 1) { name 'Google' } } })  // checks the message was successfully delivered to the service assert status.isSuccessful()}

<customers> <customer id=’1’> <name>Google</name>

</customer></customers>

mercredi 19 mai 2010

Page 29: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Jabber / XMPP support (3/3)Receving incoming instant messages

Configure the XmppServlet in web.xml

Add the inbound message service in appengine-web.xml

// get the body of the messagemessage.body// get the sender Jabber IDmessage.from// get the list of recipients Jabber IDsmessage.recipients // if the message is an XML document instead of a raw string messageif (message.isXml()) { // get the raw XML message.stanza // get a document parsed with XmlSlurper message.xml}

mercredi 19 mai 2010

Page 30: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Memcache serviceMap notation access to the cache

class Country implements Serialzable { String name } def countryFr = new Country(name: 'France') // use the subscript notation to put a country object in the cache

// (you can also use non-string keys)memcache['FR'] = countryFr // check that a key is present in the cacheif ('FR' in memcache) { // use the subscript notation to get an entry from the cache using a key

def countryFromCache = memcache['FR']}

mercredi 19 mai 2010

Page 31: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

URL Routing systemYou can have friendly URL mappings with the URL routing system introduce in Gaelyk 0.3.2

all "/blog/@year/@month/@day/@title", forward: "/blog.groovy?year=@year&month=@month@day=@day@title=@title"

get "/blog/@year/@month/@day", forward: "/blog.groovy?year=@year&month=@month@day=@day"

all "/aboutus", redirect: "/blog/2008/10/20/about-us"

get "/book/isbn/@isbn", forward: "/book.groovy?isbn=@isbn", validate: { isbn ==~ /\d{9}(\d|X)/ }

mercredi 19 mai 2010

Page 32: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Simple plugin system (1/3)Gaelyk 0.4 introduces a simple plugin system for extending your apps and share commonalities

A plugin lets youprovide additional groovlets and templates

contribute new URL routes

add new categories

define variables in the binding

provide any static content

add new libraries

do any initialization

mercredi 19 mai 2010

Page 33: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Simple plugin system (2/3)A plugin is actually just a zip file!

Basically, just a Gaelyk application, minus...the Groovy / Gaelyk / GAE JARs

the web.xml and appengine-web.xml descriptors

But with a /WEB-INF/plugins/myplugin.groovy descriptor

A plugin must be referenced in /WEB-INF/plugins.groovy with

install mypluginshortcut to /WEB-INF/plugins/myplugin.groovy

mercredi 19 mai 2010

Page 34: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Simple plugin system (3/3)An example plugin descriptor

/WEB-INF/plugins/jsonPlugin.groovy

import net.sf.json.*import net.sf.json.groovy.* // add new variables in the bindingbinding {

jsonLibVersion = "2.3"          // a simple string variable

json = new JsonGroovyBuilder()  // an instance of a class of a 3rd‐party JAR

} // add new routes with the usual routing system format

routes {get "/json", forward: "/json.groovy"

} // install a category you've developped

categories jsonlib.JsonlibCategory // any other initialization code you'd need

mercredi 19 mai 2010

Page 35: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

What’s coming next?Gaelyk 0.4 was released a few days ago

Features a lightweight plugin system

A 0.4.1 bug fix is coming soon

Expect more sugar around the DatastoreAn SQL-like query DSL

Easier relationship management (builder)

Perhaps pre-compiled groovlets and templates

More generally...Anything that’ll come up in upcoming GAE SDK versions

mercredi 19 mai 2010

Page 36: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

SummaryEasy access to a cloud solution

Deploying Java apps, as easily as you would with PHP

Familiar to Java folksYour good old Servlet centric webapps style

Pretty cheapYou need a high-trafficed website to reach the quotas

Gaelyk provides a simplified approach to creating Servlet centric webapps in a productive manner

Leveraging Groovy’s servlet / template support and dynamic capabilities

mercredi 19 mai 2010

Page 37: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Questions & Answers

mercredi 19 mai 2010

Page 39: Gaelyk quickie - GR8Conf Europe 2010 - Guillaume Laforge

Images used in this presentationClouds

http://www.morguefile.com/archive/display/627059

http://www.morguefile.com/archive/display/625552

http://www.morguefile.com/archive/display/629785

Duke ok GAE

http://code.google.com/images/duke-on-gae.jpg

http://weblogs.java.net/blog/felipegaucho/archive/ae_gwt_java.png

Python logo : http://python.org/images/python-logo.gif

Gaelyc cross with clouds : http://www.morguefile.com/archive/display/37889

Speed limit : http://www.morguefile.com/archive/display/18492

Warehouse : http://www.morguefile.com/archive/display/85628

Snow foot steps : http://www.flickr.com/photos/robinvanmourik/2875929243/

Sugar : http://www.flickr.com/photos/ayelie/441101223/sizes/l/

mercredi 19 mai 2010