2015年4月6日月曜日

GAE/J上のGoogle Cloud EndpointsをバックエンドにしてSupersonicのdataアクセスを試してみた


Supersonic data セットアップ



1. データプロバイダの追加


プロジェクトディレクトリ下でconnectを発動し、プロジェクトのコネクトスクリーンを開く。
$ steroids connect

コネクトスクリーンの"Data"タブで「Custom Provider」を選択。




NAMEに任意のデータプロバイダ名を入力。
BASE URLは「https://YOUR_APP.appspot.com/_ah/api/」まで設定。v1などバージョンナンバーまでのパスにしない(後述のリソース追加設定のため)。



また、Google Cloud Endpointsはhttpsアクセスしか認めていないので、http://ではなく、https://にしておく。


2. リソースの追加


「ADD NEW RESOURCE」ボタンをクリックして、リソースを設定する。

NAMEに任意のリソース名を入力。
URL PATHは「yourApi/v1/」を入力。
例えば、API名が「playlistApi」、バージョンが「v1」の場合、URL PATHは「playlistApi/v1/」になる。



前述のプロバイダのBASE URLで「〜/v1/」まで含めてしまうと、必須入力であるリソースのURL PATHに何も設定できなくなるので、プロバイダのBASE URLを「api/」までと設定した。

これにより、リソースへのパスは、BASE URL + RESORCE URL PATH = 「https://YOUR_APP.appspot.com/_ah/api/playlistApi/v1/」となる。


3. アクションのカスタマイズ


「CUSTOMIZE ACTIONS」ボタンをクリックして、get/postなどのリクエストの、URL PATHやROOT KEYSを設定する。

例えば、コレクションを取得するgetのAPIパスが「playlist」の場合、URL PATHは「playlist」になる。



これにより、完成したエンドポイントへのパスは、BASE URL + RESOURCE URL PATH + ACTION URL PATH = 「https://YOUR_APP.appspot.com/_ah/api/playlistApi/v1/playlist」となる。


更に、Google Cloud Endpointsのコレクションのルートは「items」なので、ROOT KEYSに「items」を指定する。


「RELOAD MODEL FROM API」ボタンをクリックすると、エンドポイントとの通信が行われる。無事にコレクションが取得できると、最新のエンティティモデルの内容が表示される。





デバイスから data access 確認



トップ画面には、「https://YOUR_APP.appspot.com/_ah/api/playlistApi/v1/playlist」へアクセスした結果が表示されている。




API Explorerで、dataStoreにエンティティを1つ追加してみる。




デバイスで起動しているアプリ側のリストも、数秒後に、自動的に更新される。





10秒間隔で同期が発動する



ログを見ると、ほぼ10秒間隔でエンドポイントが叩かれている。




データバインディングはいいのだが、10秒おきにプルリクエストが発動するのでは、GAEのdataStoreのRead Quotaの消費が激しくなってしまう。

2015年4月現在の無料枠では、Read Operationsのリミットは50,000回/日なので、

( 60秒 / 10秒間隔 ) x 60分 = 360回/時

1時間アプリを起動しているだけで、360回のRead Operationsが発生する。

50,000回 / 360回 = 138.889

例えば、同時に138人が1時間アプリを起動しているだけで、50,000回のRead Operationsのクオータはすぐに消費されてしまう。


データバインディングは、supersonic.data APIのwhenChanged()で実現されている。
Playlist.all().whenChanged( function (playlists) {
        $scope.$apply( function () {
          $scope.playlists = playlists;
          $scope.showSpinner = false;
        });
    });

クオータの消費を避けたいなら、whenChanged()を使わずに、適切なタイミングで自作でデータの同期を行う必要があるなと。


参考:Supersonic Guides - Supersonic Framework

2015年4月3日金曜日

AppGyverのSupersonicを使ってdataアクセスするアプリを作っていて"Module 'common' is not available!"のエラーが出たら

AppGyverが提供しているハイブリッドアプリ開発のフレームワークSupersonic。

Supersonicを使ってアプリを作っていて、バックエンドのデータへアクセスする部分を組み込んだ途端、

Error: [$injector:nomod] Module 'common' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.

というエラーが出て、ハマってしまったので、その備忘録。



アクセスしようとしたデータもnot found状態になる。





ここで要求されている「common」モジュールは、プロジェクトのディレクトリ下のapp/common/。

Supersonic Guides - Supersonic Framework Utilising the common module
The common module also already contains a layout file (located at app/common/views/layout.html), which has all the basic dependecies of your project declared, such as supersonic.js, steroids.js and cordova.js. Because common is declared as a dependency to all modules by default, the layout file in there can be used to throughout the app just by removing any layout files from the module itself.

Supersonicを使ったアプリのレイアウトなど基本的な部分で使われているモジュール。

自分のプロジェクトには、確かにそのディレクトリが無い。


レイアウトという時点で、もしやと思ったのは、シンプルページアプリケーションとして、プロジェクトを作ったことがボトルネックになっているのではないか、マルチページアプリケーションとして、そもそもプロジェクトを作っていないと、このcommonモジュールはapp下にデプロイされないんじゃないか?ということ。


試しに、プロジェクトをマルチページで、一から作りなおしてみる。

$ steroids create プロジェクト名

続くアプリタイプの選択で、デフォルトのマルチページタイプを選択。



改めて、新しく作ったプロジェクトで、データのリポジトリを作り、テストデータを入れてみたら、今度はエラーが出ない!

テストデータも表示されている。




commonモジュールが無いエラーで嵌ったら、プロジェクトをマルチページタイプで作りなおせばOKです。


シングルページタイプのアプリでSueprsonicのdata APIが使えないということでは無いと思います。

あくまでも、Supersonicのチュートリアルを試していて、データのハンドリングをやりたいと思っただけなのに、commonモジュールにはまってしまった場合の対処方法です。