Accessing Google Cloud SQL From App Engine

Accessing Google Cloud SQL from an App Engine application is relatively straightforward. To start, an application must first specify a host name for the Cloud SQL servers.

For example, here’s the host name for PHP applications:

:/cloudsql/[Google-Cloud-Project-Name]:[Cloud-SQL-Instance-Name]

Java accesses Cloud SQL through a special JDBC driver. Here’s the proper host name for it:

jdbc:google:mysql://[Google-Cloud-SQL-Project-Name]:[Cloud-SQL-Instance-Name]/[Database-Name]

Secondly, Cloud SQL must whitelist incoming connections from permitted App Engine applications. To do this, open up the Google Cloud console and select the project you’re using. Then press the Cloud SQL option on the left hand navigation bar:

Click the New Instance button:

On the bottom of the form there’s an option to whitelist named App Engine applications. Type in the application ID of the App Engine application using the database:

Click the Confirm button to finish setting up the database.

App Engine Downtime Notices

App Engine downtime and maintenance notices are posted to the Google Group google-appengine-downtime-notify, located at https://groups.google.com/forum/#!forum/google-appengine-downtime-notify . It’s a good idea to monitor this list for any issues with the App Engine platform.

It’s especially important to subscribe to these notices if your application is still on the M/S datastore. The M/S datastore is occasionally moved into a read-only state for maintenance, and these maintenance periods are announced over the downtime list.

Subscribing to the google-appengine-downtime-notify list is easy: go to the above linked address and click on the button marked Join Group. As you can see from the below pictures, this list is extremely low-traffic (less than 1 email a day).

Using Javascript To Forward A User (And Keeping Track Of The Forward)

URL hashes (the part after the # sign) are useful for keeping track of application state. Here’s a short example of how they can be used.

The below code fragment forwards the user to a Google search for the value held in the variable q . The useful part is that this code also sets a hash to mark that the forward has taken place. This allows the page to keep track of the forwarding status, and to prevent reissuing the forward – for instance, if the user presses the back button after being forwarded.

if (location.hash != "#forwarder") {
    location.hash = "forwarder";
    var search_url = "http://www.google.com/search?q=" + escape(q);
    //Set the timeout to 10 seconds.
    setTimeout(function(){location.assign(search_url);},10000);
}

To see how this works, consider the below example. The first alert will show that there’s no hash recorded in the URL (the alert will be blank). The second line sets a hash of forwarder and the third line shows the value of the current hash (which will be the value we set on the second line). This will cause the if statement to evaluate to false, preventing the forwarding from taking place. The same process (recognizing the hash and blocking the forward) happens when the user clicks the back button on the above forwarding code.

alert(location.hash);
location.hash = "forwarder";
alert(location.hash);
if (location.hash != "#forwarder") {
    location.hash = "forwarder";
    var search_url = "http://www.google.com/search?q=" + escape(q);
    //Set the timeout to 10 seconds.
    setTimeout(function(){location.assign(search_url);},10000);
}

App Engine System Status

The App Engine system status console is located at https://code.google.com/status/appengine . It’s a good idea to keep this page bookmarked to monitor GAE’s performance.

Here’s how the status page looks like when everything is running well:

Here’s an example of how performance issues are reported:

100% Logs Stored Data On Free Tier Applications

Some heavily-trafficked free tier applications may find themselves with a full Logs quota bar, similar to the below screen:

For free tier applications, App Engine will retain 1 GB of logs over the last 90 days. This quota doesn’t reset on a daily basis like other quotas do; instead, it shows how much logging data has been retained over the last 90 days. In this example screenshot the demonstration application has 1 GB of logging data stored, so the logs quota shows a full red bar.

App Engine will pop up a billing notice whenever there is a full quota bar (as in the above screen) and it’s a good idea to enable billing if you need to retain more logs for a longer period of time. However, if you’re only interested in the recent logs, you don’t need to enable billing. App Engine implements logs as a FIFO queue: new logs are added in, and old logs are deleted out.

In short: if your application’s logs quota is full, you only need to enable billing to retain the older logs. The logs for fresh/recent requests will always be available.

The Term (Domain) Is Not Allowed

While configuring a domain within Google Apps, you may see the error message “ The Term [Domain Name] Is Not Allowed ”:

This error can come up due to several problems. The most likely issue is that the domain has been configured as an independent domain, rather than as an alias domain. A quick fix to this issue is to delete this domain from Google Apps, and then to re-add it. When the prompt comes up to select independent domain versus alias domain, select the alias domain option.

Slashdot Downtime Notices

I like to collect samples of downtime notices and error messages from popular websites; it’s always fascinating to see how sites handle messaging on technical issues.

Here’s an example downtime notice from Slashdot:

Here is the message in context:

AccessControlException Resulting From RuntimePermission: modifyThreadGroup

While using certain libraries on App Engine, you may encounter the following exception notice:

javax.servlet.ServletContext log: 
    Exception while dispatching incoming RPC call
threw an unexpected exception: 
    java.security.AccessControlException: 
    access denied (java.lang.RuntimePermission modifyThreadGroup)

If you see this exception message, your application or (more frequently the case) a library is attempting to create a new thread. App Engine doesn’t allow frontend instances to spawn threads, so any attempt to start up a thread will result in AccessControlExceptions.

However, App Engine does allow backend threads: threads which run within backend instances. If your application absolutely needs to run threads, run the threading component within a backend or a backend module.

DatastoreFailureException: Internal Error Exception Messages

On rare occasions, an application may spawn errors similar to the below:

com.google.appengine.api.datastore.DatastoreFailureException: 
    internal error.
at com.google.appengine.api.datastore.DatastoreApiHelper.translateError     (DatastoreApiHelper.java:50)
at com.google.appengine.api.datastore.DatastoreApiHelper$1.convertException     (DatastoreApiHelper.java:70)

As the exception message suggests, this log indicates that the datastore encountered an internal error while handling the datastore operation. Unfortunately, there’s nothing that a developer can do to fix this error since it’s an internal App Engine issue.

Generally this type of exception fixes itself sooner or later; if it persists, file an issue at the App Engine bug tracker: https://code.google.com/p/googleappengine/issues/entry?template=Production%20issue

Datastore Query Cursor: ExQ

While using JDO or another datastore helper library, applications may encounter a value of ExQ when requesting a query cursor. This value means that there are no more results (entities) to display for that query, and consequently that there are no more query pages to return.

All applications using query cursors should check for an invalid or end of query results marker, and handle this in an application-specific way. A query cursor string that is null or empty (zero length) generally denotes the end of query results. The cursor value ExQ can be handled in the same way.

A word of warning: some third-party datastore helper libraries spawn an exception or error condition when applications attempt to access invalid cursors, or attempt to request a cursor when end of results has already been reached. When using these libraries, it’s important to fully read the documentation and understand how these libraries interact with the App Engine datastore.