Migrating to Endpoints Frameworks for App Engine

This page describes migrating an existing Cloud Endpoints 1.0 app to Endpoints Frameworks for App Engine in Java. Note that this page refers to Cloud Endpoints 1.0 as Cloud Endpoints Frameworks version 1.0 and new Endpoints Frameworks for App Engine as Endpoints Frameworks version 2.0.

Benefits

The new framework brings a number of benefits, including:

  • Reduced request latency
  • Better integration with App Engine features (such as custom domains)
  • Official support for Guice configurations
  • Optionally, new API management features

Endpoints Frameworks 2.0 does not affect the interfaces to your API. Existing clients continue to work after migration without any client-side code changes.

Currently excluded features and tools

The following features are not currently available. If you require any of these, please submit a feature request.

  • JSON-RPC protocol, which is required for legacy iOS clients. To create iOS clients for your Endpoints Frameworks v2 API, we recommend that you use Google APIs Objective-C Client Library for REST APIs.
  • Automatic ETags
  • Automatic kind fields
  • IDE integration
  • fields partial responses
  • Automatic PATCH API method creation

In addition, the following tools are not currently supported for version 2.0:

  • Android Studio support for Cloud Endpoints 1.0

Migrating to Endpoints Frameworks 2.0 using a Discovery Document

Endpoints Frameworks 2.0 has moved to Maven artifacts in group com.google.endpoints. The base required JAR is in the endpoints-framework artifact. If you wish to use Guice configuration, add the endpoints-framework-guice artifact.

The following instructions provide an example of how to migrate from Cloud Endpoints Frameworks 1.0 to Endpoints Frameworks 2.0 using a Discovery Document:

  1. Download and initialize the Cloud SDK.
  2. Run the following commands:
    1. Make sure that Cloud SDK is authorized to access your data and services on Google Cloud Platform:
      gcloud auth login
    2. Use Application Default Credentials:
      gcloud auth application-default login
    3. Install the Cloud SDK app-engine-java component:
      gcloud components install app-engine-java
    4. Update to the latest version of Cloud SDK and all components:
      gcloud components update
  3. Migrate using Maven or Gradle:
  4. Maven

    1. Remove the legacy dependency, which is the appengine-endpoints artifact:
      <dependency>
            <groupId>com.google.appengine</groupId>
            <artifactId>appengine-endpoints</artifactId>
            <version>1.9.53</version>
      </dependency>
    2. Add the new Endpoints Frameworks dependency:
      <dependency>
          <groupId>com.google.endpoints</groupId>
          <artifactId>endpoints-framework</artifactId>
          <version>2.1.0</version>
      </dependency>
    3. Add the new Endpoints Frameworks plugin and define the hostname for a generated discovery document:
      <plugin>
          <groupId>com.google.cloud.tools</groupId>
          <artifactId>endpoints-framework-maven-plugin</artifactId>
          <version>1.0.2</version>
          <configuration>
              <!-- plugin configuration -->
              <hostname>YOUR-PROJECT-ID.appspot.com</hostname>
          </configuration>
      </plugin>
    4. Add the new App Engine Maven plugin:
      <plugin>
          <groupId>com.google.cloud.tools</groupId>
          <artifactId>appengine-maven-plugin</artifactId>
          <version>1.3.2</version>
          <configuration>
              <!-- deploy configuration -->
          </configuration>
      </plugin>
    5. Update the API entry point in your project web.xml file:
      • Rename all occurrences of SystemServiceServlet to EndpointsServlet
      • Replace all occurences of the path /_ah/spi/ to the new required path /_ah/api/

        The following code tabs show the contents of the web.xml before and after migration:

        Before Migration

        Cloud Endpoints Frameworks 1.0 web.xml:

        <servlet>
            <servlet-name>SystemServiceServlet</servlet-name>
            <servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
            <init-param>
                <param-name>services</param-name>
                <param-value>com.example.helloendpoints.Greetings</param-value>
            </init-param>
            <init-param>
                <param-name>restricted</param-name>
                <param-value>false</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>SystemServiceServlet</servlet-name>
            <url-pattern>/_ah/spi/*</url-pattern>
        </servlet-mapping>

        After Migration

        Cloud Endpoints Frameworks 2.0 web.xml:

        <servlet>
            <servlet-name>EndpointsServlet</servlet-name>
            <servlet-class>com.google.api.server.spi.EndpointsServlet</servlet-class>
            <init-param>
                <param-name>services</param-name>
                <param-value>com.example.helloendpoints.Greetings</param-value>
            </init-param>
            <init-param>
                <param-name>restricted</param-name>
                <param-value>false</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>EndpointsServlet</servlet-name>
            <url-pattern>/_ah/api/*</url-pattern>
        </servlet-mapping>

    6. After modifying dependencies clean the project using:
      mvn clean
    7. You can generate a discovery document by using:
      mvn endpoints-framework:discoveryDocs
      Learn more about the Maven Endpoints Framework plugin goals.
    8. You can deploy a project by using:
      mvn appengine:deploy

      Learn more about the Maven App Engine plugin goals.

    Gradle

    1. Remove the legacy dependency, which is the appengine-endpoints artifact:
      compile group: 'com.google.appengine', name: 'appengine-endpoints', version: '+'
    2. Add the new Endpoints Frameworks dependency:
      compile group: 'com.google.endpoints', name: 'endpoints-framework', version: '2.0.8'
    3. Add the new App Engine and Endpoints Frameworks plugins:
      buildscript {    // Configuration for building
        repositories {
          mavenCentral()
          jcenter()    // Bintray's repository - a fast Maven Central mirror & more
        }
        dependencies {
          // App Engine Gradle plugin
          classpath 'com.google.cloud.tools:appengine-gradle-plugin:1.3.3'
      
          // Endpoints Frameworks Gradle plugin
          classpath 'com.google.cloud.tools:endpoints-framework-gradle-plugin:1.0.2'
        }
      }
    4. Apply the new App Engine and Endpoints Frameworks plugins:
      apply plugin: 'com.google.cloud.tools.appengine'
      apply plugin: 'com.google.cloud.tools.endpoints-framework-server'
    5. Define the hostname endpoint for generated discovery documents:
      endpointsServer {
        // Endpoints Framework Plugin server-side configuration
        hostname = "YOUR-PROJECT-ID.appspot.com"
      }
    6. Update the API entry point in your project web.xml file:
      • Rename all occurrences of SystemServiceServlet to EndpointsServlet
      • Replace all occurences of the path /_ah/spi/ to the new required path /_ah/api/

        The following code tabs show the contents of the web.xml before and after migration:

        Before Migration

        Cloud Endpoints Frameworks 1.0 web.xml:

        <servlet>
            <servlet-name>SystemServiceServlet</servlet-name>
            <servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
            <init-param>
                <param-name>services</param-name>
                <param-value>com.example.helloendpoints.Greetings</param-value>
            </init-param>
            <init-param>
                <param-name>restricted</param-name>
                <param-value>false</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>SystemServiceServlet</servlet-name>
            <url-pattern>/_ah/spi/*</url-pattern>
        </servlet-mapping>

        After Migration

        Cloud Endpoints Frameworks 2.0 web.xml:

        <servlet>
            <servlet-name>EndpointsServlet</servlet-name>
            <servlet-class>com.google.api.server.spi.EndpointsServlet</servlet-class>
            <init-param>
                <param-name>services</param-name>
                <param-value>com.example.helloendpoints.Greetings</param-value>
            </init-param>
            <init-param>
                <param-name>restricted</param-name>
                <param-value>false</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>EndpointsServlet</servlet-name>
            <url-pattern>/_ah/api/*</url-pattern>
        </servlet-mapping>

    7. After modifying dependencies clean the project using:
      gradle clean
    8. You can generate a discovery document by using:
      gradle endpointsDiscoveryDocs
      Learn more about the Gradle Endpoints Framework plugin tasks
    9. You can deploy a project by using:
      gradle appengineDeploy

      Learn more about the Gradle App Engine plugin tasks.

Verifying a new deployment

You can verify that the new framework is serving traffic:

  1. Send some requests to the new deployment.
  2. Visit the log viewer for your project.
    View Google App Engine Application Logs
  3. If requests are shown with having paths beginning with /_ah/api, then Endpoints Frameworks 2.0 is now serving your API. The logs should not show any requests with paths beginning with /_ah/spi. These requests indicate that the Cloud Endpoints 1.0 proxy is still serving requests.

Using Guice to configure Cloud Endpoints Java Framework

If you wish to use Guice:

  1. Add the new Endpoints Frameworks Guice dependency:

    Maven

    <dependency>
        <groupId>com.google.endpoints</groupId>
        <artifactId>endpoints-framework-guice</artifactId>
        <version>2.1.0</version>
    </dependency>

    Gradle

    compile 'com.google.endpoints:endpoints-framework-guice:2.0.9'
  2. Declare a new module that extends `EndpointsModule`, and configure it, as follows:
    public class EchoEndpointModule extends EndpointsModule {
      @Override
      public void configureServlets() {
        super.configureServlets();
    
        bind(ServiceManagementConfigFilter.class).in(Singleton.class);
        filter("/_ah/api/*").through(ServiceManagementConfigFilter.class);
    
        Map<String, String> apiController = new HashMap<String, String>();
        apiController.put("endpoints.projectId", "YOUR-PROJECT-ID");
        apiController.put("endpoints.serviceName", "YOUR-PROJECT-ID.appspot.com");
    
        bind(GoogleAppEngineControlFilter.class).in(Singleton.class);
        filter("/_ah/api/*").through(GoogleAppEngineControlFilter.class, apiController);
    
        bind(Echo.class).toInstance(new Echo());
        configureEndpoints("/_ah/api/*", ImmutableList.of(Echo.class));
      }
    }

Adding Endpoints API Management

Cloud Endpoints Frameworks 2.0 also allows you to turn on API management features, including:

  • API key management
  • API sharing
  • User authentication
  • API metrics
  • API logs

To get started using these and other Cloud Endpoints Frameworks 2.0 features, navigate to the Endpoints Frameworks for App Engine using Java page.

Troubleshooting

This section describes common erratic behaviors whe migrating to Endpoints Frameworks 2.0 and suggested solutions.

API returns 404 errors, but API Explorer still lists APIs correctly

You are required to remove the old v1 Endpoints configuration when migrating to Endpoints Frameworks v2. If the old configuration is still present in the app configuration, the Endpoints service will continue to treat the app as a v1 app. You may see requests in your App Engine logs being sent to /_ah/spi, which result in HTTP 404 errors being sent to the client. Remove the following lines from your web.xml, if they are present:

<servlet>
    <servlet-name>SystemServiceServlet</servlet-name>
    <servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
    <init-param>
        <param-name>services</param-name>
        <param-value>...</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>SystemServiceServlet</servlet-name>
    <url-pattern>/_ah/spi/*</url-pattern>
</servlet-mapping>

API is throwing reflection errors

You must package only the endpoints-framework artifact into your app, not the old appengine-endpoints JAR. If you deploy an app with both JARs, you are likely to run into reflection errors or runtime type errors, such as NoClassDefFoundError, NoSuchMethodError, and ClassCastException. Remove the following lines from your build file, if they are present:

Maven

<dependency>
      <groupId>com.google.appengine</groupId>
      <artifactId>appengine-endpoints</artifactId>
      <version>1.9.53</version>
</dependency>

Gradle

compile group: 'com.google.appengine', name: 'appengine-endpoints', version: '+'

In addition, if any of your other dependencies depend on older versions of Guava, this can also manifest as a missing TypeToken method. You must ensure that you use Guava v19 or use the endpoints-framework-all artifact, which shadows dependencies.

Client library sources do not compile

If you see an error such as, "method does not override or implement a method from a supertype," or "cannot find symbol method setBatchPath(String)", then your client application likely depends on an old version of the Google Java client library. You must ensure that your google-api-client artifact is 1.23.0 or higher.

Maven

<dependency>
    <groupId>com.google.api-client</groupId>
    <artifactId>google-api-client</artifactId>
    <version>1.23.0</version>
</dependency>

Gradle

compile group: 'com.google.api-client', name: 'google-api-client', version: '1.23.0'

Issues with JPA/JDO Datanucleus enhancement

Maven

The new Cloud SDK-based App Engine Maven plugin does not support Datanucleus enhancement of any type. If your project uses the Datanucleus JDO or JPA enhancement support from the old plugin, you must configure the 3rd party Datanucleus Maven plugin separately when you migrate. See the following for more information:

Gradle

If your project uses the gradle-appengine-plugin JPA/JDO Datanucleus enhancement, you must manually configure Datanucleus enhancement after switching to the new Cloud SDK-based Gradle plugin. See an example from Stackoverflow.

Was this page helpful? Let us know how we did:

Send feedback about...

Cloud Endpoints Frameworks for App Engine