Google Cloud Endpoints	
                         & BigQuery	


appengine ja night #24
Ryo Yamasaki @vierjp	


                                        1
自己紹介	
Ryo Yamasaki	
  •  Blog
     •    http://blog.vier.jp/
  •  Twitter
     •    @vierjp
  •  仕事
     •    Javaでサーバーサイドの開発がメイン
     •    前職はスマホ向けサービス事業者の技術リーダー
     •    Google App Engineを中心にCloud StorageやBigQuery等、
          Google Cloud Platformのプロダクトを利用していました。
  •  個人でAndroidアプリ公開してます
     •    WiFi Tunes Sync

                                                          2
Google Cloud Endpoints	


              概要	




                           3
Google Cloud Endpoints	
一言で言えば・・・
AppEngineを
クライアントアプリのバックエンドとして
より簡単に使えるようにするための仕組み




                           4
Google Cloud Endpoints	
通信周りの実装が不要になります	
                Endpointsがカバーする範囲	
            クライアント	
                       サーバー側	


            GET・POSTパ
  必要な値を                  リクエストを        リクエストを
            ラメーターを
   取得	
                    送信	
         受け取る	
               セット	



                                                  リクエスト内
                                    サーバー側	
  
                                   API	
          容に基づい
            クライアント・ライブラリ	
                                    Framework	
    て処理	



                                       オブジェクト
  取得した結     JsonをParse
                         レスポンスを        をJson形式
  果を基に処     してオブジェ
                          受け取る	
       に変換して
   理を行う	
   クトにセット	
                                         返す	




                                                           5
Google Cloud Endpoints	
Android、iOS、JavaScript用クライアント・ライブラリを自動生成できる	




                   App	
  Engine	
  


                       Cloud	
  
                       Endpoints	


     Android	
         iOS	
           JavaScript	
  




                                                        6
Google Cloud Endpoints	
GoogleアカウントでのOAuth 2.0認証をサポート	




                                  7
Google Cloud Endpoints	
AppEngineの持つ各種サービスを利用可能	


                                       Cloud	
  
                                     Endpoints	
  




                                     AppEngine	
  




                                                                          Google	
  Cloud	
  
  Datastore	
     Url	
  Fetch	
        Mail	
       Task	
  Queues	
  
                                                                            Storage	
  




                                                                                                8
Google Cloud Endpoints	
作成したAPIはAPI Explorerから実行可能	
 •  Google APIs Discovery Serviceに準拠
 •  OAuth2認証した状態でのAPI実行も簡単
                               API実行画面	




   API一覧表示画面	




                                           9
Google Cloud Endpoints	


           実装手順	




                           10
Google Cloud Endpoints	
必要な環境 (Java)	
 •  Eclipse
 •  AppEngine SDK1.7.5以降
 •  Google Plugin for Eclipse (最新)




                                     11
Google Cloud Endpoints	
実装手順	
 1.  Eclipseプロジェクトの作成
 2.  サーバー側(バックエンド)の実装
 3.  API ExplorerでAPIの動作確認
 4.  クライアントライブラリの生成
 5.  クライアント側の実装
 	




                             12
Google Cloud Endpoints	
Eclipseプロジェクトの   バックエンドの     API	
  Explorerで    クライアントライ    クライアント側
        作成	
       実装	
        動作確認	
             ブラリの生成	
     の実装	




                 Androidクライアントを作る                        Androidクライアントを作ら
                         場合	
                                   ない場合	




                              2.右クリックから	
                                                             AppEngineの	
                            「Generate	
  AppEngine	
  
   1.Androidプロジェクトを作                                     「Webアプリケーションプロ
                                 Backend」	
             成	
                                               ジェクト」	
                           でサーバー側プロジェクト
                                                               を作成	
                                   作成	




                                                                            13
Google Cloud Endpoints	
Eclipseプロジェクトの            バックエンドの                API	
  Explorerで      クライアントライ       クライアント側
        作成	
                実装	
                   動作確認	
               ブラリの生成	
        の実装	


 @Api(name = "appData", version = "v1", description = "AppData API description v1")
 public class AppDataV1Endpoint {
                                                                      コード例
                                                              IDを指定してデータを1件取得する処理
 @ApiMethod(name = "data.get", path = "data/get/{id}”)
 public AppDataV1 get(String id) throws ServiceException {
                       @Named("id") String id) throws ServiceException {
      try {
           // Entityのget処理
           Key key = KeyFactory.createKey("AppData", id);
           DatastoreService ds = DatastoreServiceFactory.getDatastoreService();	
           Entity entity = ds.get(key);
           // 返却するDTOを生成してEntityの値を詰め替える	
                                                                ・ポイント
           AppDataV1 result = entity2Dto(entity);                ・@Api、@ApiMethod、@Namedアノテーション
           return result;                                        ・例外をthrowして呼び出し元にエラーを通知する
      } } catch (EntityNotFoundException e) {
            // IDに対応するデータが見つからない場合のエラー処理
            throw new NotFoundException("id:" + id + " is not found.");
        } catch (Exception e) {
            // 予期しないシステムエラーが発生した場合のエラー処理
            throw new InternalServerErrorException(e);
        }
  }


                                                                                                14
Google Cloud Endpoints	
Eclipseプロジェクトの    バックエンドの     API	
  Explorerで   クライアントライ    クライアント側
        作成	
        実装	
        動作確認	
            ブラリの生成	
     の実装	

 •    用意されているアノテーション	
 •    @Api
      •    クラスに定義する
      •    API群の一つのバージョンを示す (ex. Google Drive API v1)
      •    一つのAPIを複数バージョン定義する場合は別のクラスにする
 •    @ApiMethod
      •    メソッドに定義する
      •    個別のAPIを示す (ex. Google Drive APIの「drive.files.list」)
 •    @Named
      •    メソッド引数に定義する
      •    @ApiMethodのPathで「引数との対応」を指定しないなら必須
      •    Nullableを指定するなら必須
 •    @Nullable
      •    メソッド引数に定義する
      •    メソッド引数の値としてNullを許可する場合に指定	


                                                                       15
Google Cloud Endpoints	
Eclipseプロジェクトの          バックエンドの                   API	
  Explorerで          クライアントライ                   クライアント側
        作成	
              実装	
                      動作確認	
                   ブラリの生成	
                    の実装	


 •  @Api	
                  @Api(name = "appData", version = "v1", description = "AppData API description v1”)




  ・JavaScript
  gapi.client.appData.data.get({'id':$scope.id}).execute(function(response,rawResponseJson) {
     // callback
  });	

  ・Android
  AppData.Builder builder = new AppData.Builder(AndroidHttp.newCompatibleTransport(), new
  GsonFactory(), null);
  AppData appDataApi = CloudEndpointUtils.updateBuilder(builder).build();
  AppDataV1 response = appDataApi.data().get(id).execute();
  return response;	

                                                                                                                 16
Google Cloud Endpoints	
Eclipseプロジェクトの          バックエンドの                 API	
  Explorerで        クライアントライ                       クライアント側
        作成	
              実装	
                    動作確認	
                 ブラリの生成	
                        の実装	


 •  @ApiMethod	
                               @ApiMethod(name = "data.get", path = "data/get/{id}”)
                                               @ApiMethod(name = "data.put", path = "data/put”)
                                               	



                                                    ・ポイント
                                                     ・nameはAPIExplorerに表示される名前や
                                                      クライアントライブラリのメソッド(関数)名に影響するので
                                                      ルールを決めてわかりやすい名前をつけると良いかと。
                                                     ・Pathは内部的に実行されるAPIのPathに影響する。
                                                      →気にしないなら定義しなくてもOK

  ・JavaScript
  gapi.client.appData.data.get({'id':$scope.id}).execute(function(response,rawResponseJson) {
     // callback
  });	

  ・Android
  AppData.Builder builder = new AppData.Builder(AndroidHttp.newCompatibleTransport(), new
  GsonFactory(), null);
  AppData appDataApi = CloudEndpointUtils.updateBuilder(builder).build();
  AppDataV1 response = appDataApi.data().get(id).execute();
  return response;	
  	
                                                                                                                 17
Google Cloud Endpoints	
Eclipseプロジェクトの       バックエンドの            API	
  Explorerで   クライアントライ    クライアント側
        作成	
           実装	
               動作確認	
            ブラリの生成	
     の実装	

 エラーの通知に使用できる例外クラス
      BadRequestExcepRon	
  
      • 入力エラー等 (ステータスコード400)	

      UnauthorizedExcepRon	
  
      • 認証エラー (ステータスコード401)	

      ForbiddenExcepRon	
  
      • アクセス権限が無い (ステータスコード403)	

      NotFoundExcepRon	
  
      • 要求したデータが存在しない場合等 (ステータスコード404)	

      InternalServerErrorExcepRon	
  
      • システムエラー等 (ステータスコード500)	

      ServiceUnavailableExcepRon	
  
      • メンテナンス中 等 (ステータスコード503)	



                                                                                 18
Google Cloud Endpoints	
Eclipseプロジェクトの   バックエンドの   API	
  Explorerで   クライアントライ    クライアント側
        作成	
       実装	
      動作確認	
            ブラリの生成	
     の実装	


 •  例外クラスの自作
     •  com.google.api.server.spi.ServiceException
        を継承	
     •  実装例
     public class ConflictException extends ServiceException{
        public ConflictException(String message){
             super(409, message);
        }
     }



                                                                    19
Google Cloud Endpoints	
Eclipseプロジェクトの    バックエンドの      API	
  Explorerで   クライアントライ    クライアント側
        作成	
        実装	
         動作確認	
            ブラリの生成	
     の実装	


 •  ポイント
     •  API名(@Apiのname)は小文字から始める
     •  返り値としてリテラルは返せない。
     •  返り値としてAppEngineのEntity型も返せない。
     •  一覧取得処理でページングしたい場合は
        CollectionResponse<T>を使うと楽。
     •  以下はメソッド引数として定義すれば取得可能。
          •      javax.servlet.http.HttpServletRequest
          •      javax.servlet.ServletContext


                                                                        20
Google Cloud Endpoints	
Eclipseプロジェクトの   バックエンドの   API	
  Explorerで   クライアントライ    クライアント側
        作成	
       実装	
      動作確認	
            ブラリの生成	
     の実装	


 •  Tips:JUnitでサーバー側の単体テスト
     •  一般的なAppEngineアプリのクラスと同様に
        単体テストコードを書くことができます。
     •  Slim3のAppEngineTestCaseを使うのが簡単。
         (実装コード内でSlim3を使ってなくてもOK)




                                                                    21
Google Cloud Endpoints	
Eclipseプロジェクトの   バックエンドの   API	
  Explorerで   クライアントライ    クライアント側
        作成	
       実装	
      動作確認	
            ブラリの生成	
     の実装	

 •  API ExplorerでAPIの動作確認	
                                                •    入力項目はフォームに自
                                                     動で反映されます
                                                •    赤字は必須項目
                                                •    リクエスト内容を参照可能
                                                •    実行結果も参照可能
                                                •    OAuth2で認証してAPIを実
                                                     行することも可能	




                                                                    22
Google Cloud Endpoints	
Eclipseプロジェクトの     バックエンドの              API	
  Explorerで    クライアントライ             クライアント側
        作成	
         実装	
                 動作確認	
             ブラリの生成	
              の実装	


 •  Eclipseのプロジェクト右クリックから生成




 •  コマンドラインから生成
         sh	
  appengine-­‐java-­‐sdk-­‐1.7.5/bin/endpoints.sh	
  get-­‐java-­‐client-­‐lib	
  
                 	
  jp.vier.sample.endpoints.sample.v1.SampleEndpoint	




                                                                                                   23
Google Cloud Endpoints	
Eclipseプロジェクトの    バックエンドの   API	
  Explorerで   クライアントライ    クライアント側
        作成	
        実装	
      動作確認	
            ブラリの生成	
     の実装	


 •  ポイント
     •  コードが正しくない場合にはクライアントライ
        ブラリ生成時にエラーが発生する
     •  エラー内容は「エラー・ログ」(Error Log)
        ビューに表示される	
         •       Eclipseでよく使う「問題」 (Problems)ビューでは
                 無いので注意




                                                                     24
Google Cloud Endpoints	
Eclipseプロジェクトの      バックエンドの            API	
  Explorerで   クライアントライ            クライアント側
        作成	
          実装	
               動作確認	
            ブラリの生成	
             の実装	


 •  JavaScript 初期化処理(with AngularJS)
 <script type="text/javascript">
 var ENDPOINTS_ROOT = 'https://[your_app_id].appspot.com/_ah/api';

 function init() {
       // EndpointsのAPIを使うための初期化処理
       // (第一引数はサーバー側の@APIに定義したAPI名)	
     	
gapi.client.load(’appData', 'v1', function() {
             // angular init
             angular.bootstrap(document,['ui.bootstrap','my.filter']);
       }, ENDPOINTS_ROOT);
 }
 </script>
 <script src="https://apis.google.com/js/client.js?onload=init"></script>	




                                                                                        25
Google Cloud Endpoints	
Eclipseプロジェクトの      バックエンドの           API	
  Explorerで   クライアントライ         クライアント側
        作成	
          実装	
              動作確認	
            ブラリの生成	
          の実装	


 •  JavaScript 関数実行(with AngularJS)
 $scope.getAppData=function() {
   // API実行	
   gapi.client.appData.data.get({'id':$scope.id}).execute(function(response) {
      // レスポンスを受け取って処理する
      $scope.appData = response;
      $scope.$apply();
   });	

 ・JavaScriptの関数を呼び出すことでサーバーのAPIを実行して結果を取得できる。
 ・AngularJSでは値の変更を反映するために「$scope.$apply();」が必要。
  (AngularJSで「$http.get」を使った場合と違い、自動で反映されない)




                                                                                    26
Google Cloud Endpoints	
Eclipseプロジェクトの        バックエンドの             API	
  Explorerで   クライアントライ            クライアント側
        作成	
            実装	
                動作確認	
            ブラリの生成	
             の実装	

 •  JavaScript エラーハンドリング(with AngularJS)
 $scope.getAppData=function() {
     // API実行	
      gapi.client.appData.data.get({'id':$scope.id}).execute(function(response,rawResponseJson) {
        // for local
        if(response===false){
            var rawResponse = JSON.parse(rawResponseJson);
            // エラーダイアログを表示する	
            $scope.openErrorModal(rawResponse[0].error.message);
            $scope.$apply();
        // for production
        }else if(response.error && response.error.data && response.error.data.length > 0){
            // エラーダイアログを表示する	
            $scope.openErrorModal(response.error.data[0].message);
            $scope.$apply();
        // success                             ・エラーメッセージとhttpのステータスコードを取得できる。
        }else{                                 ・ローカル環境とProduction環境でエラー時の挙動が異なる。(バグ?)
            $scope.appData = response;         ・rawResponseJsonは本来不要だが、
            $scope.$apply();                    ローカル環境でエラーハンドリングする際に必要。
        }
     });
 }	
                                                                                                27
Google Cloud Endpoints	
Eclipseプロジェクトの    バックエンドの         API	
  Explorerで   クライアントライ      クライアント側
        作成	
        実装	
            動作確認	
            ブラリの生成	
       の実装	


 •  Android メソッド実行
 AppData.Builder builder = new AppData.Builder(AndroidHttp.newCompatibleTransport(),
 new GsonFactory(), null);
 AppData appDataApi = CloudEndpointUtils.updateBuilder(builder).build();
 AppDataV1 response = appDataApi.data().get(id).execute();



 ・生成されたクライアント・ライブラリを実行するだけで
  サーバー側の処理の返り値を取得できます。
 ・通常AsyncTaskの中で実行することになるでしょう。




                                                                                       28
Google Cloud Endpoints	
Eclipseプロジェクトの                             バックエンドの                                API	
  Explorerで                     クライアントライ                                クライアント側
        作成	
                                 実装	
                                   動作確認	
                              ブラリの生成	
                                 の実装	

 •  Android エラーハンドリング
 @Override	
  
 protected	
  AppDataV1	
  doInBackground(Void...	
  unused)	
  {	
  
 	
  	
  	
  	
  try	
  {	
  
 	
  	
  	
  	
  	
  	
  	
  	
  AppData.Builder	
  builder	
  =	
  new	
  AppData.Builder(AndroidHbp.newCompaRbleTransport(),	
  new	
  GsonFactory(),	
  null);	
  
 	
  	
  	
  	
  	
  	
  	
  	
  AppData	
  appDataApi	
  =	
  CloudEndpointURls.updateBuilder(builder).build();	
  
 	
  	
  	
  	
  	
  	
  	
  	
  AppDataV1	
  response	
  =	
  appDataApi.data().get(id).execute();	
  
 	
  	
  	
  	
  	
  	
  	
  	
  return	
  response;	
  
 	
  	
  	
  	
  }	
  catch	
  (final	
  GoogleJsonResponseExcepRon	
  e)	
  {	
  
 	
  	
  	
  	
  	
  	
  	
  	
  handler.post(new	
  Runnable()	
  {	
  
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  @Override	
  
                                                                                                                                                               ・サーバーから返されたエラーは
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  public	
  void	
  run()	
  {	
                                                                                 GoogleJsonResponseExceptionとしてcatchして
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  //	
  サーバー側で例外インスタンス生成時に渡したメッセージを取得する	
                                                                 String	
  resMessage	
  =	
  e.getDetails().getMessage();	
                                    エラーメッセージを取得する。
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Toast.makeText(context,	
  "Error:	
  "	
  +	
  resMessage,	
  Toast.LENGTH_LONG).show();	
  
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return;	
  
                                                                                                                                                               ・エラーメッセージの他にステータスコードも取得できる。
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
                                                                                                           ・IOExceptionは通信エラーとして処理する。
 	
  	
  	
  	
  	
  	
  	
  	
  });	
  
 	
  	
  	
  	
  	
  	
  	
  	
  return	
  null;	
  
 	
  	
  	
  	
  }	
  catch	
  (IOExcepRon	
  e)	
  {	
  
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  //	
  通信エラーのケース	
                                            handler.post(new	
  Runnable()	
  {	
  
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  @Override	
  
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  public	
  void	
  run()	
  {	
  
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Toast.makeText(context,	
  “通信エラーが発生しました。ネットワーク状態を確認してください。",	
  Toast.LENGTH_LONG).show();	
  
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return;	
  
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
 	
  	
  	
  	
  	
  	
  	
  	
  });	
  
 	
  	
  	
  	
  	
  	
  	
  	
  return	
  null;	
  

 	
 	
  	
  	
  	
  }	
  
 }



                                                                                                                                                                                                        29
Google Cloud Endpoints	
Eclipseプロジェクトの   バックエンドの   API	
  Explorerで   クライアントライ    クライアント側
        作成	
       実装	
      動作確認	
            ブラリの生成	
     の実装	


 •  ポイント
     •  関数やメソッドを実行するだけで、内部的に
        サーバー側のAPIを実行して返り値を取得
        できます。
     •  クライアント側の実装方法はGoogleが提供
        するAPIの使い方とほとんど同じなので、
       困ったときはGoogle APIの使い方をググる
       と良いかもしれません。
         •       Endpointsの情報に比べると情報がたくさんあり
                 ます。

                                                                    30
Google Cloud Endpoints	
Eclipseプロジェクトの   バックエンドの   API	
  Explorerで   クライアントライ    クライアント側
        作成	
       実装	
      動作確認	
            ブラリの生成	
     の実装	

 Tips:Androidの実機からローカルサーバーに接続してテ
 ストする方法
 •  Android側はCloudEndpointUtilsを使う
      •    「Generate AppEngine Backend」をすると生成される。
      •    使い方は 前述の「Android メソッド実行」を参照。	
      •    CloudEndpointUtils#LOCAL_ANDROID_RUNをtrueにする。


 •    サーバー側はデバッグ設定を変更
      •    デバッグの構成 -> 引数タブ -> 「プログラムの引数」に
             「--address=0.0.0.0 」を追加する。



                                                                    31
Google Cloud Endpoints	


         OAuth2認証	




                           32
Google Cloud Endpoints	
OAuth2: ClientIDの生成	
 APIs Console -> API Accessで以下のように設定	
JavaScript用             Android用




                                         33
Google Cloud Endpoints	
OAuth2: サーバー側の実装例	
/** Web用ClientId */
private static final String CLIENT_ID_WEB = "10*********09-7ufji**********k2a91.apps.googleusercontent.com";
/** Android用ClientId */
private static final String CLIENT_ID_ANDROID = "10*********09-
o4e8d**********gt2ts3.apps.googleusercontent.com";
/** Android用Audience */
private static final String AUDIENCE_ANDROID = CLIENT_ID_WEB;

@ApiMethod(                                                 OAuth2認証を利用する場合はClientIDの定義は必須。
                                                            ここに定義したClientID以外で認証して取得したTokenでアクセスした
                name = "data.put",                          場合、引数「user」はnullになる。(認証してないものとして扱われる)
                path = "data/put",                          Androidで認証してアクセスする場合のみ「audiences」の指定が必要。

                clientIds = {CLIENT_ID_WEB, CLIENT_ID_ANDROID },
                audiences = AUDIENCE_ANDROID)
public AppDataV2 put(AppDataV2 appDataV2, User user) throws ServiceException {
    // 認証チェック	
                                                       com.google.appengine.api.users.User型の引数を定
                                                                      義すると、
   if (user == null) {                                                OAuth2認証済みの場合に
       throw new UnauthorizedException(“ログインが必要です。");                 Userクラスにユーザー情報がセットされる。

    }
    // データの登録処理                                        認証チェックはuserがnullかどうかで判定し、
}	
                                                    UnauthorizedExceptionをthrowする。

*実際には定数は別のクラスに定義した方が複数バージョンの対応等で使い勝手が良いです。

                                                                                                                  34
Google Cloud Endpoints	
OAuth2: JavaScriptの実装例	
var	
  mainCtrl	
  =	
  	
  funcRon($scope)	
  {	
  
	
  
	
  	
  var	
  CLIENT_ID	
  =	
  '10*********09-­‐7uri**********k2a91.apps.googleusercontent.com';	
  
	
  	
  var	
  SCOPES	
  =	
  'hbps://www.googleapis.com/auth/userinfo.email’;	
  
	
  	
  //	
  OAuthライブラリをloadして自動で認証を試みる	
                                                   ・Web用のClient_IDを使用
	
  	
  gapi.client.load('oauth2',	
  'v2',	
  funcRon(response)	
  {	
                      ・scopeは最低限「userinfo.email」が必要	
	
  	
  	
  	
  	
  	
  	
  	
  $scope.signin(true,	
  $scope.userAuthed);	
  
	
  	
  });	
                                                                                ・認証処理の実行	
	
  	
  //	
  OAuth認証関数	
                                                                    ・画面表示時に「可能であれば自動認証」する	
  
	
  	
  $scope.signin=funcRon(mode)	
  {	
                                                    際は「immediate:	
  true」にする。	
  
	
  	
  	
  	
  	
  	
  	
  	
  gapi.auth.authorize({client_id:	
  CLIENT_ID,	
              ・ボタン押下等で明示的に認証する場合は	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  scope:	
  SCOPES,	
  immediate:	
  mode,	
    「immediate:	
  false」にする。	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  response_type:	
  'token	
  id_token'},	
  
                                                                                             	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  $scope.userAuthed);	
  
                                                                                             	
  
	
  	
  };	
                                                                                 ・認証処理完了時のcallbackで	
	
  	
  //	
  認証後にユーザー情報を取得するcallback関数	
                                                    	
  
	
  	
  $scope.userAuthed	
  =	
  funcRon()	
  {	
                                                              ユーザー情報の取得とTokenの設定を行う。
	
  	
  	
  	
  	
  	
  	
  	
  var	
  request	
  =	
  gapi.client.oauth2.userinfo.get().execute(funcRon(response)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (!response.code)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  var	
  token	
  =	
  gapi.auth.getToken();	
  
                                                                                                               ・サインアウトは「gapi.auth.setToken(null);」でOK。	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  token.access_token	
  =	
  token.id_token;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  gapi.auth.setToken(token);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  //	
  User情報を取得	
                                                                 $scope.user=response;	
                                    ・明示的なSign	
  in処理の呼び出し部分	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  //	
  反映させる	
                                                                 $scope.$apply();	
                                         <a	
  ng-­‐click="signin(false);">	
  Sign	
  In	
  </a>	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  });	
  
	
  	
  	
  	
  }	
  
}	
  
	
                                                                                                                                                                                         35
Google Cloud Endpoints	
OAuth2: Androidの実装例 (Credentialの管理)	
private	
  staRc	
  final	
  String	
  CLIENT_ID	
  =	
  
"10*********09-­‐7uri**********k2a91.apps.googleusercontent.com";	
  
	
                                                                         ・サーバー側でAudienceに指定したClient_IDを指定
private	
  GoogleAccountCredenRal	
  credenRal;	
  
	
                                                                         Credentialの定義
@Override	
  
protected	
  void	
  onCreate(Bundle	
  savedInstanceState)	
  {	
  
	
  	
  	
  	
  super.onCreate(savedInstanceState);	
  
	
  	
  	
  	
  setContentView(R.layout.acRvity_main);	
  
                                                                           Credentialを生成する。
	
  
	
  	
  	
  	
  //	
  CredenRalを生成する	
                credenRal	
  =	
  GoogleAccountCredenRal.usingAudience(this,	
  "server:client_id:"	
  +	
  CLIENT_ID);	
  
}	
  
	
  
private	
  void	
  setAccountName(String	
  accountName)	
  {	
            認証情報をCredinRalにセットする。	
  
	
  	
  	
  	
  //	
  CredenRalにアカウント名をセット	
                credenRal.setSelectedAccountName(accountName);	
  
}	
  
	
  	
  
                                                                                                                              36
Google Cloud Endpoints	
OAuth2: Androidの実装例 (アカウント選択)	
//	
  「Googleアカウント選択用Picker」を表示する	
private	
  void	
  chooseAccount()	
  {	
  
	
  	
  	
  	
  startAcRvityForResult(credenRal.newChooseAccountIntent(),	
  REQUEST_ACCOUNT_PICKER);	
  
}	
  
	
  
@Override	
  
protected	
  void	
  onAcRvityResult(int	
  requestCode,	
  int	
  resultCode,	
  Intent	
  data)	
  {	
  
	
  	
  	
  	
  super.onAcRvityResult(requestCode,	
  resultCode,	
  data);	
  
	
  	
  	
  	
  switch	
  (requestCode)	
  {	
  
	
  	
  	
  	
  //	
  「Googleアカウント選択用Picker」の選択結果を取得する	
                case	
  REQUEST_ACCOUNT_PICKER:	
  
	
  	
  	
  	
  	
  	
  	
  	
  if	
  (data	
  !=	
  null	
  &&	
  data.getExtras()	
  !=	
  null)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  Bundle	
  bundle	
  =	
  data.getExtras();	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  String	
  accountName	
  =	
  bundle.getString(AccountManager.KEY_ACCOUNT_NAME);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  if	
  (accountName	
  !=	
  null)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  //	
  CredenRalにアカウント名をセット	
                                                                setAccountName(accountName);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  break;	
  
	
  	
  	
  	
  }	
  
}	
  

                                                                                                                                       37
Google Cloud Endpoints	
OAuth2: Androidの実装例 (クライアントライブラリ実行)	
AppData.Builder	
  builder	
  =	
  new	
  AppData.Builder(	
  
	
  	
  	
  	
  	
  	
  	
  AndroidHbp.newCompaRbleTransport(),	
  
	
  	
  	
  	
  	
  	
  	
  new	
  GsonFactory(),	
  
	
  	
  	
  	
  	
  	
  	
  	
  credenRal);	
  
AppData	
  appDataApi	
  =	
  CloudEndpointURls.updateBuilder(builder).build();	
  



                   認証情報を使用してAPIを実行する場合には、	
                   Credentialを引数に渡す。	
                   (認証情報が不要な場合にはnullを渡せばOK)




                                                                                      38
Google Cloud Endpoints	
OAuth2: サーバーに渡せるTokenは二種類ある	
Id_token	
                       access_token	
公式サンプルが使用している形式	
                API	
  Explorerが使用している形式(*1)	
  
ドキュメントに書かれている形式	
                ドキュメントに書かれてない形式(*2)	
  
User情報からEmailアドレスと               User情報からUserId、Email、
NickNameのみ取得できる (*3)	
           NickName、AuthDomainを取得できる	
認証したユーザーの権限をサーバー                 認証したユーザーの権限をサーバー
側で行使できない(たぶん)	
                  側で行使できる(若干強引に)(*4)	
Token生成に使用したClientIDのチェッ Id_token同様にチェックが行われる。	
  
クが行われる(Token	
  swap	
  aback対策)	
 (ただしAPI	
  Explorerは無条件で許可)	
*1 認証に関してはドキュメント通りのJS・Android実装とAPI Explorerで挙動が異なります。
*2 Endpointsのドキュメントに書かれていない方式なので継続的にサポートされるか不明。
*3 id_tokenを使った場合にUserIDを取得できない事に関してはissueが上げられて
  Acceptedになっているのでバグとして修正されるかもしれません。
*4 Endpointsの機能としてTokenやCredentialを取得する仕組みは無いようです。
  HttpServletRequest#getHeaderメソッドでaccess_token文字列を直接取得する必要があります。
各クライアント・Tokenタイプによる挙動に関する詳細は「http://goo.gl/44vNj」を参照。	


                                                                    39
Google Cloud Endpoints	
デモ (JavaScript & Android)	
•  サーバー側API
   •  一覧取得
   •  メッセージ投稿(要認証)
•  クライアント
   •  一覧取得
   •  メッセージ投稿
   •  認証機能



                              40
Google Cloud Endpoints	
参考リンク	
•    公式ドキュメント
     •    http://goo.gl/6wp7R
•    公式サンプル (tictactoe)
     •    Android - http://goo.gl/xjX1B
     •    Backend & JS- http://goo.gl/V8MEV
•    API Explorer
     •    https://developers.google.com/apis-explorer/#s/
•    Google APIs Discovery Service
     •    https://developers.google.com/discovery/?hl=ja
•    APIs Console
     •    https://code.google.com/apis/console/
•    Blog @vierjp 「Google Cloud Endpointsを試してみた」
     •    http://blog.vier.jp/2013/02/google-cloud-endpoints-12.html


                                                                       41
BigQuery	
新機能のデモ	
•  Small JOINと Big JOIN
•  GROUP BYとGROUP EACH BY




*デモの内容はブログ( http://goo.gl/jJnuR )の解説と同じです。




                                             42
BigQuery	
参考リンク	
•    BigQuery 公式ドキュメント
     •    https://developers.google.com/bigquery/
•    BigQuery Query Reference (JOIN)
     •    http://goo.gl/LKEZq
•    BigQuery Query Reference (GROUP BY)
     •    http://goo.gl/EI2aK
•    Google Developers Blog (BigQuery gets big new
     features to make data analysis even easier)
     •    http://goo.gl/Unwmq
•    Blog @vierjp 「BigQueryの新機能 (2013/03/15)」
     •    http://blog.vier.jp/2013/03/bigquery-20130315.html


                                                               43
Google Cloud Endpoints & BigQuery	

  ご清聴ありがとうございました

     時間の都合で扱えなかった細かい内容はブログで!
            http://blog.vier.jp/	




                                      44

appengine ja night #24 Google Cloud Endpoints and BigQuery

  • 1.
    Google Cloud Endpoints & BigQuery appengine ja night #24 Ryo Yamasaki @vierjp 1
  • 2.
    自己紹介 Ryo Yamasaki •  Blog •  http://blog.vier.jp/ •  Twitter •  @vierjp •  仕事 •  Javaでサーバーサイドの開発がメイン •  前職はスマホ向けサービス事業者の技術リーダー •  Google App Engineを中心にCloud StorageやBigQuery等、 Google Cloud Platformのプロダクトを利用していました。 •  個人でAndroidアプリ公開してます •  WiFi Tunes Sync 2
  • 3.
  • 4.
  • 5.
    Google Cloud Endpoints 通信周りの実装が不要になります Endpointsがカバーする範囲 クライアント サーバー側 GET・POSTパ 必要な値を リクエストを リクエストを ラメーターを 取得 送信 受け取る セット リクエスト内 サーバー側   API 容に基づい クライアント・ライブラリ Framework て処理 オブジェクト 取得した結 JsonをParse レスポンスを をJson形式 果を基に処 してオブジェ 受け取る に変換して 理を行う クトにセット 返す 5
  • 6.
  • 7.
  • 8.
    Google Cloud Endpoints AppEngineの持つ各種サービスを利用可能 Cloud   Endpoints   AppEngine   Google  Cloud   Datastore   Url  Fetch   Mail   Task  Queues   Storage   8
  • 9.
    Google Cloud Endpoints 作成したAPIはAPIExplorerから実行可能 •  Google APIs Discovery Serviceに準拠 •  OAuth2認証した状態でのAPI実行も簡単 API実行画面 API一覧表示画面 9
  • 10.
    Google Cloud Endpoints 実装手順 10
  • 11.
    Google Cloud Endpoints 必要な環境(Java) •  Eclipse •  AppEngine SDK1.7.5以降 •  Google Plugin for Eclipse (最新) 11
  • 12.
    Google Cloud Endpoints 実装手順 1.  Eclipseプロジェクトの作成 2.  サーバー側(バックエンド)の実装 3.  API ExplorerでAPIの動作確認 4.  クライアントライブラリの生成 5.  クライアント側の実装 12
  • 13.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 Androidクライアントを作る Androidクライアントを作ら 場合 ない場合 2.右クリックから AppEngineの 「Generate  AppEngine   1.Androidプロジェクトを作 「Webアプリケーションプロ Backend」 成 ジェクト」 でサーバー側プロジェクト を作成 作成 13
  • 14.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 @Api(name = "appData", version = "v1", description = "AppData API description v1") public class AppDataV1Endpoint { コード例 IDを指定してデータを1件取得する処理 @ApiMethod(name = "data.get", path = "data/get/{id}”) public AppDataV1 get(String id) throws ServiceException { @Named("id") String id) throws ServiceException { try { // Entityのget処理 Key key = KeyFactory.createKey("AppData", id); DatastoreService ds = DatastoreServiceFactory.getDatastoreService(); Entity entity = ds.get(key); // 返却するDTOを生成してEntityの値を詰め替える ・ポイント AppDataV1 result = entity2Dto(entity);  ・@Api、@ApiMethod、@Namedアノテーション return result;  ・例外をthrowして呼び出し元にエラーを通知する } } catch (EntityNotFoundException e) { // IDに対応するデータが見つからない場合のエラー処理 throw new NotFoundException("id:" + id + " is not found."); } catch (Exception e) { // 予期しないシステムエラーが発生した場合のエラー処理 throw new InternalServerErrorException(e); } } 14
  • 15.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  用意されているアノテーション •  @Api •  クラスに定義する •  API群の一つのバージョンを示す (ex. Google Drive API v1) •  一つのAPIを複数バージョン定義する場合は別のクラスにする •  @ApiMethod •  メソッドに定義する •  個別のAPIを示す (ex. Google Drive APIの「drive.files.list」) •  @Named •  メソッド引数に定義する •  @ApiMethodのPathで「引数との対応」を指定しないなら必須 •  Nullableを指定するなら必須 •  @Nullable •  メソッド引数に定義する •  メソッド引数の値としてNullを許可する場合に指定 15
  • 16.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  @Api @Api(name = "appData", version = "v1", description = "AppData API description v1”) ・JavaScript gapi.client.appData.data.get({'id':$scope.id}).execute(function(response,rawResponseJson) { // callback }); ・Android AppData.Builder builder = new AppData.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), null); AppData appDataApi = CloudEndpointUtils.updateBuilder(builder).build(); AppDataV1 response = appDataApi.data().get(id).execute(); return response; 16
  • 17.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  @ApiMethod @ApiMethod(name = "data.get", path = "data/get/{id}”) @ApiMethod(name = "data.put", path = "data/put”) ・ポイント  ・nameはAPIExplorerに表示される名前や   クライアントライブラリのメソッド(関数)名に影響するので   ルールを決めてわかりやすい名前をつけると良いかと。  ・Pathは内部的に実行されるAPIのPathに影響する。   →気にしないなら定義しなくてもOK ・JavaScript gapi.client.appData.data.get({'id':$scope.id}).execute(function(response,rawResponseJson) { // callback }); ・Android AppData.Builder builder = new AppData.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), null); AppData appDataApi = CloudEndpointUtils.updateBuilder(builder).build(); AppDataV1 response = appDataApi.data().get(id).execute(); return response; 17
  • 18.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 エラーの通知に使用できる例外クラス BadRequestExcepRon   • 入力エラー等 (ステータスコード400) UnauthorizedExcepRon   • 認証エラー (ステータスコード401) ForbiddenExcepRon   • アクセス権限が無い (ステータスコード403) NotFoundExcepRon   • 要求したデータが存在しない場合等 (ステータスコード404) InternalServerErrorExcepRon   • システムエラー等 (ステータスコード500) ServiceUnavailableExcepRon   • メンテナンス中 等 (ステータスコード503) 18
  • 19.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  例外クラスの自作 •  com.google.api.server.spi.ServiceException を継承 •  実装例 public class ConflictException extends ServiceException{ public ConflictException(String message){ super(409, message); } } 19
  • 20.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  ポイント •  API名(@Apiのname)は小文字から始める •  返り値としてリテラルは返せない。 •  返り値としてAppEngineのEntity型も返せない。 •  一覧取得処理でページングしたい場合は CollectionResponse<T>を使うと楽。 •  以下はメソッド引数として定義すれば取得可能。 •  javax.servlet.http.HttpServletRequest •  javax.servlet.ServletContext 20
  • 21.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  Tips:JUnitでサーバー側の単体テスト •  一般的なAppEngineアプリのクラスと同様に 単体テストコードを書くことができます。 •  Slim3のAppEngineTestCaseを使うのが簡単。 (実装コード内でSlim3を使ってなくてもOK) 21
  • 22.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  API ExplorerでAPIの動作確認 •  入力項目はフォームに自 動で反映されます •  赤字は必須項目 •  リクエスト内容を参照可能 •  実行結果も参照可能 •  OAuth2で認証してAPIを実 行することも可能 22
  • 23.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  Eclipseのプロジェクト右クリックから生成 •  コマンドラインから生成 sh  appengine-­‐java-­‐sdk-­‐1.7.5/bin/endpoints.sh  get-­‐java-­‐client-­‐lib    jp.vier.sample.endpoints.sample.v1.SampleEndpoint 23
  • 24.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  ポイント •  コードが正しくない場合にはクライアントライ ブラリ生成時にエラーが発生する •  エラー内容は「エラー・ログ」(Error Log) ビューに表示される •  Eclipseでよく使う「問題」 (Problems)ビューでは 無いので注意 24
  • 25.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  JavaScript 初期化処理(with AngularJS) <script type="text/javascript"> var ENDPOINTS_ROOT = 'https://[your_app_id].appspot.com/_ah/api'; function init() { // EndpointsのAPIを使うための初期化処理 // (第一引数はサーバー側の@APIに定義したAPI名) gapi.client.load(’appData', 'v1', function() { // angular init angular.bootstrap(document,['ui.bootstrap','my.filter']); }, ENDPOINTS_ROOT); } </script> <script src="https://apis.google.com/js/client.js?onload=init"></script> 25
  • 26.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  JavaScript 関数実行(with AngularJS) $scope.getAppData=function() { // API実行 gapi.client.appData.data.get({'id':$scope.id}).execute(function(response) { // レスポンスを受け取って処理する $scope.appData = response; $scope.$apply(); }); ・JavaScriptの関数を呼び出すことでサーバーのAPIを実行して結果を取得できる。 ・AngularJSでは値の変更を反映するために「$scope.$apply();」が必要。  (AngularJSで「$http.get」を使った場合と違い、自動で反映されない) 26
  • 27.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  JavaScript エラーハンドリング(with AngularJS) $scope.getAppData=function() { // API実行 gapi.client.appData.data.get({'id':$scope.id}).execute(function(response,rawResponseJson) { // for local if(response===false){ var rawResponse = JSON.parse(rawResponseJson); // エラーダイアログを表示する $scope.openErrorModal(rawResponse[0].error.message); $scope.$apply(); // for production }else if(response.error && response.error.data && response.error.data.length > 0){ // エラーダイアログを表示する $scope.openErrorModal(response.error.data[0].message); $scope.$apply(); // success ・エラーメッセージとhttpのステータスコードを取得できる。 }else{ ・ローカル環境とProduction環境でエラー時の挙動が異なる。(バグ?) $scope.appData = response; ・rawResponseJsonは本来不要だが、 $scope.$apply();  ローカル環境でエラーハンドリングする際に必要。 } }); } 27
  • 28.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  Android メソッド実行 AppData.Builder builder = new AppData.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), null); AppData appDataApi = CloudEndpointUtils.updateBuilder(builder).build(); AppDataV1 response = appDataApi.data().get(id).execute(); ・生成されたクライアント・ライブラリを実行するだけで  サーバー側の処理の返り値を取得できます。 ・通常AsyncTaskの中で実行することになるでしょう。 28
  • 29.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  Android エラーハンドリング @Override   protected  AppDataV1  doInBackground(Void...  unused)  {          try  {                  AppData.Builder  builder  =  new  AppData.Builder(AndroidHbp.newCompaRbleTransport(),  new  GsonFactory(),  null);                  AppData  appDataApi  =  CloudEndpointURls.updateBuilder(builder).build();                  AppDataV1  response  =  appDataApi.data().get(id).execute();                  return  response;          }  catch  (final  GoogleJsonResponseExcepRon  e)  {                  handler.post(new  Runnable()  {                          @Override   ・サーバーから返されたエラーは                        public  void  run()  {    GoogleJsonResponseExceptionとしてcatchして                                //  サーバー側で例外インスタンス生成時に渡したメッセージを取得する String  resMessage  =  e.getDetails().getMessage();   エラーメッセージを取得する。                                Toast.makeText(context,  "Error:  "  +  resMessage,  Toast.LENGTH_LONG).show();                                  return;   ・エラーメッセージの他にステータスコードも取得できる。                        }   ・IOExceptionは通信エラーとして処理する。                });                  return  null;          }  catch  (IOExcepRon  e)  {                        //  通信エラーのケース handler.post(new  Runnable()  {                          @Override                          public  void  run()  {                                  Toast.makeText(context,  “通信エラーが発生しました。ネットワーク状態を確認してください。",  Toast.LENGTH_LONG).show();                                  return;                          }                  });                  return  null;          }   } 29
  • 30.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 •  ポイント •  関数やメソッドを実行するだけで、内部的に サーバー側のAPIを実行して返り値を取得 できます。 •  クライアント側の実装方法はGoogleが提供 するAPIの使い方とほとんど同じなので、   困ったときはGoogle APIの使い方をググる   と良いかもしれません。 •  Endpointsの情報に比べると情報がたくさんあり ます。 30
  • 31.
    Google Cloud Endpoints Eclipseプロジェクトの バックエンドの API  Explorerで クライアントライ クライアント側 作成 実装 動作確認   ブラリの生成 の実装 Tips:Androidの実機からローカルサーバーに接続してテ ストする方法 •  Android側はCloudEndpointUtilsを使う •  「Generate AppEngine Backend」をすると生成される。 •  使い方は 前述の「Android メソッド実行」を参照。 •  CloudEndpointUtils#LOCAL_ANDROID_RUNをtrueにする。 •  サーバー側はデバッグ設定を変更 •  デバッグの構成 -> 引数タブ -> 「プログラムの引数」に 「--address=0.0.0.0 」を追加する。 31
  • 32.
    Google Cloud Endpoints OAuth2認証 32
  • 33.
    Google Cloud Endpoints OAuth2:ClientIDの生成 APIs Console -> API Accessで以下のように設定 JavaScript用 Android用 33
  • 34.
    Google Cloud Endpoints OAuth2:サーバー側の実装例 /** Web用ClientId */ private static final String CLIENT_ID_WEB = "10*********09-7ufji**********k2a91.apps.googleusercontent.com"; /** Android用ClientId */ private static final String CLIENT_ID_ANDROID = "10*********09- o4e8d**********gt2ts3.apps.googleusercontent.com"; /** Android用Audience */ private static final String AUDIENCE_ANDROID = CLIENT_ID_WEB; @ApiMethod( OAuth2認証を利用する場合はClientIDの定義は必須。 ここに定義したClientID以外で認証して取得したTokenでアクセスした name = "data.put", 場合、引数「user」はnullになる。(認証してないものとして扱われる) path = "data/put", Androidで認証してアクセスする場合のみ「audiences」の指定が必要。 clientIds = {CLIENT_ID_WEB, CLIENT_ID_ANDROID }, audiences = AUDIENCE_ANDROID) public AppDataV2 put(AppDataV2 appDataV2, User user) throws ServiceException { // 認証チェック com.google.appengine.api.users.User型の引数を定 義すると、 if (user == null) { OAuth2認証済みの場合に throw new UnauthorizedException(“ログインが必要です。"); Userクラスにユーザー情報がセットされる。 } // データの登録処理 認証チェックはuserがnullかどうかで判定し、 } UnauthorizedExceptionをthrowする。 *実際には定数は別のクラスに定義した方が複数バージョンの対応等で使い勝手が良いです。 34
  • 35.
    Google Cloud Endpoints OAuth2:JavaScriptの実装例 var  mainCtrl  =    funcRon($scope)  {        var  CLIENT_ID  =  '10*********09-­‐7uri**********k2a91.apps.googleusercontent.com';      var  SCOPES  =  'hbps://www.googleapis.com/auth/userinfo.email’;      //  OAuthライブラリをloadして自動で認証を試みる   ・Web用のClient_IDを使用    gapi.client.load('oauth2',  'v2',  funcRon(response)  {   ・scopeは最低限「userinfo.email」が必要                $scope.signin(true,  $scope.userAuthed);      });   ・認証処理の実行    //  OAuth認証関数   ・画面表示時に「可能であれば自動認証」する      $scope.signin=funcRon(mode)  {    際は「immediate:  true」にする。                  gapi.auth.authorize({client_id:  CLIENT_ID,   ・ボタン押下等で明示的に認証する場合は                          scope:  SCOPES,  immediate:  mode,    「immediate:  false」にする。                          response_type:  'token  id_token'},                            $scope.userAuthed);        };   ・認証処理完了時のcallbackで    //  認証後にユーザー情報を取得するcallback関数        $scope.userAuthed  =  funcRon()  {    ユーザー情報の取得とTokenの設定を行う。                var  request  =  gapi.client.oauth2.userinfo.get().execute(funcRon(response)  {                          if  (!response.code)  {                                  var  token  =  gapi.auth.getToken();   ・サインアウトは「gapi.auth.setToken(null);」でOK。                                  token.access_token  =  token.id_token;                                  gapi.auth.setToken(token);                                                                    //  User情報を取得 $scope.user=response;   ・明示的なSign  in処理の呼び出し部分                                  //  反映させる $scope.$apply();   <a  ng-­‐click="signin(false);">  Sign  In  </a>                          }                  });          }   }     35
  • 36.
    Google Cloud Endpoints OAuth2:Androidの実装例 (Credentialの管理) private  staRc  final  String  CLIENT_ID  =   "10*********09-­‐7uri**********k2a91.apps.googleusercontent.com";     ・サーバー側でAudienceに指定したClient_IDを指定 private  GoogleAccountCredenRal  credenRal;     Credentialの定義 @Override   protected  void  onCreate(Bundle  savedInstanceState)  {          super.onCreate(savedInstanceState);          setContentView(R.layout.acRvity_main);   Credentialを生成する。          //  CredenRalを生成する credenRal  =  GoogleAccountCredenRal.usingAudience(this,  "server:client_id:"  +  CLIENT_ID);   }     private  void  setAccountName(String  accountName)  {   認証情報をCredinRalにセットする。          //  CredenRalにアカウント名をセット credenRal.setSelectedAccountName(accountName);   }       36
  • 37.
    Google Cloud Endpoints OAuth2:Androidの実装例 (アカウント選択) //  「Googleアカウント選択用Picker」を表示する private  void  chooseAccount()  {          startAcRvityForResult(credenRal.newChooseAccountIntent(),  REQUEST_ACCOUNT_PICKER);   }     @Override   protected  void  onAcRvityResult(int  requestCode,  int  resultCode,  Intent  data)  {          super.onAcRvityResult(requestCode,  resultCode,  data);          switch  (requestCode)  {          //  「Googleアカウント選択用Picker」の選択結果を取得する case  REQUEST_ACCOUNT_PICKER:                  if  (data  !=  null  &&  data.getExtras()  !=  null)  {                          Bundle  bundle  =  data.getExtras();                          String  accountName  =  bundle.getString(AccountManager.KEY_ACCOUNT_NAME);                          if  (accountName  !=  null)  {                                  //  CredenRalにアカウント名をセット setAccountName(accountName);                          }                  }                  break;          }   }   37
  • 38.
    Google Cloud Endpoints OAuth2:Androidの実装例 (クライアントライブラリ実行) AppData.Builder  builder  =  new  AppData.Builder(                AndroidHbp.newCompaRbleTransport(),                new  GsonFactory(),                  credenRal);   AppData  appDataApi  =  CloudEndpointURls.updateBuilder(builder).build();   認証情報を使用してAPIを実行する場合には、 Credentialを引数に渡す。 (認証情報が不要な場合にはnullを渡せばOK) 38
  • 39.
    Google Cloud Endpoints OAuth2:サーバーに渡せるTokenは二種類ある Id_token access_token 公式サンプルが使用している形式 API  Explorerが使用している形式(*1)   ドキュメントに書かれている形式 ドキュメントに書かれてない形式(*2)   User情報からEmailアドレスと User情報からUserId、Email、 NickNameのみ取得できる (*3) NickName、AuthDomainを取得できる 認証したユーザーの権限をサーバー 認証したユーザーの権限をサーバー 側で行使できない(たぶん) 側で行使できる(若干強引に)(*4) Token生成に使用したClientIDのチェッ Id_token同様にチェックが行われる。   クが行われる(Token  swap  aback対策) (ただしAPI  Explorerは無条件で許可) *1 認証に関してはドキュメント通りのJS・Android実装とAPI Explorerで挙動が異なります。 *2 Endpointsのドキュメントに書かれていない方式なので継続的にサポートされるか不明。 *3 id_tokenを使った場合にUserIDを取得できない事に関してはissueが上げられて   Acceptedになっているのでバグとして修正されるかもしれません。 *4 Endpointsの機能としてTokenやCredentialを取得する仕組みは無いようです。   HttpServletRequest#getHeaderメソッドでaccess_token文字列を直接取得する必要があります。 各クライアント・Tokenタイプによる挙動に関する詳細は「http://goo.gl/44vNj」を参照。 39
  • 40.
    Google Cloud Endpoints デモ(JavaScript & Android) •  サーバー側API •  一覧取得 •  メッセージ投稿(要認証) •  クライアント •  一覧取得 •  メッセージ投稿 •  認証機能 40
  • 41.
    Google Cloud Endpoints 参考リンク •  公式ドキュメント •  http://goo.gl/6wp7R •  公式サンプル (tictactoe) •  Android - http://goo.gl/xjX1B •  Backend & JS- http://goo.gl/V8MEV •  API Explorer •  https://developers.google.com/apis-explorer/#s/ •  Google APIs Discovery Service •  https://developers.google.com/discovery/?hl=ja •  APIs Console •  https://code.google.com/apis/console/ •  Blog @vierjp 「Google Cloud Endpointsを試してみた」 •  http://blog.vier.jp/2013/02/google-cloud-endpoints-12.html 41
  • 42.
    BigQuery 新機能のデモ •  Small JOINとBig JOIN •  GROUP BYとGROUP EACH BY *デモの内容はブログ( http://goo.gl/jJnuR )の解説と同じです。 42
  • 43.
    BigQuery 参考リンク •  BigQuery 公式ドキュメント •  https://developers.google.com/bigquery/ •  BigQuery Query Reference (JOIN) •  http://goo.gl/LKEZq •  BigQuery Query Reference (GROUP BY) •  http://goo.gl/EI2aK •  Google Developers Blog (BigQuery gets big new features to make data analysis even easier) •  http://goo.gl/Unwmq •  Blog @vierjp 「BigQueryの新機能 (2013/03/15)」 •  http://blog.vier.jp/2013/03/bigquery-20130315.html 43
  • 44.
    Google Cloud Endpoints& BigQuery ご清聴ありがとうございました 時間の都合で扱えなかった細かい内容はブログで! http://blog.vier.jp/ 44