Hello Endpoints Code Walkthrough

In this part of the tutorial, we'll look at the code you'll need to add in your own backend API, using the Hello Endpoints code to illustrate. The backend API is defined in the class file helloendpoints/src/main/java/com/google/appengine/samples/helloendpoints/Greetings.java.

In this sample, the backend API is implemented as a plain Java object, inheriting from Object. However, it can be part of a more complex class hierarchy if you want. (For backend APIs implemented in multiple classes, see Multiclass APIs).


Here are the imports for Greetings.java:

package com.example.helloendpoints;

import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.response.NotFoundException;
import com.google.appengine.api.users.User;

import java.util.ArrayList;

import javax.inject.Named;

You must always import com.google.api.server.spi.config.Api because you must always annotate your API class with @Api, as shown in the snippet. In this sample, we also import com.google.api.server.spi.config.ApiMethod because we want to illustrate its use in changing the name of a method, but this is optional; all public methods of the class with the @Api annotation are automatically exposed in the backend API.

We import com.google.appengine.api.users.User because we have a method protected by OAuth, and this import is required for that. We also import import javax.inject.Named because we need it for our request parameters.

API definition (configuration) using @Api

Let's look at the @Api annotation in Greetings.java:

 * Defines v1 of a helloworld API, which provides simple "greeting" methods.
@Api(name = "helloworld",
    version = "v1",
    scopes = {Constants.EMAIL_SCOPE},
    clientIds = {Constants.WEB_CLIENT_ID, Constants.ANDROID_CLIENT_ID, Constants.IOS_CLIENT_ID},
    audiences = {Constants.ANDROID_AUDIENCE}
public class Greetings {

  public static ArrayList<HelloGreeting> greetings = new ArrayList<HelloGreeting>();

  static {
    greetings.add(new HelloGreeting("hello world!"));
    greetings.add(new HelloGreeting("goodbye world!"));

This API is implemented in the single class called Greetings, with the API name and version always required. If you need to create an API that exposes multiple classes, you must use the same @Api annotation for each class. (The name and version would have to be identical for each class). For details on the attributes available, see @Api: API-Scoped Annotations or the Javadoc for @Api.

The sample protects a method by OAuth, which means that the scopes attribute is required; this must be set to the value https://www.googleapis.com/auth/userinfo.email, which is what Constants.EMAIL_SCOPE resolves to. (This scope lets OAuth work with Google Accounts.)

Also, because of the OAuth protection, we must supply a list of clients allowed to access the protected method in the clientIDs attribute. The sample suggests one way to do this, with lists of client IDs in the Constants.java file. So far, we have supplied a valid web client ID via Constants.java, but we have dummy values for Android and iOS clients to show that this client ID list could contain all the supported clients. Only clients in this list can access the protected method.

The audiences attribute is set to the backend API's web client. This attribute must be set if there are any Android clients; it is not used for non-Android clients.

Inside the class, notice the lines that set up an ArrayList of stored HelloGreeting (defined in HelloGreeting.java) JavaBean objects that are returned from the methods. In Endpoints, methods can only return Objects (treated as JavaBean objects) or a collection of Objects, which are converted to JSON to form the response.

A simple GET

The following lines return text greetings. Both getGreeting and listGreeting are public, so they will be exposed in the backend API:

public HelloGreeting getGreeting(@Named("id") Integer id) throws NotFoundException {
  try {
    return greetings.get(id);
  } catch (IndexOutOfBoundsException e) {
    throw new NotFoundException("Greeting not found with an index: " + id);

public ArrayList<HelloGreeting> listGreeting() {
  return greetings;

The getGreeting method serves an incoming GET request that has a numeric value indicating the user's choice of greeting:

  • A value of 0 returning the first value, hello world!.
  • A value of 1 returning the second value, goodbye world!.

All other values will return an error. Notice that the @Named attribute must be used for the incoming parameter since it is not an entity type.

The listGreeting method returns all the stored greetings in the array list.

A simple POST

The following lines of code handle an incoming POST request containing a user-supplied greeting and integer, and returns the greeting repeated the number of times specified by the integer:

@ApiMethod(name = "greetings.multiply", httpMethod = "post")
public HelloGreeting insertGreeting(@Named("times") Integer times, HelloGreeting greeting) {
  HelloGreeting response = new HelloGreeting();
  StringBuilder responseBuilder = new StringBuilder();
  for (int i = 0; i < times; i++) {
  return response;

This method is annotated by @ApiMethod so we can override the default name that is generated by Endpoints. Notice that Endpoints prepends the class name (greetings, lowercase) to the method name when it generates the method name in the backend API: greetings.insertGreeting. When we override this value using the method annotation, the prepending does not take place, so we need to add the class prepending manually in our code: greetings.multiply to make it consistent with the other backend API method names.

The method annotation can perform other API overrides as well; for more details, see @ApiMethod: Method-Scoped Annotations.

OAuth Protecting a method

Any client can access your Endpoints API methods unless you protect them with OAuth 2.0. In some scenarios, you may want to restrict access to some or all of the API methods.

To protect a method in the backend API, you need to do the following:

  • Add required support in the @Api annotation as described above:
    • Add scopes set to the email scope.
    • Add clientIds containing the client whitelist.
    • For Android devices only, specify audiences.
  • Add a User parameter to the method you wish to protect.

The code you copied already has the required annotations, so look at the code with the added User parameter:

@ApiMethod(name = "greetings.authed", path = "hellogreeting/authed")
public HelloGreeting authedGreeting(User user) {
  HelloGreeting response = new HelloGreeting("hello " + user.getEmail());
  return response;

When you declare a parameter of type User in your API method as shown in the snippet above, the API backend framework automatically authenticates the user and enforces the authorized clientIds whitelist, ultimately by supplying the valid User or not.

If the request coming in from the client has a valid auth token or is in the list of authorized clientIDs, the backend framework supplies a valid User to the parameter. If the incoming request does not have a valid auth token or if the client is not on the clientIDs whitelist, the framework sets User to null. Your own code must handle both the case where User is null and the case where there is a valid User. If there is no User, for example, you could choose to return a not-authenticated error or perform some other desired action.

Done with the tutorial: what's next?

Now that you've created your first backend APIs, take a deeper dive into backend API features and configurations, and you may want to hook up other App Engine services to your backend API, such as the Datastore. You can learn more by visiting the following resources:

  • Annotating Your Code; which covers all of the API configuration and features.
  • The Tic-Tac-Toe sample; which shows how to build a backend that uses the Datastore.

Send feedback about...

App Engine standard environment for Java