Best practices for Google Cloud Endpoints

Google Cloud Endpoints can save you coding time. This article walks you through several best practices for using endpoints, such as how to annotate methods to avoid REST collisions.

Cloud Endpoints in a Nutshell

Cloud Endpoints is a service for building and exposing custom APIs with which your client applications can interact.

It exists to make your life as a developer much easier. Google engineers have already put in an enormous amount of effort to write and optimize it for you, freeing you from the worry of writing the bulk of the server-client interactions and protocols yourself.

One of the benefits of being able to easily build your own API is that you can design it any way you want. Cloud Endpoints gives you this flexibility—it allows REST- or RPC-style APIs, or a combination of both. Even better, you can change the design as often as you like and implement those changes quickly. This is perfect for agile style of development.

A Bit About Basic REST

In REST, the basic idea is to expose the state of the system as a collection of individually addressable resources. You perform operations by manipulating these resources. A resource is an entity that has a state, as well as a name or id. Resources are stored in your backend—whether that is the Google Cloud Datastore, or something else.

As a general rule with REST, the client sees representations of the resources through requests made to the server. It can also update the resources by manipulating the representations, and sending the updated representations to the server via subsequent requests. Resources may be represented in a variety of ways: XML, JSON, CSV, or more. At this time, Cloud Endpoints only supports JSON, which tends to be less verbose and less vulnerable to human error than XML is.

CRUD (Create, Retrieve, Update, Delete) is at the root of REST. When you use Android Studio or the Google Plugin for Eclipse to generate an Endpoint class, these types of basic methods are generated for you.

You are not limited to those basic actions. Adding custom methods gives you more flexibility, allowing you to perform complex operations. For example, checkForVictory might perform several queries and write to a database.

Setup: A Quick Review

This section provides a quick review on how to generate your project and build Endpoints on Eclipse. For more information, refer to the developer documentation.

  1. Make sure the following are downloaded and set up on your computer:
    1. Eclipse
    2. Google Plugin for your version of Eclipse
    3. App Engine SDK
    4. Android SDK

    At the time of writing, the latest versions were Eclipse 4.2, App Engine SDK 1.8.0, and Android SDK r21.01.1.

  2. If you do not already have an Android client application, create one in Eclipse.
  3. Create your App Engine backend by right-clicking your Android Application and selecting Google > Create App Engine Backend.
  4. You can generate basic Endpoints classes by right-clicking your data object java class and selecting Google > Generate Cloud Endpoint Class. You can always further modify these classes.
  5. Generate your library by right-clicking your App Engine backend application and selecting Google > Generate Cloud Endpoint Library.

If you’re an IntelliJ user, another option for an Android development environment is the Android Studio on IntelliJ. Although this article does not cover that option, you can read more about it on the Android developer site.

Snippets of Endpoint Code

Defining Endpoints in the Backend

The App Engine application Endpoints code can be grouped into two categories: model and API.

The first type is your model. These classes represent the objects in the world of your application—in other words, they represent the resources that will be manipulated by your API. For example, if your application world contains lobsters with whiskers, you might have a data object such as this:

public class Lobster {
  private int whiskerLength;
  public int getWhiskerLength() {
    return whiskerLength;
  public void setWhiskerLength(int whiskerLength) {
    this.whiskerLength = whiskerLength;

The second type is your API code. The API part of your code provides the methods that may be accessed in a client application. These methods manipulate the objects in your model. There are two ways to start writing API code:

  • You may right-click on and select Google > Generate Endpoint Class, whereupon Eclipse will generate a new class for you called This class will be filled with pre-generated annotations and code, ready to be called from your client. These generated methods insert, update, and delete your Lobster objects from your Datastore. You can further modify this class by adding or removing methods.
  • You may create your own Java class and call it whatever you want. As long as it is annotated properly, Cloud Endpoints will recognise it as being part of your API. Please note that private instance methods will not become part of your API.

An example of an endpoint class might look like this:

@Api(name = "lobster")
public class LobsterEndpoint {
  @ApiMethod(name = "lobster.growWhisker", httpMethod = HttpMethod.POST)
  public void growWhisker(Lobster lobster) {
    // grows the lobster’s whisker
    // calculates growth, updates the Lobster in Datastore
  private int calculateWhiskerGrowth(Lobster lobster) {
    // this method is a private utility method
    // it will NOT be visible in your API

One general tip: Don’t get stuck on the generated endpoint code. It is useful, yes, and contains great starting point patterns, but don’t be afraid to modify it for your specific project. The code is as malleable as you want it to be. For example, the auto-generated DeviceInfo entities use Registration IDs as keys. You can still add new fields to a DeviceInfo entity, or use a different field for the key instead.

Consuming Endpoints from the Client

After you generate your Cloud Endpoint Library, the new code that appears in your client (usually under some folder with endpoint-libs in the filepath) corresponds to the functionality you provided in your backend code.

The difference in the model is that new classes extend the GenericJson class, so that they can be sent as JSON. This is what your newly-generated Lobster class might look like:

public final class Lobster extends GenericJson {
  private int whiskerLength;
  public int getWhiskerLength() {
    return whiskerLength;
  public Lobster setWhiskerLength(int whiskerLength) {
    this.whiskerLength = whiskerLength;
    return this;

The API client code is a series of methods and JSON request classes, which make it very easy for you to use in an Android client. This is what the result of your class might look like:

public Lobster lobster() {...}
public class Lobster {
  public GrowWhisker growWhisker(Lobster lobster) {...}
  public class GrowWhisker extends LobsterRequest {
    private static final String REST_PATH = “growWhisker”
    protected GrowWhisker(Lobster lobster) {...}

You can then consume this exposed endpoint with the following code:


If you are at all familiar with HTTP requests, you will know that, for any given REST path, you can only provide one definition of POST, one of GET, and so on. You can certainly create multiple POSTs in the same endpoint API, but make sure that their REST paths are different, or you will run into conflicts. For more information on @ApiMethod annotations, see the relevant section in the appendix.

Ideally, once the library is generated in your client application, you should leave the generated client code alone. Any changes you may want to make to your model or API should be done in the backend.

Designing Your API


  • The classes in your model must have certain characteristics.
    If you want to use a class in your API, these are the characteristics that are required:
    • Be serializable
    • Have a zero-argument constructor
    • Implement getters and setters for its fields
  • The classes in your model may contain other instance methods as well.
    Keep in mind that any methods that are not getters or setters will never see the light of day on the client side.
  • How does an object class definition in the model get flagged for inclusion in the generated client model?
    Say you have a class and some fields and getters and setters (get/setPearl, get/setColor, for example), but when you generate the Endpoint Library, no appears in your generated code. What happened to it? How you use the Clam object in the rest of your model and in your backend API determines this behavior.
    • Using the entity in your API will force Cloud Endpoints to recognize that Clams, as objects, exist.
      @ApiMethod(name = "clam.producePearl", httpMethod = HttpMethod.POST)
      public void producePearl(Clam clam) {
        // adds a pearl to the clam
    • Using Clams properly in your model forces Cloud Endpoints to recognize them and generate a client-side for you. In order to make Cloud Endpoints recognize Clams as objects, write a setClam (Clam clam) setter method, which can be public, protected, or private.
      • “Setter” methods must have the following properties:
        • The method name must begin with “set”
        • The object that you want to set must be in the parameters
          For example:

          setClam(Tree tree) is clearly setting a Tree, not a Clam – despite the method name claiming otherwise. This method will actually generate a class in the client, as well as getTree() and setTree(Tree) methods. It will not generate a setClam(Clam) method.

About Supported Types

  • Enums. Enums in your backend are generated as String representations in the client code. In other words, if you are making use of the enum functionality in both the backend and client, you will need to define the enum in both places.
  • Boolean – Getters often appear in a form such as “isLobster” in Java code, and Eclipse uses that convention when you right-click the field and go to Source > Generate Getters/Setters. However, be aware that Cloud Endpoints will generate “getLobster” in the client model.

API Methods

  • The attribute “name” for @Api annotation should start with a lowercase character. It should be formatted like a Java variable name—camel case, alphanumeric.
  • Static methods are not supported in your Endpoints classes. If you must have a static method, it should be made private.
  • If you do not specify the httpMethod attribute in @ApiMethod signature, Cloud Endpoints will make an educated guess for you, based on your method name.
  • Use the @ApiNamespace annotation for more control over your the package names of your library. Otherwise, your API will use the default package names.
  • Method parameters in the generated client library are in alphabetical order, regardless of the original order in the backend method. As a result, you should be careful when editing your methods, especially if there are several parameters of the same type. The compiler will not be able to catch parameter-ordering errors for you.
  • Empty Lists that are returned will arrive as nulls on the client-side. Remember to check for those.
  • Overloaded methods in a class are not supported.

About Supported Parameter Types

  • Most parameter types must be serializable because JSON requires that the objects be serializable.
    • You may also use any JavaBean, which includes anything from your model, since your model objects should conform to the JavaBean standard as described above.
  • A limited set of types need not be serializable, but must be annotated with @Named. These are the types: String, int/Integer, boolean/Boolean, long/Long.

About Supported Return Types

  • Return types must be serializable. The supported @Named method parameters (such as Strings and Booleans) are not supported as return types. One exception is that you can return a void, in which case the generated client-side method will return a Void.class.
  • Lists of serializable types. Actually, what Endpoints generates is a new “Collection” JSON class that is similar to every other client model class. For example, if you have an object in your model that is represented by, and you want to return a List<Lobster>, the library will have a You can retrieve the list of Lobsters in your client by calling getItems().
  • Maps of serializable types. Similar to the way it deals with Lists, Endpoints generates a “JsonMap” for Maps.
  • Subclass types will generate the interface type. For example, if your backend method returns an ArrayList, it will be a List in your client. Of course, you should probably be using the interface to define your variables and return types anyway, but be aware of this in cases where you want to use the subclass.

Generating Your Library

As you begin to generate your Cloud Endpoints API library, here are a few features that the Google Plugin for Eclipse can help you with:

  • Starting from scratch is very easy. When you first generate your App Engine backend from your Android project, Eclipse sets up the configurations to link the the two. These configurations tell Eclipse to put the new generated library code into the correct folder in your Android project. For more details, see the Generating Endpoints sections.
  • If you already have an App Engine application that you want to link up to your Android frontend, you’ll need to edit your Eclipse project settings.
    • In your Eclipse project for your Android client, there is a hidden folder called “.settings/”. The file in the settings folder should contain a line: “connectedProject=YourAppEngineBackend”, where “YourAppEngineBackend” is the name of your backend.
    • In your Eclipse project for your App Engine backend, there is also a hidden folder called “.settings/”. The file in the settings folder should contain a line: “connectedProject=YourAndroidClient”, where “YourAndroidClient” is the name of your frontend client.
  • Resolve errors when generating the Cloud Endpoint Library by looking at Eclipse’s Error Log. As you start developing with Cloud Endpoints, you might run into problems generating the library at first. You may encounter the error, “Generating Cloud Endpoint has encountered errors and is not complete.” You can see a much more complete description of the error by selecting Window > Show View > Error Log. Double-click on each error for a nice verbose output.
  • Make sure your Eclipse version has a Google Plugin that is compatible with the version of App Engine SDK. If you’re still running into odd errors such as “method not found” after reading the Error Log, it may be due to incompatibility between versions. When in doubt, update to the latest versions of the Google Plugin, App Engine SDK, and Android SDK. If there are still problems, try switching to newer versions of Eclipse.
  • Re-generate your library periodically, or after every major change. When you change your @ApiMethod name attribute, or anything else that causes client-side changes, you should update your library. Think of it this way: You are the engineer for both server code and client code. Sometimes you, the backend engineer, will make breaking changes, and you, the frontend engineer, will have to adapt.
  • Set up a local development environment if you want to test locally. When you generate the endpoint library, a class is automatically created for you, named CloudEndpointUtils. If you want to do local testing, remember to set LOCAL_ANDROID_RUN = true, and call CloudEndpointUtils.updateBuilder(builder) in every place that instantiates an endpoint service. This way, you can easily switch between local versus deployed versions by toggling the LOCAL_ANDROID_RUN variable.

Designing Your Model for the Datastore

Remember to make your model Datastore-compliant if you wish to use the easily-accessible persistent storage that Datastore offers, which plays so nicely with Cloud Endpoints. Take a look here for the full list of Datastore Properties and Types. The following describes some of the highlights and ambiguities of Datastore in more detail:

  • You have several choices for interacting with the Datastore. JPA/JDO provides an excellent abstraction layer for when your saved model is simple. The low-level Datastore API gives you more control over how your objects persist. If you use the low-level Datastore API, you can, and will need to, manually control changes to your model. This has upsides and downsides.
  • Empty lists persist as plain old nulls. It is worth noting that even if you check for these nulls and attach an empty List to the object that gets sent to the client, it will still arrive as null on the client.
  • For persisting groups of objects, remember that Datastore only takes objects of type Collection or its subclasses. The items in the Collection must be of one of the other supported types, or they must be serializable into a Blob.
  • No arrays. As mentioned above, Datastore will take values of type Collection, so make use of those instead of arrays.
  • Datastore does not distinguish between the sizes of the numbers, such as int32 and int64. For example, if you persist a List of Integers, it is stored as List<Long>.

Of course, you do not have to use the Datastore. One of the benefits of App Engine is that you can mix and match many Cloud services. Cloud SQL, JPA for example (which would be a great option) is available for you to use. Alternatively, you could explore Google BigQuery, if that is the type of data storage you need. And Google Cloud Storage is a good way to store a wide variety of types of data, as well.

Google Cloud Messaging

Google Cloud Messaging is pretty straightforward to use for basic purposes. Any known issues are documented here.

For First-time Android Developers

If you’re new to Android, you’ll find that Cloud Endpoints makes everything much simpler and allows you to focus your energies on the app itself, such as:

  • Make calls to your API asynchronously on non-UI threads. Android has one main thread (often referred to as the “UI thread”) running, so you do not want it to be bogged down and waiting for responses.
    • AsyncTasks are your friends. Note that AsyncTasks that are tied to an Activity can be destroyed when the Activity is destroyed, so it is up to you to make sure that all such behavior is intended. Search for articles regarding “AsyncTasks screen rotation,” for example, and you should find many ideas out there for dealing with this.
    • If you need to use an object that should be returned by the task, make use of the task’s onPostExecute override method. If you request a Lobster object from your API using an AsyncTask, and then immediately try to use it in your next line of code (for example, Lobster lobster = new GetLobsterAsyncTask().execute(lobsterName);;), you will receive an exception. So, not only will your lobster “not dance,” it will “throw a NullPointerException at you”.
    • If you want the UI to wait until the task returns, use a ProgressDialog in the onPreExecute and onPostExecute methods.
  • Keep track of Activity and Fragment lifecycles. If you’re having trouble with this at first, override a number of the important lifecycle methods and put debug Log statements in them, just to see whether and when your Activities are getting Paused, Resumed, Destroyed, and so on. Here is a full list of these methods, if you need them.
    • For example, when you start a second Activity with startActivityForResult, you’ll be able to see that the very first thing the lifecycle hits, when that second Activity finishes, is the onActivityResult in the first Activity – even before onCreate/Resume.
  • Starting a new Activity in the middle of a method does not excuse the rest of the line of logic from executing. This applies to startActivity, startActivityForResult, or anything else. Even though you cannot see it, the method will complete, as well as any other methods that it calls. The Activity containing the executing method does not go away until you destroy it or pop it off the stack.
  • Sometimes, you should just delete the file. Or, in other words: Clean and rebuild your project. Occasionally you’ll run into some issues where “you can’t cast Lobster into Tree.” “But I’m not trying to,” you say, “because that that’s silly—Lobsters and Trees aren’t even part of the same Kingdom!” It might mean that your file, which holds pointers to values defined in your res/ folder, got a little mixed up. Rebuilding should fix it.
  • Android layouts rules are not CSS rules. They can often be very similar, so you should feel very much at ease. However, sometimes there are minor differences. For example, margins do not collapse in Android, so check your facts before investing a lot of effort into your layout.
  • Dalvik is not really Java. Dalvik does use Java syntax, however, and Android supports a very large subset of the Standard Java libraries, such as java.util and You cannot import just any third-party Java library and expect it to play well with Android.
  • Creating a new Activity with Eclipse’s “Create a New” wizard generates/modifies five files:
    • AndroidManifest.xml (adds a new <activity> entry)
    • res/values/strings.xml (adds a title string for the activity)
    • res/menu/your_activity.xml (creates this file)
    • res/layout/your_activity.xml (creates this file)
    • (creates this file with some starter methods, such as onCreate override)
  • Use the standard Logger class for logging on App Engine. You can view the output in the App Engine Dashboard of the Google Cloud Platform Console. Android uses its own logging, and its output can be seen in one of the Eclipse views called “LogCat”.
  • If you’re hitting occasional EOFException errors, it is likely due to keepAlive connections on Android. You can find various solutions on StackOverflow.

Final Word

You’ve read through a lot of the specifics you may encounter, but the best way to learn is to jump right in. Cloud Endpoints is extremely flexible and intuitive. It takes on the burden of developing client-server interactions and protocols, and allows you to focus on developing your application logic. Best of all, it’s not in the way—after you begin to develop your application, getting your client to talk to your server is so easy that you forget that it was not always so simple.

Good luck!


@ApiMethod usage

There is a wonderful table here to guide you through annotating your API methods in Java. Here are a few additional, in-depth details:

The REST URI path of your endpoint prefers to use these attributes, in the following order:

  1. Your path attribute.
    • In path = lobsters: “lobsters” will become your REST path.
  2. The 2nd part of your “name” attribute.
    • In name = lobsters.assignName: “assignName” will become your REST path.
  3. Your method name.
    • In public void assignName(Lobster lobster): “assignName” will become your REST path.

Regarding your name attribute, think of the first part of this attribute as your resource class. Think of the second part as the method you want to perform. Here are a couple examples of the name attribute:

  • name = lobsters.assignName on your backend will be consumed with service.lobsters().assignName(param)in your client code.
  • name = lobsters on your backend will be consumed with service.lobsters(param)in your client code.

Example 1

With those rules in mind, here is a typical example of what a method might look like in your App Engine backend. Notice that the resource, lobster, is pluralized:

@ApiMethod(path = “lobsters/assign/{[a]name}[a]”, name = "lobsters.assignName",
httpMethod = HttpMethod.POST)
public void makeLobsterANewName(String name) {...}

Then the client library will generate the following code to use on your client:

public Lobsters lobsters() {...}
  public class Lobsters {
  public AssignName assignName(String name) {...}
  public class AssignName extends CloudmazeRequest {
    private static final String REST_PATH = “lobsters/assign/{name}”
    protected AssignName(String name) {...}

And to consume the endpoint, you can write the following code:

String name = “Bob the Lobster”;

Example 2

Here is a typical example of a simpler CRUD-type method for a Lobster resource in your App Engine backend. Notice that the resource, lobster, is pluralized, and that there is no HttpMethod attribute because the “update” method defaults to HttpMehod.PUT:

@ApiMethod(path = “lobsters”, name = "lobsters.update")
public void updateLobster(Lobster lobster) {...}

The client library then generates the following code to use on your client:

public Lobsters lobsters() {...}
  public class Lobsters {
  public Update update(String name) {...}
  public class Update extends CloudmazeRequest {
    private static final String REST_PATH = “lobsters”
    protected Update(String name) {...}

To consume the endpoint, you can write the following code:

Lobster bobLobster = new Lobster();

HttpMethod Defaults

Cloud Endpoints will make some smart decisions on which HttpMethod to use when a method name begins with certain key words. For example, setLobster defaults to httpMethod = HttpMethod.POST, unless otherwise specified.

Method Name


get, list


set, insert






Send feedback about...