The first day of OSCon 2009 covered a number of tutorials and I decided to attend Google App Engine tutorial for the first half of the day. Google App Engine API follows CGI model of web development, i.e., it uses stdin and stdout files and assumes stateless applications. There is limit of 10MB response size and 30 requests per second, but it does not allow streaming. The tutorial started pretty slow and we spent first hour just installing the SDK and tutorial. The Google App Engine SDK is available from http://code.google.com/appengine/downloads.html. I downloaded Mac image and then dragged the image to my hard drive. I then double clicked the app icon for Google Appe Engine SDK, which installed the SDK under /usr/local/google_appengine. Once the SDK is installed, you have to install Google App Engine tutorials from http://code.google.com/p/app-engine-tutorial/.
After installing SDK and tutorial, I copied all files named tutorial? under the SDK. The rest of session covered those tutorials one by one, though we ran out of time in the end and completed only upto tutorial7. In order to install first tutorial, I went into tutorial1 directory, e.g.
cd /usr/local/google_appengine/tutorial1
Then started local app server as follows:
python ../dev_appserver.py .
When I pointed my browser to the http://localhost:8080, I was able to see “Hello World!”.
Next, I registered myself to http://appspot.com. After registering, I received an SMS message for confirmation and was able to fully register after entering the confirmation number. Next, I created an application-id on Google App Engine. You can only create 10 app-ids and you cannot delete app-ids, so be careful with ids. Also, you can also use your own domain instead appspot.com. For my testing purpose, I chose the id “shahbhat”.
Next, I changed app.yaml inside my local tutorial1 directory that describes how your application is configured. You may also notice index.yaml, which describes list of indices in the database, though Google App Engine can figure out what queries are being used and creates indices automatically. I changed application name in app.yaml to “shahbhat”, e.g.
application: shahbhat
I then pushed my application to the Google App Engine by typing
python ../appcfg.py update .
I was then able to go to http://shahbhat.appspot.com/ and see my application, Voila. You can also see your application usage from http://appengine.google.com/dashboard?app_id=shahbhat (you will have to change app_id parameter in your application).
Unfortunately, a lot of people had problems getting to that state so we wasted another half hour in break where other folks sort out configuration and deployment issues.
Next, I went through another tutorial to turn on authentication by setting:
login: required
in app.yaml file. Next I added caching by adding expires options in the app.yaml. I was also able to use curl to test my applications and see headers to verify caching, e.g.
curl --include http://localhost:8080
Which showed following when caching was not configured:
Cache-Control: no-cache
When I configured the caching to 2d, I was able to see:
Cache-Control: public, max-age=172800
The Google App Engine SDK also includes development that you can view by going to:
http://localhost:8080/_ah/admin
The Google App Engine supports Django based templates, e.g.
#!/usr/bin/env python import os from google.appengine.ext.webapp import template def main(): template_values = {"foo" : [1,2,3]} template_file = os.path.join( os.path.dirname(__file__), "index.html") body = template.render( template_file, template_values) print "Status: 200 OK" print "Content-type: text/html" print print body if __name__ == '__main__': main()
In addition, Google App Engine supports WSGI standard (PEP 333), e.g.
import os import wsgiref.handlers from google.appengine.ext import webapp from google.appengine.ext.webapp import template class IndexHandler(webapp.RequestHandler): def get(self): template_values = {"foo" : 1} template_file = os.path.join(os.path.dirname(__file__), "index.html") self.response.out.write(template.render(template_file, template_values)) def main(): application = webapp.WSGIApplication([('/', IndexHandler)], debug=True) wsgiref.handlers.CGIHandler().run(application) if __name__ == '__main__': main()
Other tutorials included authentication APIs such as
create_login_url(dest_url) create_logout_url(dest_url) get_current_user() is_current_user_admin()
The SDK also includes decorator to add authentication automitcally using
from gogole.appengine.ext.webapp.util import login_required ... @login_required def get(self):
Finally, we went over datastore APIs for persistence support, e.g.
import os import wsgiref.handlers from google.appengine.ext import webapp from google.appengine.ext.webapp import template from google.appengine.ext import db class ToDoModel(db.Model): description = db.StringProperty() created = db.DateTimeProperty(auto_now_add=True) foo = db.FloatProperty(default=3.14) bar = db.IntegerProperty() baz = db.BooleanProperty(default=False) N = db.IntegerProperty() l = db.ListProperty(str, default=["foo", "bar"]) class IndexHandler(webapp.RequestHandler): def get(self): todo = ToDoModel(description = "Hello World", bar=1, baz=True) todo.put() def main(): application = webapp.WSGIApplication([('/', IndexHandler)], debug=True) wsgiref.handlers.CGIHandler().run(application) if __name__ == '__main__': main()
You can view the model by going to http://localhost:8080/_ah/admin/datastore. The data store supports a number of types such as string, boolean, blob, list, time, text. However, there are some limitations,
e.g. TextProperty can only store upto 500 bytes and Google App Engine will create index if needed, however it won’t create index on TextProperty. For each row, the datastore assigns a numeric id and UUID based key,
though you can provide your own key. Also, a row cannot exceed 1MB.
Unfortunately, we ran out of time At this time, so I had to go to http://code.googlecom/appengne/docs for further documentation. Overall, I thought it was good introduction to Google App Engine, but I was disappointed that instructor wasted a lot of time with setup that could have been used to cover rest of the tutorials.
For the second half of the day, I attended session on “Building applications with XMPP”. This was interesting session that showed usage of XMPP for a number of usecases such as IM, gaming, real-time social networking, , monitoring, etc. The session started with history of XMPP (Extensible Messaging and Presnce Protocol), its Jabber roots and its use of streaming XML. A number of factors contributed to the popularity of XMPP such as open source, XML, federeated network, low latency, etc. The XMPP is also very extensible and supports audio/video via jingle, geo location, TLS, SASL, etc. XMPP architecture is based on client server, where servers are decentralized and federated. XMPP identifies a user with jabber id that looks like email address and consists of local part, domain and resource, e.g. alise@wonderland.lit/TeaParty, where domain is mandatory, but local-part and resource are optional. There are three types of XMPP message stanzas, i.e., presence, IQ, message. The presence-stanza is asynchronous, but IQ stanza requires response. As opposed to web architecture that is based on short lived connections and stateless architecture, XMPP uses one long lived session and events are received asynchronously.
Next, the tutorial showed how to build a javascript client for jabber using sleekxmpp and Strophe library (alternatively you can use twistedword). The example used Bosh protocol to wrap XMPP protocol with HTTP protocol. Unfortunately, there was a lot of fast typing and I could not follow all that. I am waiting for the presenters to post the slides online so that I can use those examples in my own applications.