ラベル GAE の投稿を表示しています。 すべての投稿を表示
ラベル GAE の投稿を表示しています。 すべての投稿を表示

2013年2月22日

2013年のJリーグのカレンダー

今年もJリーグが開幕しますのでカレンダーフィードを作りました。

「Google」というボタンをクリックすると、チームごとのスケジュールを Google Calendar に追加できます。 パソコンでもスマートフォンでもカレンダーを共有している人は便利だと思います。 まだ前半戦のスケジュールしか公開されていませんが、後半戦のスケジュールが発表されたら追随する予定なので、 追加漏れも無くなると思います。(去年は後半戦の反映が遅れて自分でも困りました)

iCal 配信部分は去年作ったものがありますので、そのデータを更新しただけですが、 昇格・降格の反映、スタジアム名称の反映の2点も実施しました。 ネーミングライツの関係で名称が変わったスタジアムがあるためです。 オフィシャルサイトは短縮表記を使っていますが、これでは検索しても引っかかりにくいので、 できるだけ正式名称を使うようにしています。

また、表示順序をランダムにし、リロードする度に変わるようにしました。 特に意味はありませんが、何かの縁のあるクラブのスケジュールを登録するのも良いかもしれませんね。

今シーズンから J1 に昇格した湘南ベルマーレのスケジュールはこんな感じになります。

JFA がスケジュールをオープンデータで配信してくれると嬉しいんだけどなぁと思いました。

関連:

2013年2月2日

#fctokyo のツイートを見る Web アプリを作ってみた

#fctokyo のツイートを表示するものを作ってみました。

FC東京のチームカラーである青と赤で埋めてみたかった、という点と、 Web アプリのお勉強がてら、という2点の動機です。 1分ごとに更新処理が走って、新しいツイートがある場合は表示が更新されます。 実装方法がイマイチなので、ちょっとカクカクした感じになってしまっていますが。

さて、来月からはJリーグが開幕します。 日程も発表されたので楽しみですね。

2013シーズン Jリーグ試合日程発表!

2013 Jリーグディビジョン1のリーグ戦およびヤマザキナビスコカップの試合日程が発表されましたので、お知らせいたします。 今シーズンも熱いご声援をよろしくお願い申し上げます。

2011年6月21日

Google Tasks API を使ってみる

先月、Google Tasks の API が公開されました。 API 公開のアナウンスが出されたときはサンプルがありませんでしたが、 先週末に記事が公開されました。 ライブラリコードのサンプルディレクトリに同様のコードが存在します。

記事/サンプルを読む中では、 OAuth2Decorator クラスが導入されたこと、 コールバック URL のハンドラスクリプトとして oauth2client/appengine.py を使えるようになったこと、 この二点が大きな改善点だと思います。

しかし、それに気付かずに実装しちゃった... という寂しいお話。 いちおう、スクリプトはこちら。。。

2011年3月19日

Google App Engine / Java の SDK をインストール

Google App Engine / Java の開発では Eclipse が必須のような扱いですが、 HTML / JavaScript / CSS を書き換えて表示を確認したいだけの場合には面倒に感じます。 SDK をインストールすると、コマンドラインツールを使って開発用サーバを立ち上げることができます。 Eclipse を起動する必要がありませんので、マシンのメモリ使用量を抑えられます。

手順は Google App Engine のページに記載されていますが、 しばらくすると存在自体を忘れてしまいそうなのでメモしておきます。

「プログラミング Google App Engine」の "2.1 SDK のセットアップ" の最後にある "Eclipse なしでの Java SDK のインストール" でも少しだけ触れられています。

手順

  1. appengine-java-sdk-1.4.2.zip をダウンロードする。 (ダウンロードページ)
  2. zip ファイルを展開したものを適当なディレクトリに移動させる。
  3. ターミナル / コマンドプロンプトなどを立ち上げ、Google App Engine / Java のプロジェクトのディレクトリに移動する。
  4. war ディレクトリを指定して、SDK のスクリプトを実行する。

やること

手元の環境では SDK を /usr/local/appengine-java-sdk-1.4.2 に移動させ、 バージョン番号を隠すようにシンボリックリンクを用意しました。 mv でも構わないと思いますが、複数の SDK を使えるようにしておくためには ln の方が良さそうです。 また、SDK のバージョンによって demos などが異なりますので、参照用に残しておくこともできます。

$ cd /usr/local
$ sudo ln -s appengine-java-sdk-1.4.2 appengine-java-sdk

中身は次の構成になっています。

$ tree -d -L 2 /usr/local/appengine-java-sdk
/usr/local/appengine-java-sdk
|-- bin
|-- config
|   |-- sdk
|   `-- user
|-- demos
|   |-- guestbook
|   |-- helloorm
|   |-- helloxmpp
|   |-- jdoexamples
|   |-- mandelbrot
|   |-- mediastore
|   |-- new_project_template
|   |-- shardedcounter
|   |-- sticky
|   |-- taskengine
|   `-- taskqueueexamples
|-- docs
|   |-- javadoc
|   |-- testing
|   `-- tools
|-- lib
|   |-- agent
|   |-- impl
|   |-- shared
|   |-- testing
|   |-- tools
|   `-- user
`-- src
    `-- orm

29 directories

bin ディレクトリには4つのスクリプトが用意されています。 .cmd は Windows 用、 .sh は Linux などのためですから、実質的には2種類のスクリプトです。

$ ls /usr/local/appengine-java-sdk/bin
appcfg.cmd         appcfg.sh*         dev_appserver.cmd  dev_appserver.sh*

開発用サーバを起動するスクリプトは dev_appserver で、引数には war ディレクトリを渡します。 ここではプロジェクトのディレクリに移動してあるものとして考えていますので war だけですが、 必要ならば絶対パスの方が間違いが少ないかもしれません。

$ /usr/local/appengine-java-sdk/bin/dev_appserver.sh war

スクリプトは -h オプションでヘルプが表示され、 -p オプションでポート番号を指定できます。 -a オプションでバインドするアドレスを指定できますので、他のマシンから表示を確認するためにも使えます。

$ /usr/local/appengine-java-sdk/bin/dev_appserver.sh -a 192.168.0.2 -p 8888 war

まとめ

コマンドラインから開発用サーバを立ち上げました。 まぁ、今どきそんなメモリ使用量を気にするようなマシンで開発するな、という話かもしれませんが、 たまにはそういうこともあります。たぶん。 あと、フロントエンドの開発者に Eclipse を強要しない、という点では良いと思います。 CI (Continuous Integration) との相性も良いでしょうね。

2010年12月9日

AppEngine の環境依存調整メモ

from apiclient.json import simplejson で simplejson が C 拡張を使うためにエラーが発生する場合は、わざと ImportError を発生させてみます。 これで django の方にフォールバックするはずです。

-  import simplejson
+  import _simplejson

開発サーバと本番サーバで OAuth のコールバック URL を振り分けたりする場合は環境変数を参照します。 ビルドスクリプトで調整しても構わないと思いますが、好きずきです。 環境変数名は Python Runtime Environment にて。

if "Development" in os.environ['SERVER_SOFTWARE']:
    STEP2_URI = "http:localhost:8080/works/buzz-sample/callback"
else:
    STEP2_URI = "http://%s.appspot.com/works/buzz-sample/callback" % (
                    os.environ['APPLICATION_ID'], )

2010年10月24日

"oauth-signpost" で OAuth on Slim3

Slim3 を使ったアプリケーションで OAuth の認可を実施します。 OAuth (3-way dance) の流れは次のようになりますので、 HTTP リクエストの生成、認可のページへのリダイレクト、コールバックの受け取り、の三つの機能をサポートする必要があります。

OAuth の流れ

  1. サービスプロバイダーの情報を与える。
  2. アプリケーションの認証情報 (Consumer Key / Consumer Secret) を与える。
  3. HTTP リクエストによって一時トークンを取得し、 oauth_tokenoauth_token_secret を抜き出す。
  4. oauth_token を GET パラメータに乗せて認可のページへユーザーをリダイレクトさせる。
  5. サービスのサイトでユーザーに自分で認可を確認してもらう。
  6. 認可のページからコールバックへ戻してもらい、アプリケーション側で確認コード (oauth_verifier) を取得する。
  7. 確認コードを使って HTTP リクエストを発行し、認証トークンを取得する。
  8. 認証トークンから oauth_tokenoauth_token_secret を抜き出して保存する。

最後の手順で保存した認証トークンを使うと、API 経由でデータを操作できるようになります。 Twitter OAuth on Java AppEngine というブログ記事を参考にして、実際に API 経由でデータを取得します。 OAuth って何?という場合は Twitter の開発者向けページ を読みます。 英語で書いてある...とか、そういう細かいことは気にしません。 必要なら RFC などを読みます、、、これも英語なので、やっぱり日本語で検索するのが無難かもしれません。

何を言っているのか分からん...という場合は OAuth 2.0 の仕様が固まってライブラリが充実してくるのを待った方が 良いかもしれません。というか、OAuth 2.0 のドラフト 9 か 10 に対応したサービスを使ってみるのも良いですね。 いずれにしても、3-way ダンスはユーザーエージェント (Web ブラウザ) のリダイレクトを使いますので、 誰が誰から何を許可してもらうかを把握しておかないと大変です。 登場人物が3人 (サービスプロバイダー、コンシューマー or アプリケーション、ユーザー or リソースオーナー) いますので、 それぞれの関係を間違えないことが大事なのではないでしょうか。

いくつかの準備

まず、Java のライブラリをプロジェクトに配置します。 必要なライブラリは次のふたつです。違うライブラリを使う場合は適当に揃えます。 Twitter 以外のサービスプロバイダーも使いたくなるかもしれませんので、 Twitter4j は使いません。

これらの .jar ファイルを war/WEB-INF/lib ディレクトリに配置し、 CLASSPATH を通します。 適切に設定すると、Eclipse の .classpath は次のように変化します。

$ svn diff .classpath
(snip)
+       <classpathentry kind="lib" path="war/WEB-INF/lib/signpost-core-1.2.1.1.jar"/>
+       <classpathentry kind="lib" path="war/WEB-INF/lib/commons-codec-1.4.jar"/>
(snip)

次に、サービスプロバイダーの情報を取得します。 サービスプロバイダーが発行するドキュメントに記載されている、次の3つの URL を確認します。

  • 一時トークンを取得する URL ... Twitter の場合は https://api.twitter.com/oauth/request_token
  • 認証トークンを取得する URL ... Twitter の場合は https://api.twitter.com/oauth/access_token
  • 認可の画面の URL ... Twitter の場合は https://api.twitter.com/oauth/authorize

サービスプロバイダーにアプリケーションを登録すると、認証情報としてコンシューマートークンをもらえます。 表記はいろいろあるかもしれませんが、アプリケーションのためのパスワードのようなものです。 これらが揃うと、次のような Java のコードを記述できます。 記述を省略している部分には適切な文字列を当てはめてください。

String requestTokenUrl = ...;
String accessTokenUrl = ...;
String authorizeUrl = ...;
OAuthProvider provider = new DefaultProvider(requestTokenUrl, accessTokenUrl, authorizeUrl);

String consumerKey = ...;
String consumerSecret = ...;
OAuthConsumer consumer = new DefaultConsumer(consumerKey, consumerSecret);
  1. それぞれのパラメータはサービスプロバイダーの設定に合わせます。
  1. コンシューマーシークレットは秘密のパスワードなので公開してはいけません。パスワードを晒すようなものです。

次に、App Engine でセッションを有効にします。 セッションを有効にするには appengine-web.xml を次のように編集します。

$ svn di war/WEB-INF/appengine-web.xml
(snip)
-       <sessions-enabled>false</sessions-enabled>
+       <sessions-enabled>true</sessions-enabled>
(snip)

ここまでの状態でコンパイルが通れば準備は完了です。

  1. セッションを有効にしていると CNMV というデータビューアーがデフォルト設定では動きません。

実装 (前半戦)

冒頭の手順の 1 と 2 は先の準備で実施しました。 次は、HTTP リクエストを発行します。 AppEngine のドキュメントの Using java.net も参照してください。

まずは一時トークンを取得します。Java のソースコードで OAuthProvider#retrieveRequestToken を呼び出します。 このメソッド内で HTTP リクエストが発行されます。ネットワーク接続を確認しておいてください。

OAuthProvider provider = getProvider(); // 記述を簡略化しておきます。
OAuthConsumer consumer = getConsumer(); // 記述を簡略化しておきます。
try {
    String authUrl = provider.retrieveRequestToken(consumer, basePath + "/callback");
    System.out.println("tokenKey     = " + consumer.getToken());
    System.out.println("tokenSecret  = " + consumer.getTokenSecret());
    System.out.println("AuthorizeURL = " + authUrl);
} catch (OAuthNotAuthorizedException e) {
    System.out.println(e.getMessage());
}

見たままですね。戻り値が認可の画面の URL で、 consumer インスタンスには tokentokenSecret が設定されています。 ここで取得した token / tokenSecret のペアは後で使いますので、一時的な記憶領域に保存します。 本当にワンステップずつ実行したい場合は紙にメモしても構いませんが、ここではセッションに保存します。 そのためにセッションを有効した、ということです。

上記のコードスニペットを次の要領で書き換えます。 Slim3 でセッションに積むためには sessionScope() を使うのがお作法のようですが、 後で実装を書き換えますので標準のセッションオブジェクトにしておきます。手抜きです。

-  System.out.println("tokenKey     = " + consumer.getToken());
-  System.out.println("tokenSecret  = " + consumer.getTokenSecret());
+  request.getSession().setAttribute("tokenKey", consumer.getToken());
+  request.getSession().setAttribute("tokenSecret", consumer.getTokenSecret());

次に、認可のページにアクセスします。 コンソールに出力された AuthorizeURL がそれに該当しますので、これをコピーしてブラウザでアクセスします。 実際は、これだと運用に耐えませんので、ブラウザ (ユーザーエージェント) にリダイレクトするよう伝えます。 Slim3 では redirect() メソッドで返される Navigation インスタンスのことです。

return redirect(authUrl + "&oauth_callback=" + basePath + "/callback");

これで、サービスプロバイダーの認可のページに辿り着くことができました。あと二息といったところです。 冒頭の手順では、3 と 4 を消化したことになります。

手順 5 にはプログラムは関知しませんので、素直に認可してもらうとしましょう。 しかし、認可が終わったらサービスプロバイダーは何をすべきでしょうか?アプリケーションは何を期待すべきでしょうか? その答えがコールバックであり、OAuth がダンスと言われる部分です。 redirect() メソッドでシレっと oauth_callback を指定している部分でもあります。 続きを後半戦で見て行きます。

実装 (後半戦)

前半戦で、ユーザーはサービスプロバイダーのサイトにリダイレクトされました。 この時点で自分のアプリケーションではユーザーがどこのだれであるかは分かりません。 ユーザーがサービスプロバイダーから自分のシステムに戻ってきても、クッキーはドメインを超えて共有できませんので、 相変わらずユーザーがどこのだれであるかは分かりません。

しかし、先ほど保存した一時トークンと、サービスプロバイダーから戻ってくるときにユーザーが持っているコードを合わせると、この状況を打破できます。 それが OAuth のダンスです。 アプリケーションはサービスプロバイダーから認められて、ユーザーからも認められたのです。 あとは、ユーザーがきちんと自分のアプリケーションに戻ってきてくれたことをサービスプロバイダーに伝えるだけです。

実装は次のようになります。 セッションに保存しておいた一時トークンを consumer に設定し直します。 サービスプロバイダーはコールバックで戻すときにクエリパラメータに文字列を設定しますので、それを受け取ります。 コールバックが設定されていない場合にはサービスプロバイダーは PIN コードを表示するだけのはずですので、 アプリケーションにはそれを入力してもらうための機構が必要になります。 ここでの実装は前者です。 認証トークンを取得するためには Java のソースコードで OAuthProvider#retrieveAccessToken を呼び出します。

Object key = request.getSession().getAttribute("tokenKey");
Object secret = request.getSession().getAttribute("tokenSecret");
if (key == null || secret == null) {
    // invalid state
    return redirect("/");
}

OAuthConsumer consumer = getConsumer();
consumer.setTokenWithSecret(key.toString(), secret.toString());

// サービスプロバイダーからの伝言メモみたいなもの
String verifier = asString("oauth_verifier");

OAuthProvider provider = getProvider();
try {
    //provider.setOAuth10a(true);
    provider.retrieveAccessToken(consumer, verifier);
    System.out.println("tokenKey: " + consumer.getToken());
    System.out.println("tokenSecret: " + consumer.getTokenSecret());
} catch (OAuthNotAuthorizedException e) {
    System.out.println(e.getMessage());
}

認証リクエストの後では、 consumer に設定された tokentokenSecret が変更されています。 これがユーザーの認証トークンです。 最後にこれを Google App Engine の Datastore に保存します。 モデルは適当に定義します。Google アカウントと関連づけるのが簡単だと思います。

ということで OAuth による認可は完了です。

実装 (延長戦)

OAuth で認可するそもそもの目的は、サービスプロバイダーが提供するリソースにアクセスするためです。 最後に確認の意味を込めて、単発のリクエストを発行します。 エンドポイントの URL は適当に設定してください。

String tokenKey = "<access token key>";
String tokenSecret = "<access token secret>";

OAuthConsumer consumer = getConsumer();
consumer.setTokenWithSecret(tokenKey, tokenSecret);

String endpoint = "<service provider endpoint url>";
URL url = new URL(endpoint);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
    // 署名を生成します。リクエスト情報のフィンガープリントのようなものです。
    consumer.sign(connection);
    connection.connect();
    if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
        System.out.println("response is HTTP_OK!!");
    }
    InputStream stream = connection.getInputStream();
    InputStreamReader reader = new InputStreamReader(stream);
    BufferedReader buffer = new BufferedReader(reader);
    String line;
    while ((line = buffer.readLine()) != null) {
        System.out.println(line);
    }
    buffer.close();
    reader.close();
    stream.close();
} catch (OAuthNotAuthorizedException e) {
    System.out.println(e.getMessage());
}

リクエストが成功して、期待する出力を得られれば成功です。 あとは自由にリソースで遊ぶだけですね :D

  1. リクエストに失敗した場合にはエラーの oauth_problem を確認します。だいたいは signature_invalid だと思いますので、 リクエストを発行するマシンの時計が正常な状態であるかを確認します。

まとめ

Slim3 に固有の機構はあまり使っていませんが、とりあえずこれで Google App Engine を使って OAuth のダンスを踊れるようになりました。 抜粋したスニペットを例示していますので、一部おかしいコードもあるかもしれません。 それは組み込むときに修正する、ということで。

それにしても Java のコード記述量は多いなぁ、と実感する今日この頃。 IDE でスムーズに記述できるのは嬉しい人も多いでしょうが、文字数 (タイプ数ではない) が多いと、コードレビューが大変だろうなぁ、と思います。

2010年10月18日

Getting Started Slim3 with Subversion

Mashup Award 6 のハッカソンでちょっとしたプロジェクトを始めることになりました。 認証情報が必要なフィードを取得して、それをデスクトップにプッシュするアプリケーションです。

認証情報に関しては OAuth という認可の仕様がありますので、それを利用します。 フィードを取得するサービスは Google App Engine に配置します。 App Engine には cron に似た仕組みがありますので、定期実行ジョブでフィードを確認する、という仕組みです。 取得したフィードはマルチデバイスに対応した仕組みで再度配信するようにします。 最初は HTML で表示してブラウザで確認できるようにしますが、時間に余裕があれば Adobe AIR や HTML5 Widget なども利用したいところです。

とはいえ、最初からあれもこれもでは何も始まりませんので、まずは Google App Engine でのプロジェクトをセットアップして、Subversion のレポジトリを準備します。 Google App Engine では Java を使用し、フレームワークには Slim3 を採用します。 Subversion のレポジトリには Google Code を利用します。

Slim3 の準備

プロジェクトのセットアップは非常に簡単です。 Slim3 のスタートガイド に沿って進めるだけです。 ハッカソンではハンズオンを開催して頂きましたので、その場でチョコチョコ聞けばすぐにスタートできました。

  1. Java をインストールする。
  2. Eclipse をダウンロードして zip ファイルを展開する。
  3. Google の Eclipse プラグイン をインストールする。
  4. Slim3ブランクプロジェクト をダウンロードする。
  5. Eclipse からブランクプロジェクトを import する。

1, 2, 3, 4 はダウンロードに時間がかかりますが手順として難しいことはありませんので、 ただただ粛々とネットワーク回線に頑張ってもらいます。

ブランクプロジェクトは zip ファイルなのですが、Eclipse は zip ファイルをプロジェクトとして取り込むこともできますので、手動で展開する必要はありません。

一通りのチュートリアルに目を通して簡単な入出力を簡単したら準備完了です。 最後に、プロジェクトの名称を変更したらオシマイです。

共有するデータの検討

チーム開発の場合にはソースコードを共有する必要があります。 原理的には *.java ファイルだけ共有すれば問題ないはずですが、 実際にはそうでもないことがほとんどです。

Java のチーム開発で難しいことのひとつは、統合開発環境を利用することを前提としている、ということだと思います。 今回は Google のプラグインの関係もありますので Eclipse を使います。 Eclipse には .project ファイルを始めとしたプロジェクト管理用の設定ファイルが必要です。 問題は、こうした設定ファイル (ドットファイル) も共有するかどうか?という点になります。

Slim3 のブランクプロジェクトから作成したプロジェクトのディレクトリには、次のようなファイルおよびディレクトリが含まれます。 通常ファイルもドット始まりのファイルもそれなりに存在しています。

$ ls -A
.apt_generated/        .externalToolBuilders/ .project          war/
build.xml              libsrc/                test/
.classpath             .factorypath           .settings/
build.properties       lib/                   src/

少し脱線しますが、Slim3 はモデル層の Java クラスに対応するメタクラスを生成します。 モデル層のクラスには @Model アノテーションを付与しますが、これを自動的に処理するために「Annotation Processing」を使用します。 Annotation Processing Tool を略して APT と表記します。 上記の .apt_generated ディレクトリは、APT が生成した何かを保存する場所です。 次に注意するのが .factorypath です。このファイルでは APT の場所を指定します。 Slim3 の場合は lib ディレクトリ直下にある slim3-gen-{version}.jar です。 今回のプロジェクトで利用する Slim3 のバージョンは 1.0.5 なので、その文字列が {version} に該当します。 先にも述べたように、Slim3 の APT はメタクラスを生成しますので、ここも CLASSPATH に含まれている必要があります。 つまり、この辺の設定をチームメンバーが共有できていないと、メタクラスを発見できない、という状態になります。

具体的な設定情報は次のようになります。

$ cat .factorypath
<factorypath>
    <factorypathentry kind="WKSPJAR" id="/joogoo/lib/slim3-gen-1.0.5.jar" enabled="true" runInBatchMode="false"/>
</factorypath>

$ cat .classpath
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
    <classpathentry kind="src" path="src"/>
    <classpathentry kind="src" path="test"/>
    <classpathentry kind="lib" path="war/WEB-INF/lib/junit-4.7.jar"/>
    <classpathentry kind="lib" path="war/WEB-INF/lib/slim3-1.0.5.jar" sourcepath="libsrc/slim3-1.0.5-sources.jar"/>
    <classpathentry kind="src" path=".apt_generated">
        <attributes>
            <attribute name="optional" value="true"/>
        </attributes>
    </classpathentry>
    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
    <classpathentry kind="con" path="com.google.appengine.eclipse.core.GAE_CONTAINER"/>
    <classpathentry kind="output" path="war/WEB-INF/classes"/>
</classpath>

ということで、これを満足するようにプロジェクトで共有を進める必要があります。

Subversion の設定

Google Code にプロジェクトを作成し、管理者としての設定を行います。 プロジェクト作成のリンクは画面中央のやや下にあります。 Google Code にプロジェクトを作成するときは、一番最初にライセンスを指定します。 この辺は関係者のポリシーなり大人の事情なりで決めましょう。 当然ながら、すでに存在するプロジェクトと同名のプロジェクトを作成することはできません。 Google App Engine におけるアプリケーション ID との兼ね合いも考えてプロジェクト名を作成しましょう。

Google Code のレポジトリに変更を反映させるためにはユーザー ID とパスワードが必要です。 ユーザー ID は通常の Google アカウントそのままですが、パスワードは googlecode 用のものです。 googlecode 用のパスワードはランダムな文字列で、サイトで確認および再生成が可能です。

ここまで来たら、あとはそれをレポジトリに反映させるだけです。 しかし svn:ignore 設定には注意が必要です。 Java コンパイラが生成する *.class ファイルを除外することはもとより、App Engine の SDK が生成するファイルも除外しておく必要があります。 先ほどは共有すべきものを検討しましたが、ここでは、余計なものが共有されないように注意するわけです。 また、文字コードや改行コード、ファイルの実行ビットなども確認します。 例えば、 war/WEB-INF ディレクトリには次のように設定します。

$ svn propget svn:ignore war/WEB-INF
classes
appengine-generated

そしてついに変更をプッシュします。 変更点はプロジェクトのサイトで確認できます。 自分がコミットしたチェンジセットにはスターが付きますので、視認性はかなり良いと思います。 また、それぞれのコミットに対してコメントを付けることもできますので、普通にプロジェクト管理として使えますね。

まとめ

Slim3 でプロジェクトを作成して、それを googlecode にプッシュしました。 Slim3 のセットアップは1時間もあればサクサク進めることができました。 一方、Subversion を介してプロジェクトを共有するためには、やや時間がかかりました。 その多くはドットファイルに由来しますが、IDE を使わなくはいけないのは大変だなぁ、と思います。 IDE は補完してくれるから便利、という意見もあるようですが、diff が長くなることには変わりありませんし、 そもそも補完のキーバインドを記憶しておかなくてはなりません。

短期間での開発なので、何をどこまでやるかは難しいところです。 いろいろな兼ね合いを考えながら満足いくものができるものまで持っていきたいと思います。

ともあれ、Mashup Award 事務局および、ajn コミュニティの方には感謝です!

2010年5月29日

BPStudy #33

昨日は恵比寿に行って Google App Engine に関するお勉強をしてきました。先日開催された Google I/O で発表されたいくつかのことと、実際に開発を進める中での勘所を共有できれば良いかなぁというのが動機です。Google I/O での App Engine に関するビジネス面での最大の発表は VMWare との協業だと思いますが、開発面での発表はどんなことがあったっけかな?ということの確認です。

Google I/O 2010 App Engineセッションレポート

最初のスピーカの方は実際に Google I/O 2010 に参加してきたようで、写真やビデオの紹介もありました。よくよく考えると創業10年程度でここまでのイベントを開催できる Google はスゴいと実感させられます。さて、セッションの内容はブログにまとめられていた通りに BigQueryChannel API に関することでした。実際に Channel API のデモで遊んでみると、確かにリアルタイム性の高いアプリケーションも実装できそうな感じでした。Wave Protocol のような federation の機構は意識されていない印象でしたが、インターネット上でのリアルタイムメッセージングはこれで十分なんだろうなぁ、と思いました。Java のライブラリにも Defered が導入されるようですし、通信方法を websocket へ移行してもソースコードをそのまま使えるそうです。差分情報だけをそれが存在するときに限って配信してくれれば良いので、スポーツなどのテキストライブ (例:ジロ・デ・イタリア2010の第20ステージ) に使えると嬉しい機能ですね。あと、デモのソースコードを公開している辺りは Google らしいな、と感じます。

一方の BigQuery はまだ一般の開発者が気軽に使える代物ではないらしく、Google の中の人とメールでやり取りしながら作業を進めなくてはいけない場合があるレベルのようです。Google Storage にデータを入れ込む部分が難しいのでしょうか。とはいえ、想定するデータ数が数百億件という規模なので、気軽にそんなデータ量を使う人もいないでしょうが。600億件くらいのデータセットに対して SQL の COUNT(*) 文を実行しても、10秒くらいで結果が返ってくるそうです。概念としては MapReduce や Hadoop + Hive に似ているのかもしれませんが、結果セットがすぐに返ってくる、という点がポイントです。Google Spreadsheet から BigQuery を使える?とのことなので、気が向いたら実験してみても良いかもしれませんね。なお、トランザクション機能と Pivot 分析はサポートしていないそうなので、用途に合わせて考える必要がある、というところでしょうか (今後もサポートしない、ということではありませんけど)。まぁ、自分は数百億件規模のデータを気軽に扱うことは当面ありませんので、どうでもいいっちゃどうでもいい話ではあります。

Slim3がすごいトコ

次の話は App Engine の Java 用のフレームワークである Slim3 の紹介でした。個人的には、やっぱり型安全のためには色々なことが必要なんだよなぁ、と誰もが思っているんだと再認識できました。Controller 層の単体テストもできたり、前のテストが次のテストに影響しないようにしてくれるのはモダンなフレームワークではありがちな話ですが、仕事では (Google App Engine を使っているわけではありませんが...) 何のことやらと放置しているので耳の痛い話でした。それにしても、MyModel を定義したら自動的に MyModelMeta が定義されるのは直感的には好き嫌いが分かれそうです。型安全なクエリを生成するためや、そのチューニング、あるいは Eclipse のような IDE との親和性を高めるためであることは認識できますが、Java っぽい考え方に慣れていない人には何とも表現しようがない難しさがありそうです。

Global Transaction のサポートと、asInteger などで入力値の型キャストを担当してくれる機能は、どのプログラミング言語でも必要とされる機能ですね。他にも、テストに関する諸々の説明がありました。自分の開発マシンでテストする場合と App Engine にアップロードした後でテストする場合で、挙動が異なる可能性は仕方ないと割り切っています。しかし、本番環境でテストを実行すると、その過程も計算資源の利用としてカウントされてしまい、あまりにも大量のテストを実行するとクラウド破産を引き起こす可能性もあるとかないとか。なかなかに複雑な世界ですね。

まとめ

ぼやーっとしていた部分のいくつかが解消されて、有意義な時間でした。蛇足ですが、一番笑劇的だったのは、Google App Engine を Java で使ってる人と Python で使ってる人のアンケートをとったら Python の方がやや多く、Java の人は本当にスーツを着ていたことでした (平日の夜だから)。そうは言っても、業務レベルで App Engine を使っている人もいると思うと、計算資源の在り方、使い方は大きく変わってきています。「クラウド・コンピューティング」という表現は4年も経たない比較的新しいものですが、ことばを得たことで飛躍的な進歩の真っ只中にあります。そんな中で Google が App Engine をどのような方向に育てていくのかは興味深いですね。最後ではありますが、BPStudy を運営してくださった方々には感謝です。