About the 2015 Editions

In July 2015, Programming Google App Engine split in two! Formerly a single volume, PGAE is now two separate books:

The two versions include similar material on App Engine concepts, as well as material specific to each language's runtime environment and libraries. Both versions include updates and new material for 2015.

What's New

The material from the 2nd edition has been revised heavily for the 2015 editions. Features include:

  • Now available in two language-specific versions: Java and Python
  • Completely updated for the new Google Cloud SDK and Google Developers Console
  • New major sections on topics such as on SSL, custom domain names, and traffic splitting
  • All-new chapters on modules, Python's ndb library, and Google Cloud SQL
  • Python's Django chapter updated to cover Django 1.8 and Cloud SQL

Here's the chapter list:

  • Introducing Google App Engine
  • Creating an Application
  • Configuring an Application
  • Request Handlers and Instances
  • Using Modules
  • Datastore Entities
  • Datastore Queries
  • Datastore Transactions
  • Data Modeling with ndb [Python only]
  • Datastore Administration
  • The Java Persistence API [Java only]
  • Using Google Cloud SQL with App Engine
  • The Memory Cache
  • Fetching URLs and Web Resources
  • Sending and Receiving Email Messages
  • Sending and Receiving Instant Messages with XMPP
  • Task Queues and Scheduled Tasks
  • Optimizing Service Calls
  • The Django Web Application Framework [Python only]
  • Managing Request Logs
  • Deploying and Managing Applications

2015 Editions Errata

All errata from the 2nd edition has been fixed in the 2015 editions. Any newly discovered errata will be listed below.

App Engine is an active project, and may have changed since these books were published. For a complete list of changes, see the App Engine release notes for Java and Python.

Many thanks to the readers that have submitted errata and feedback! Submit your feedback.

Chapter 2

  • In July 2015, Google made a major change to the App Engine command line tools distributed with the Cloud SDK. The dev_appserver and appcfg commands were replaced with gcloud ... equivalents, and the gae-java and gae-python SDK components were removed in favor of libraries that install automatically as needed. As of July 9, the new command line tools for running a development server and deploying the app are gcloud preview app run and gcloud preview app deploy, respectively. The word "preview" will be removed in favor of just gcloud app ... when the new feature is finalized.

    You can download the original standalone GAE SDK to acquire the original dev_appserver and appcfg tools described in the book. Alternatively, you can run gcloud help preview app ... to learn more about the new commands (currently in beta). There are minor differences between the old and new commands.

    It is no longer necessary (or possible) to run the gcloud components update gae-python (or ... gae-java) command.

  • In March 2016, Google changed the address of the Cloud Console. It is now available at https://console.cloud.google.com/.

    The original URL, https://console.developers.google.com/, is now a streamlined subset of the Cloud Console for developers using Google APIs without Cloud products.

Chapter 9 (Java) / Chapter 10 (Python)

  • The Datastore Administration chapter describes how to call your app's Remote API endpoint from a custom client tool to perform arbitrary API calls remotely, such as a local script that queries your app's datastore. The example scripts provided use an authentication method called ClientLogin. On January 20, 2016, Google will disable ClientLogin in favor of OAuth2. See the official Remote API documentation for an updated example of writing a client tool that uses OAuth2.

Chapter 16 (Python)

  • The Python task chaining code sample code needs several fixes:

    • Remove the start_cursor=cursor parameter from the call to Quest.query(), then add it as the second argument to query.fetch_page(...).
    • In the two places where new_cursor is used, replace it with new_cursor.urlsafe().
    • Change datetime.fromtimestamp to datetime.datetime.fromtimestamp.

    Also note that for this code sample to function, there must be entities of kind Quest, each with a end_timestamp property with a numeric value.