Chrome, HTML5, JavaScript, mobile, webdev

HTML5 Modern Web App and Google Cloud Endpoints (Part 2 Of 3)


  1. Google Plugin for Eclipse
  2. Google API JavaScript client library
  3. Sign up for Cloud Endpoints

User Experiences demands are pushing modern web apps to a more distributed architecture.  A pattern many developers have used is using a MVC framework on the client and communicate to the server with REST. Google App Engine’s easy to build, easy to manage environment makes it ideal for REST APIs for Web backends.  At Google IO 2012, we made it much easier to build REST APIs on App Engine with Cloud Endpoints.

Cloud Endpoints enables you to build REST and RPC APIs in App Engine.  It leverages the same infrastructure  Google uses for its own API and as such, you get strongly typed clients for Android, and IOS as well as a lightweight client for JavaScript which we will be walking through in this presentation.

In getting ready for IO, Ido and I thought we’d build a modern web application using Cloud Endpoints.  We decided on a topic that would be relevant to both App Engine and the general web developer community, something we both have some interest in and something generally useful…. a Beer rating and review web application.

Try it out yourself at:

The general architecture of the app is very basic.  We are storing beer metadata in the data store, doing some application logic on the app engine app, then exposing a REST based interface to a web client.

It’s not an easy definition since web technology is running very fast. Nevertheless, we can find certain features across successful web apps:

  • Self Contained & Functional– They all have one specific goal and they do their best to provide the users the functionality to get to her goal. Few examples:
    1. New York Times – Consume news.
    2. Hipmunk – Find a flight that is the ‘perfect’ for your needs.
    3. Gojee – Find the recipe you would taste and say WOW after it.
  • “Offline first” – You will want your web app to work offline. It’s an important feature that will let your users be productive on places like: planes, subways etc’. Another very important benefit will be the improve in performance. Since the app will work locally (first) and then sync the state/data the users will get responsiveness that are far better from an app that need to ‘wait’ for network on every action that the user does.
  • Client Side Architecture – Since we are moving big parts of our ‘logic’ to the client we need to think about methods that will keep your code readable and maintainable. I guess this is the main reason why we see so many MVC Frameworks. The only advice we can give here is to try few of the popular ones and see how they approach the separation between the data and the UI. If you have some time go over The Top 10 Javascript MVC Frameworks Reviewed. Then, after you try ‘some’ you will be able to pick the one that fit the bill in the best way. For the busy developer (I know… most of us don’t have too much free time – Go and play with these three MVC:
    1. Ember.js – Don’t waste time making trivial choices
    2. Angular.js -Lets you extend HTML vocabulary for your application
    3. Backbone.js – gives structure to web applications by providing models with binding, collections and views.
  • Device Aware – We all know that mobile is going ‘up and right’. So when you design your web app you should think on progressive enhancement and how it will fit  to different screen sizes. Good examples to look at are: Gmail, Google plus etc’. If you want to go deeper on this interesting subject there is a webcast on ‘mobile web apps’ I did with Oreilly three weeks ago.

Let’s take a look at what it takes to build this application. I have Eclipse and the latest version of the Google Plugin for Eclipse installed.  We create a new Web Application, call it birra.

Then, if we are going to build a Beer rating app… the first thing we are going to need is… beer!

Let’s create a Beer class.

It is just a standard POJO for storing information about a beer..

public class Beer {

  private Long id;
  private String beerName;
  private String kindOfBeer;
  private Long score;
  private Long numberOfDrinks;
  private Text image;
  private String country;
  private String description;
  private Double latitude;
  private Double longitude;

  public Long getId() {
    return id;

  public void setId(Long id) { = id;

  public String getBeerName() {
    return beerName;

  public void setBeerName(String beerName) {
    this.beerName = beerName;

  public String getKindOfBeer() {
    return kindOfBeer;

  public void setKindOfBeer(String kindOfBeer) {
    this.kindOfBeer = kindOfBeer;

  public Long getScore() {
    return score;

  public void setScore(Long score) {
    this.score = score;

  public Long getNumberOfDrinks() {
    return numberOfDrinks;

  public void setNumberOfDrinks(Long numberOfDrinks) {
    this.numberOfDrinks = numberOfDrinks;

  public Text getImage() {
    return image;

  public void setImage(Text image) {
    this.image = image;

  public String getCountry() {
    return country;

  public void setCountry(String country) { = country;

  public String getDescription() {
    return description;

  public void setDescription(String description) {
    this.description = description;

  public Double getLatitude() {
    return latitude;

  public void setLatitude(Double latitude) {
    this.latitude = latitude; 

  public Double getLongitude() {
    return longitude;

public void setLongitude(Double longitude) {
  this.longitude = longitude;


Ok, that is a great Beer — now we want to teach App Engine how to persist instances of this beer class in the datastore.  To do that, we will use the classic Java JDO support.  You can of course use any persistence layer (or roll your own) with Cloud Endpoints.

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
@PersistenceCapable(identityType = IdentityType.APPLICATION)

public class Beer {

  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  private Long id;

Now we need to expose these Beers to the JavaScript client.  To do that, we need to use the new cloud Endpoints feature.

That creates a template class that does the basic List, Add, Update, and Delete operations.  The code is meant to be a starter that you can modify to add your application logic.

Let’s test this locally with curl to ensure it is working well before we start to build out a our web client.   First we start the local development time server by hitting debug.

Now we see our local development time server up and running.  From there we also get hint as to the right URL to use for curl.

% curl http://localhost:8888/_ah/api/birra/v1/beer
  "items" : [ ]

Above you can see we are hitting our local development time server.  Then we use the _ah namespace which is the standard app engine reserved namespace… this ensures there are not conflicts with any web pages in your app.  The we use the /api/birra path.  “birra” comes from the @Api() attribute at the top of the file.  Then we access the beer endpoint. This comes from the name of the type the List method returns. The results is an empty list encoded as JSON.

Let’s look at how we add an item.

% curl  -H 'Content-Type: appilcation/json' -d '{"beerName": "bud"}' http://localhost:8888/_ah/api/birra/v1/beer

  "id" : 1,
  "beerName" : "bud",
  "kindOfBeer" : null,
  "score" : null,
  "numberOfDrinks" : null,
  "image" : null,
  "country" : null,
  "description" : null,
  "latitude" : null,
  "longitude" : null

Above you can see we are doing an HTTP POST passing a json encoded blob where we set the beerName to bud.   The results is a JSON blob of the beer after it has been added to the datastore.  Notice it has an ID set which we can use to query for it later.

%  curl http://localhost:8888/_ah/api/birra/v1/beer/1

  "id" : 1,
  "beerName" : "bud",
  "kindOfBeer" : null,
  "score" : null,
  "numberOfDrinks" : null,
  "image" : null,
  "country" : null,
  "description" : null,
  "latitude" : null,
  "longitude" : null

The above code calls the getBeer method passing beerId of 1 and this returns a JSON blob of the beer. As we will see later, we can use the Google API JavaScript client library to access our methods.  To control what they look like in the JavaScript code, we can use the @Api attribute in the package.    We will look a fair bit at the customization options this attribute gives us later in the post.


public Beer removeBeer(@Named(“id”) Long id) {

That is great that we can do this level of testing on the client, but let’s take a look at a version of this I deployed earlier.  You can get a list of all the APIs on your app engine app by hitting:


Above you can see that discovery is tell us we have two APIs. The top one is the discovery API itself and the bottom one is the birra API we just created. Clicking on the discoveryRestUrl link we see the discovery doc for our API.  This is the exact same discovery doc format we use for most Google APIs and as such works with our Google Client Libraries.

In addition, we can use the Google API Explorer with our custom API.  It is very easy to get to by using the explorer shortcut.  http://<appid&gt;

Above we see  a list of all the methods we defined in our API.  Clicking on any of them allows me to interact with that method live.

Notice that we see the exact http request and the response.  This is a very nice way to debug the API independently from the client.  It also gives you all the insight into request and response formats to help you build out great clients.

Now, let’s take a look at using this API from JavaScript..

Client side code to get a list of beers

As we all know, in software development it’s good to take small steps. So first thing we will try to do is to run a simple ajax request.

var apiUrl = "";
  url: apiUrl,
  dataType: 'json',
  contentType: 'application/json',
  type: "GET",
  success: function(data) {
  error: function(xhr, ajaxOptions, thrownError) {
    console.error("Beer list error: " + xhr.status);

You can try this generic test page from:

or test it live:

After we were successful in getting the list of beers with plain vanilla JavaScript, it’s time to use google api JavaScript library. Why? Well, you are getting some powerful features like:

  1. RPC Batch
  2. CORS
  3. Authentication out of the box
  4. Version control
  5. Super Simple to use.
  6. Generic

The call to get the JS library:

<script src="">
{ "client": {},
  "googleapis.config": {
    root: ""

The callback that will be called after Google API JS library was loaded. In our case, we wish to set the API key and load our amazing beer service: ‘birra’.
function loadGapi() {
  // Set the API key
  // Set: name of service, version and callback function
  gapi.client.load('birra', 'v1', getBeers);

The callback function that will be called after our Birra service was loaded. In this case we fetch a list of beers (top 20 beers) andshow them to the user.
function getBeers() {
  var req = gapi.client.birra.listBeer();
  req.execute(function(data) {

Here are some of the basic Adding, Editing and Removing operations:

Let’s take a look at adding Comment support to this application.  I may want to allow people to leave comments on the beers.  To do that, let’s add a new Comment class and enable it for persistence into the datastore.

Now, we need to expose Comment as part of our Birra REST API.    We use the Google->Generate Cloud Endpoint class option in eclipse.

We change the name to be birra to have it be part of the same API.

It’s becoming much too long for a post… so here is the full article.

Also, if you miss the first part of this series:

As always, if you have any comments please share…


7 thoughts on “HTML5 Modern Web App and Google Cloud Endpoints (Part 2 Of 3)

  1. Kevin Lippiatt says:

    Thanks for the article. It’s a great follow-up to the I/O session video. As Cloud Endpoints are currently under a Trusted Tester programme – when will they be available to all as standard?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s