App Engine 用 Cloud Endpoints Frameworks バージョン 2.0 への移行

このページでは、既存の Cloud Endpoints バージョン 1.0 アプリケーションを、Java の App Engine 用 Endpoints Frameworks に移行する方法について説明します。

利点

新しいフレームワークには数多くの利点があります。

  • リクエスト レイテンシの短縮
  • App Engine の機能(カスタム ドメインなど)との統合強化
  • Guice 構成の正式サポート
  • 新しい API 管理機能(オプション)

Endpoints Frameworks バージョン 2.0 に移行しても、API のインターフェースには影響しません。既存のクライアントは、クライアント側コードを変更しなくても、移行後も引き続き動作します。

現時点で利用できない機能とツール

現在、以下の機能はご利用いただけません。これらのいずれかが必要な場合は、機能のリクエストを送信してください。

  • JSON-RPC プロトコル。レガシー iOS クライアントで必要になります。Endpoints Frameworks バージョン 2.0 API 用の iOS クライアントを作成する際には、REST API 用の Google API Objective-C クライアント ライブラリを使用することをおすすめします。
  • 自動 ETag
  • 自動 kind フィールド
  • IDE との統合
  • fields 部分応答
  • PATCH API メソッドの自動作成

また、Endpoints バージョン 1.0 用の Android Studio サポートは、現在のところバージョン 2.0 には対応していません。

Endpoints Frameworks バージョン 2.0 への移行

Endpoints Frameworks バージョン 2.0 は、グループ com.google.endpoints の Maven アーティファクトに移動しました。必要な基本 JAR は endpoints-framework アーティファクトに含まれています。Guice 構成を使用するには、endpoints-framework-guice アーティファクトを追加してください。

以下の手順は、ディスカバリ ドキュメントを使用して Endpoints Frameworks バージョン 1.0 から Endpoints Frameworks バージョン 2.0 に移行する方法の一例です。

  1. Google Cloud CLI をダウンロードして初期化します
  2. 次のコマンドを実行します。
    1. gcloud CLI が、Google Cloud にある対象のデータとサービスにアクセスできるよう許可されていることを確認します。
      gcloud auth login
    2. 次のアプリケーションのデフォルト認証情報を使用します。
      gcloud auth application-default login
    3. Google Cloud SDK app-engine-java のコンポーネントをインストールします。
      gcloud components install app-engine-java
    4. Google Cloud SDK とすべてのコンポーネントを最新バージョンに更新します。
      gcloud components update

Maven または Gradle を使用した移行

Maven

  1. 従来の依存関係(appengine-endpoints アーティファクト)を削除します。
    <dependency>
          <groupId>com.google.appengine</groupId>
          <artifactId>appengine-endpoints</artifactId>
          <version>1.9.53</version>
    </dependency>
  2. 新しい Endpoints Frameworks 依存関係を追加します。
    <dependency>
        <groupId>com.google.endpoints</groupId>
        <artifactId>endpoints-framework</artifactId>
        <version>2.2.1</version>
    </dependency>
  3. 新しい Endpoints Frameworks プラグインを追加し、生成するディスカバリ ドキュメントのホスト名を定義します。
    <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. 新しい App Engine Maven プラグインを追加します。
    <plugin>
        <groupId>com.google.cloud.tools</groupId>
        <artifactId>appengine-maven-plugin</artifactId>
        <version>1.3.2</version>
        <configuration>
            <!-- deploy configuration -->
        </configuration>
    </plugin>
  5. プロジェクトの web.xml ファイルで API のエントリ ポイントを更新します。
    • SystemServiceServlet をすべて EndpointsServlet に変更します。
    • パス /_ah/spi/ をすべて新しい必須パス /_ah/api/ に置き換えます。

    移行前後の web.xml の内容を次に示します。

    移行前

    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>

    移行後

    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. 依存関係を変更した後、プロジェクトをクリーンアップします。
    mvn clean
  7. ディスカバリ ドキュメントを生成します。
    mvn endpoints-framework:discoveryDocs
    Maven Endpoints Frameworks プラグインのゴールについては、こちらをご覧ください。
  8. プロジェクトをデプロイします。
    mvn appengine:deploy

    Maven App Engine プラグインの目標については、プラグインのゴールをご覧ください。

Gradle

  1. 従来の依存関係(appengine-endpoints アーティファクト)を削除します。
    compile group: 'com.google.appengine', name: 'appengine-endpoints', version: '+'
  2. 新しい Endpoints Frameworks 依存関係を追加します。
    compile group: 'com.google.endpoints', name: 'endpoints-framework', version: '2.0.8'
  3. 新しい App Engine プラグインと新しい Endpoints Frameworks プラグインを追加します。
    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. 新しい App Engine プラグインと新しい Endpoints Frameworks プラグインを適用します。
    apply plugin: 'com.google.cloud.tools.appengine'
    apply plugin: 'com.google.cloud.tools.endpoints-framework-server'
  5. 生成するディスカバリ ドキュメントのホスト名エンドポイントを定義します。
    endpointsServer {
      // Endpoints Framework Plugin server-side configuration
      hostname = "YOUR-PROJECT-ID.appspot.com"
    }
  6. プロジェクトの web.xml ファイルで API のエントリ ポイントを更新します。
    • SystemServiceServlet をすべて EndpointsServlet に変更します。
    • パス /_ah/spi/ をすべて新しい必須パス /_ah/api/ に置き換えます。

    移行前後の web.xml の内容を次に示します。

    移行前

    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>

    移行後

    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. 依存関係を変更した後、次のコマンドでプロジェクトをクリーンアップします。
    gradle clean
  8. ディスカバリ ドキュメントを生成するには、次のコマンドを使用します。
    gradle endpointsDiscoveryDocs
    Gradle Endpoints Frameworks プラグインのタスクについては、こちらをご覧ください。
  9. プロジェクトをデプロイするには、次のコマンドを使用します。
    gradle appengineDeploy

    Gradle App Engine プラグインのタスクについては、プラグインのタスクをご覧ください。

Guice を使用した Java 用 Endpoints Frameworks の構成

Guice を使用する場合:

  1. 新しい Endpoints Frameworks Guice 依存関係を追加します。

    Maven

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

    Gradle

    compile 'com.google.endpoints:endpoints-framework-guice:2.0.9'
  2. EndpointsModule を拡張する新しいモジュールを宣言し、次のように構成します。
    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));
      }
    }

新しいデプロイの確認

新しいフレームワークでトラフィックが処理されていることを確認できます。

  1. 新しいデプロイにリクエストをいくつか送信します。
  2. Google Cloud コンソールで、[Logging] > [ログ エクスプローラ] ページに移動します。

    [ログ エクスプローラ] ページに移動

  3. パスが /_ah/api で始まるリクエストがログに含まれている場合は、Endpoints Frameworks バージョン 2.0 が API を処理していることを示しています。パスが /_ah/spi で始まるリクエストがログに含まれていてはいけません。そのようなリクエストが含まれている場合は、Endpoints Frameworks バージョン 1.0 プロキシがリクエストを処理していることを示しています。

Endpoints API 管理の追加

Endpoints Frameworks バージョン 2.0 では、次のような API 管理機能を有効にすることもできます。

  • API キー管理
  • API 共有
  • ユーザー認証
  • API 指標
  • API ログ

これらの機能の使用にあたっては、API 管理の追加をご覧ください。

トラブルシューティング

このセクションでは、Endpoints Frameworks バージョン 2.0 への移行で発生する一般的なエラーと推奨される解決方法について説明します。

API から 404 エラーが返されるが、API Explorer では API が正しくリストされる

Endpoints Frameworks バージョン 2.0 に移行するときには、古い Endpoints Frameworks バージョン 1.0 の構成を削除する必要があります。古い構成がアプリケーション構成に残っていると、Endpoints サービスはアプリを引き続きバージョン 1.0 アプリとして扱います。/_ah/spi に送信されたリクエストが App Engine ログに記録されている場合、これはクライアントに HTTP 404 エラーが返されたことを示します。

  1. このようなエラーが発生した場合は、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>...</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>SystemServiceServlet</servlet-name>
        <url-pattern>/_ah/spi/*</url-pattern>
    </servlet-mapping>
    
  2. web.xml ファイルに次の記述が含まれていることを確認します。

    <servlet-mapping>
        <servlet-name>EndpointsServlet</servlet-name>
        <url-pattern>/_ah/api/*</url-pattern>
    </servlet-mapping>
    

API からのリフレクション エラー

endpoints-framework アーティファクトのみをアプリケーションにパッケージ化する必要があります。古い appengine-endpoints JAR は使用しません。両方の JAR が含まれるアプリケーションをデプロイすると、NoClassDefFoundErrorNoSuchMethodErrorClassCastException などのリフレクション エラーまたはランタイム エラーが発生する場合があります。このようなエラーが発生した場合は、ビルドファイルから次の行を削除します。

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: '+'

また、Guava の古いバージョンと依存関係がある場合は、欠落している TypeToken メソッドとして現れることもあります。この場合、Guava v19 を使用するか、依存関係をシャドウする endpoints-framework-all アーティファクトを使用します。

クライアント ライブラリ ソースがコンパイルされない

method does not override or implement a method from a supertypecannot find symbol method setBatchPath(String) などのエラーが発生する場合は、クライアント アプリケーションが古いバージョンの Google Java クライアント ライブラリに依存している可能性があります。google-api-client アーティファクトを 1.23.0 以降にする必要があります。

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'

JPA/JDO Datanucleus エンハンスメントに関する問題

Maven

新しい Google Cloud CLI ベースの App Engine Maven プラグインは、どのようなタイプの Datanucleus エンハンスメントもサポートしていません。プロジェクトで古いプラグインによる Datanucleus JDO または JPA のエンハンスメント サポートを使用している場合は、移行する際に、サードパーティの Datanucleus Maven プラグインを個別に構成する必要があります。詳しくは以下をご覧ください。

Gradle

プロジェクトで gradle-appengine-plugin の JPA / JDO Datanucleus エンハンスメントを使用している場合は、gcloud CLI ベースの Gradle プラグインへの切り替え後に、Datanucleus エンハンスメントを手動で構成する必要があります。Stack Overflow の例をご覧ください。