2009年6月27日土曜日

BPStudy#22に参加して来た

GAE/Jってどう使う?

スティルハウス佐藤一憲氏。佐藤一憲氏といえば、"Google App Engineのtips集"のエントリでの秀逸なまとめがありますね、ありがたいです。

JavaVMはServerVMじゃなくてHotspot ClientVM
これは今まで意識した事が無かった。ヒープのチューニングとかもあまり関係無さそうだし(できない)、あんまり意識する必要は無いかな…?と思ってる。
セッションは勝手には消えないので自分で掃除しなきゃダメ
Frameworkを使えばそっちがやってくれるはずだと思うけど、手動でやる場合は当然そぅなりますねぇ。気をつけなきゃならん。
JVM的なGlobalはダメ
使わないからこれもまた意識した事は無いけれど、ノードが違ったらダメだとの事。確かにそりゃそぅだ。ノードが同じでも、アプリが終了させられてしまぅ場合もありそぅだし。Session、Memcache、Datastore等をうまく使い分けなきゃなりませんね。
GAEのスケールアウト。50分くらい高負荷が続くとスケールされる、とかの話がどこかにあった。→実際はそれよりももっと早くスケールされてる気がするね、等等。
ここはGoogle様任せの話だけれど、ある程度の仕組みは出して欲しいトコですねぇ。たぶん皆もそぅ思っているだろぅし。
bigtableの履歴に関してはAppengineは使えない
GFSの仕組み的に全てのデータに対する履歴が絶対にあるはずで、そいつらをなんとか利用できないのか?という点がずっと気になってたけど、やっぱそーなんだなー、とあきらめがついた。
インデックスの話
これらはDatastoreの最も特徴的なところだから、特に新しい話は無かったが、説明するときの用語としてとても勉強になった。
プロパティが無い、値がnullは区別される
これはあんまり意識してなかったし、試した事も無い。実際はスキーマの拡張が行われた時にしか発生しないように思うが、Low-Level APIを使った場合は「ひとつのKindが同じプロパティ構成とは限らない(必要なPropertyだけに最適化されたRecordでKindを構成する)」という状態でスキーマを構成できる(むしろこれこそスキーマレス?)ので、それを実際に試してみよぅと思う。やっぱ無理にJDOとか使うよりLow-Level APIの方が使い勝手よいよね?というのが自分的な結論だったりするし。
アプリ全体でのACIDを行う為の実装はある
知らなかったけど、あんまりやってはいけない事だと思うし、設計や実行時のパフォーマンスに無理が出て後悔するだろぅからこの話は見なかった事にしよぅかと…。…。たぶん逃げ道としては便利なんだろけどね…。

自分としては、GAE/JのDatastoreを誰かに説明する時の説明方法を勉強できた、といぅ感想。

資料へのリンクがはてなダイアリーにあるよぅです。また、今回と同じ資料をベースにしたセミナーが7/17 18:30-20:30に開催されるようです。今回は時間の問題ではしょられた内容等の説明もあるだろぅと思われます。

scala/lift on GAE/J

yuroyoro氏。開催時間になっても登場しないとか大物すぎる。

SeasarConでの資料を拝見済みだったので内容はだいたい把握していたが、Scalaに関する理解とLiftに関する理解は深まったと思う。やっぱ資料だけ見るのと発表を聞くのは全然違うね。

自分としてLiftの"Html内のイベントとScalaの関数のバインド"が滅茶苦茶興味を持ったので、実際にGAE/J上で動かす事になるだろうと思う。コンテキストの保持を意識せず、こういった処理を行うって…これWicketやん?Scalaのパワーを持ったWicketやん!…といぅ風に見えたから。これは良い。jQueryとの親和性も高そうで、View層のコンポーネントも充実してそぅだし、もぅWicketにしか見えない。$ mvn archetype:generateして$ mvn jetty:runしたらいきなり動作するとか、やっぱりあなたはWicketなんでしょぅ?View層はWicketの方が美しそうにも感じたが、発表ではあまり深くは触れられていなかったのでよくわからない。でもたぶんWicket。まぁ、そんな感じに壮大に勘違いしてるんだけど、大変気になるものが増える事となった…。

メモ:Liftは1.1-SNAPSHOT(GAE対応版)、Scalaは2.7.5を使えばいいそぅだ。

追記

yuroyoro氏の資料もアップロードされたようです。

スタッフの方々、スピーカーの方々、皆様ありがとぅございました!

なお次回のBPStudy#23は7/31(金)19:00-21:30、"edeg2.ccクラウドコンピューティング研究プロジェクト"といぅ事だそうです。自分も仕事と調整がつけば参加したいと思います。

2009年6月19日金曜日

GAE/JのDevAppServerMainを起動するmaven pluginを作った

2009-07-27追記

SDKのバージョンに合わせてバージョンが変わってますので更新のエントリも参照する事!

今までmaven archetype pluginをいくつか作って来たけど、どれも「Eclipseが前提」となっていて、せっかくarchetype:generateでプロジェクトが作れるし、単体テストもできるのに結局Google Plugin for Eclipseappengine-java-sdkも必要なんだよな〜、mavenを使った開発っぽくないよな〜、というカンジがあった。

mavenを使うんだから、sdkなんていちいち落としてくるなんておかしいよ、プラグインが勝手に解決しろや〜、て思うもんね。そこで、以下のようなMavenプラグインを作った。

  • com.google.appengine.tools.KickStartを使ってcom.google.appengine.tools.development.DevAppServerMainを起動する。
  • 試験のためのプラットフォームとしてSDK本体が必要になるが、公式のダウンロードサイトからダウンロードしてくる事が可能。ダウンロードしてきた場合は例えばtarget/sdkなどに展開し、そこをSDKのルートとして使用する。

つまり、jettyプラグインとかcargoプラグインみたいにselenium等でintegration-testを自動で行ったり、さくっとアプリを起動して動作確認するためのモジュールです。

使い方

pluginRepositoryとしてhttp://gae-j-samples.sourceforge.jp/maven/repositoryを追加し、com.shin1ogawa:gae-maven2-plugin:1.2.1-SNAPSHOT:start(つまり、groupId=com.shin1ogawa, artifactId=gae-maven2-plugin, version=1.2.1-SNAPSHOT, goal=start)を実行してください。stopゴールはパラメータは無しで、startゴールのパラメータは以下の通り。

address(localhost),disableUpdateCheck(true),port(8080),server
これらはDevAppServerMainにそのまま渡すパラメタです。それぞれカッコ内の値がデフォルトの値です。server、って何に使うんだっけ…?
javaHome
javaを起動するためのホームディレクトリです。省略した場合はSystem.getProperty("java.home")の値を使用します。
warDirectory
SDKが使用するアプリケーションのディレクトリです。デフォルトの値はwarが設定されています。この直下にWEB-INFが配置されている必要があります。
sdkRootDirectory
appengine-java-sdkがインストールされたディレクトリを指定しますが、sdkUnZipDirectoryが指定されているとそっちを優先します。
sdkZipFile
SDKのZipファイルの場所。デフォルトの値はhttp://googleappengine.googlecode.com/files/appengine-java-sdk-1.2.1.zipが設定されています。
sdkUnZipDirectory
SDKのZipファイルを展開するディレクトリ。
sdkSaveAs
もしsdkZipFileパラメータがhttpだったりしてローカルじゃない場合に、保存するファイル名。デフォルトの値はappengine-java-sdk-1.2.1.zipが設定されています。sdkUnZipDirectoryで指定したディレクトリ配下に作成されます。もし既に存在していた場合は、リモートからダウンロードしません。
wait
DevAppServerMainを起動した状態で、そのプロセスが終了するのを待ちます。mavenでintegration-testを実行する際はpre-integration-testフェーズでfalseを指定してstartゴールを実行し、post-integration-testフェーズでstopゴールを実行して停止する必要があります。ちなみに、falseで起動してしまうと、プロセスがふたつ(KickStartと、そこから起動されたDevAppServerMain)起動されて、maven実行後にもこのふたつは止まらずに残ってしまいます。この場合は手動でkillする必要があります。

とりあえず細かい事は気にせず、以下の例を見るのが手っ取り早いです。一度でも使用するとローカルリポジトリに入ってくるので、$ mvn help:describe -Dplugin=com.shin1ogawa:gae-maven2-plugin:1.2.1-SNAPSHOT -Ddetailすると説明が表示されるはずです。

例えば、以下のようにpom.xmlintegration-test用のprofileを定義して、$ mvn -P integration-test installのようなカンジでprofileを指定しつつintegration-testフェーズが実行されるようなゴールを実行する。すると以下のように動作する。

  1. 通常のsurefire-testはskipされる。
  2. で、integration-testフェーズの直前にgae-maven2-plugin:startが実行される。
    1. 公式サイトからSDKがダウンロードされる
    2. SDKがtarget/sdkに展開される
    3. そのSDKを利用してKickStart経由でDevAppServerMainを起動する
  3. integration-testフェーズでは**/servlet/*Test.javaにマッチするテストケースが実行される。
  4. integration-testが終了すると、gae-maven2-plugin:stopが実行され、DevAppServerMainも終了する。
ちなみに、ゴールにintegration-testを指定すると、post-integration-testフェーズが実行されない。この挙動は初めて知った!!モチロン、stopゴールも実行されない為、KickStart,DevAppServerMainのふたつのプロセスが残ってしまう。

また、このプラグインを動作確認する程度だけれども、WebDriverを使ったintegration-testを行うサンプルを以下のプロジェクトに追加しています。

  • http://sourceforge.jp/projects/gae-j-samples/svn/view/gae-jdo-simple-sample/?root=gae-j-samples

2009年6月16日火曜日

GAE/Jで1MBを超えるファイルのアップロード、保存

GAEではFileのアップロードは10MBまでOKだが、DataStoreに保存できるのは1MBまで…という制限がある。分割して保存すればいいんだけど、それをラクにするためのライブラリが作られているよぅで、Google Cookbookで紹介されている。

google-file-service - Google Codeで公開されていて、そのままeclipseのプロジェクトとして配布しているっぽい。

2009年6月14日日曜日

Seasar Conference 2009 springに参加した

参加したと言っても、2コマだけ。3コマ参加する予定だったけど、3コマ目のBigtable/JDOが人大杉で入れなかった。LTと事例紹介に関しては、公式ページのタイムテーブルに情報無さ過ぎで最初からスルーを決め込んでいた。

Cubby in Action

Cubby2.0の話を聞きたくて参加した。前回聞いたときとあまり変わっていなかったように感じたが、モノ自体は着々と進んでいそう。後OValとか知らなかった。たぶんhttp://oval.sourceforge.net/の事だろぅ。guiceと連携した状態でGAE上で動作しているようだ。Guiceの時代ですね!

ServletのMockを使う事でJUnit4でActionの試験ができるそぅだ。CookieもServletのMockがどう扱うかという事で、問題無さそう。Contollerの試験ができるのは大きい。

とはいえ、JSとか描画周りの試験はやっぱりWicketTester最強、またはSelenium…となるんでしょぅねぇ。それでもデータの疎通テストとかをサクサクJUnitで回せるのはありがたいです。

T2 in Action - サンプルから学ぶT2 -

よねさんが時間を後ろに引っぱり過ぎたせいでで次のコマに並ぶ事すらできなかったです…ていうのは冗談です。よねさん+よこたさん+なぜか部屋の一番後ろで立っていたかたやまさん、の絶妙なコンビネーションによる、楽しいセッションであった。

自分としてはAMFの機能を見たかったので、AMFの機能が実際に動作しているアプリも見れてよかった。待っていたよ、AMF。細かい話だけど、リクエストを判断するためのアノテーションについて。既存のものは@GETとか@POSTなのに、@AMFじゃなくて@Amf(全部大文字じゃない)なのね。何か理由があったんだろか?BlazeDSを使ってもいいし使わなくてもT2内部の実装だけでも可能、という話は事前に聞いていて、「そりゃBlazeDS使うでしょ、安心でしょ」とか思っていたけど、T2内部の実装だと「型変換が柔軟」といぅメリットがあるらすぃ。具体的にどぅいぅ事なのかな?現在の状態だと、blazedsのjarがあるかないかで、自前の実装が適用されるかblazeDSの実装が適用されるか、が変わるらしい。今AMFを試す為のバージョンはたぶん0.6.0-SNAPSHOTかな。

参加して良かった。待ってました。というのも、自分としてはT2がGAE/Jと最も親和性が高いフレームワークだと思っているから。html5が現実的に普及するまでは、クライアント側はやっぱりリッチなプラットフォームの方が便利だと思うから(作る立場、使う立場両方で)。html5が現実的に普及したとしても、おそらく(今のアプリのアーキテクチャでよく使う)ステートはhtml5の機能で管理するだろうし、サーバ側でステートを保持しない考え方に今のうちに慣れておいた方がいいと思うし(モチロン今風に。昔はそうだったとか関係なく、新鮮な気分で)。GAE/Jではデフォルトではセッション機能が無効になっているんだけど、つまりそういう事なのかなーとか考えている。あ、別にT2がステートレス専門ってわけじゃないですよ。ちゃんとステートフルにも使えるし、SeamでいうCanversationとかBusinessProcessみたいな超絶便利な機能も、コンテナがサポートすれば使えるんでしょうから(ステートフルに使える場合はスコープの概念があると便利よねー)。

Navigationの実装として、ProtocolBufferがあってもいいのかもしれないなー。GAEの内部ではかなり使われていますよね…?

あ、MLもあるらすぃ。

Scalaのwebフレームワーク liftの紹介

自分としては上記のT2の時間はコレに参加する予定にしていたのだが、前日にshot6さんが「[T2Framework]T2AMF完成とGAEアプリのお披露目」とか書いていて、どーしてもT2の話を聞きたくなったためT2の方に浮気してしまった…。yuroyoroさんの資料はslideshareに上がっていて、家に帰ってから拝見させていただいた。わかりやすい、良い資料だからおすすめ。liftは去年にCometを使ってみたくてちょっと試したが、改めて面白そうだ、とオモタ。これも聞きたかったなー。

BigtableとJDOの勝ちパターン

人大杉で参加できなかった。。。けど、LT枠でアンコールされたらすぃ。その内容は@yamashiroさんがわかりやすく実況してくれていて、それを見る限りはGoogleのインフラの説明っぽく聞こえた。たぶん、Googleを支える技術 ‾巨大システムの内側の世界 (WEB+DB PRESSプラスシリーズ) を読んでいて、既にGAE/Jを触っている人なら聞けなかったとしても平気だよ、とか無理矢理安心しておいた。

全体的な感想とか

今後のSeasarConは、年に何回やるかは良いとして、S2Con biz と S2Con Tech みたいにわけてしまってはどぅだろか?と思った。S2Con bizでは今回で言う事例紹介的な内容にして、平日開催にするとか(ターゲットにしたい層が業務として参加しやすいはず。土日だと来ない可能性の方が高い?)。今回はちょっと技術者向けっぽく無かったし。技術的なセッションが35人部屋とかひどいよなーと。無料のカンファレンスに文句つけるならスタッフとして協力しろカス、とか言われそうだけど、フィードバックとして書いてみた。

後、アンケートを出し忘れて帰って来てしまったんだけど、認定制度みたいな話については、必要無いと思った。アジャイル関連でも結構意見が分かれていますよね。それに、SeasarFoundationの場合は具体的にどんな制度になるかは知らないけど、プロダクトもたくさんあるし、漠然とした制度を用意したところで細かいプロダクトまで知識を広げるのも大変だし。Seasar Expertみたいな中途半端ぽくなりやすそぅな制度とか、Seasar Hoge Expartみたいなやけに範囲が狭い制度があったところで…何の役に立つんだろう?結局ビジネスになりにくいんじゃないか、とかも思う。それよりは各プロダクトでコミッタをされている方々をうまく使う方向で考える方がいーんじゃないのかな?と思っちゃった。体力が必要だけど、日本にそういう組織があって欲しいし、今のところJava界隈ではSeasar Foundationが一番近そうだし。

GAE/J+T2(+Guice)用のarchetypeプラグインを作成した

昨日のWicket+GAE用のarchetypeプラグインに続けて、t2-framework(+guice Adapter)をGAE/J上で動作させるプロジェクトを作るarchetypeプラグインも作成した。本日S2Conでt2の話を聞いてわくわくしたし。

使い方

maven2がインストールされてパスも通った状態で、以下のコマンドを実行してください。

mvn archetype:generate -DarchetypeGroupId=com.shin1ogawa -DarchetypeArtifactId=gae-t2-guice-quickstart -DarchetypeVersion=1.0-SNAPSHOT -DarchetypeRepository=http://gae-j-samples.sourceforge.jp/maven/repository -Dostype=mac

もちろん、途中で改行してはイケマセン。archetype:createではなくarchetype:generateです。ただWicketの時とは違い、間違えてcreateしてもarchetype:createは失敗するのですぐ気づくと思います。

ostypeというパラメータを設定していますが、macの時だけ指定してください。windowsとlinuxはJava6の時にJava Buildpathにどういう値を設定すれば良いのかわからずまだ作っていないのですが、もしJava6が設定できなかった場合はEclipseに取り込み後にDataNucleusがEclipse内でエンハンスに失敗するとか、Classのバージョンが云々というエラーが見れるはずです。その場合はプロジェクトの設定で「JavaBuildPath」で使用されるJDKのバージョンをJava6に設定してやれば大丈夫です。。。が、明日にでもLinuxとWindowsで試す事にします。

プロジェクトが生成できたら、生成されたプロジェクトフォルダに移動して以下のコマンド。

$ mvn eclipse:eclipse dependency:copy-dependencies

後はEclipseに取り込めばOKOKです。もちろんEclipse上、Maven上、双方で単体テストが可能です。

他にも細かい説明は昨日のエントリや、下に示すドキュメントを参照してください。

公開してる場所

リポジトリ
http://gae-j-samples.sourceforge.jp/gae-t2-guice-quickstart/source-repository.html
プロジェクトの説明
http://gae-j-samples.sourceforge.jp/gae-t2-guice-quickstart/ja/

2009年6月13日土曜日

GAE/J+Wicket用のarchetypeプラグインを作成した

2009-07-27追記

SDKのバージョンに合わせてバージョンが変わってますので更新のエントリも参照する事!

久々にWicketを触っていると、"やっぱJava屋にはWicketが一番気持ちいいな…"となったので、前回のものに加えてWicket+GAE用のquickstartも作った。

使い方

maven2がインストールされてパスも通った状態で、以下のコマンドを実行してください。

$ mvn archetype:generate -DarchetypeGroupId=com.shin1ogawa -DarchetypeArtifactId=gae-wicket-quickstart -DarchetypeVersion=1.0-SNAPSHOT -DarchetypeRepository=http://gae-j-samples.sourceforge.jp/maven/repository

改行を入れてはイケマセン。それと、archetype:createではなくarchetype:generateですので注意。うっかりcreateゴールを使うと、テンプレートのhtmlが思わぬ場所にコピーされてしまいます。

プロジェクトが生成できたら、生成されたプロジェクトフォルダに移動して以下のコマンドを。

$ mvn eclipse:eclipse dependency:copy-dependencies

詳しい説明は以前のエントリを見てください。eclipseのGAESDKプラグインを1.2.0のままの人とかも要注意。

公開してる場所

リポジトリ
http://gae-j-samples.sourceforge.jp/gae-wicket-quickstart/source-repository.html
プロジェクトの説明
http://gae-j-samples.sourceforge.jp/gae-wicket-quickstart/ja/

archetype:generateうぜぇ

色々聞いてくんな、一発で作らせろという人はgenerateゴール実行時に、以下のようにgroupId, artifactId, versionを渡してinteractiveMode=falseする事でサクッとプロジェクトができあがります。

mvn archetype:generate -DarchetypeGroupId=com.shin1ogawa -DarchetypeArtifactId=gae-wicket-quickstart -DarchetypeVersion=1.0-SNAPSHOT -DarchetypeRepository=http://gae-j-samples.sourceforge.jp/maven/repository -DgroupId=com.hoge -DartifactId=com.hoge.gae-wicket -Dversion=1 -DinteractiveMode=false

2009年6月12日金曜日

Google Developer Day/Hackathon編

自分は「MailサービスとURLFetchサービスの単体テスト方法を探る」というカンジの、アプリを作るという事とははずれた事をテーマに作業した。なんとか発表には間に合わせたが、チームじゃなくて個人で作業した方も多かった事で発表者が非常に多くなり、あんまり時間をかけては迷惑だろう(発表順が二人目だった&人数から逆算すると3分くらいか?という計算)、という焦りと外部ネットワークに繋がらなかったという影響のため、実際に動作を見せる事ができなかった、という残念な結果に。その分このエントリで細かく書いておこう、と。ついでに、ハッカソン終了後の改良も追加しておくw

ちなみに、問題無く実行されると以下のように出力される予定でした。originalがプロダクトコードからの実際のリクエストやレスポンスで、modifiedがすげ替えたものの値…。

Mailサービス

Mailは簡単。ドキュメントもあるくらい。

URLFetchサービス

こいつが大変だった。ドキュメントを見ると、単体テスト時はダイレクトに実際のURLに接続します、みたいに書いてある。というのも、URLFetchに関しては通常のjava.net.HttpURLConnectionがを使うため、SDKが起動していない状態だとHttpURLConnection(sun.net.www.protocol.http.HttpURLConnectionとか)が適用されてしまい、ふっつーに指定されたURLにアクセスしてしまうため。

極力プロダクトコード側には仕組みを埋め込みたくない、となるとHttpURLConnectionを自前で実装してそれを適用させるのが近道じゃね?というのが最初の案。この方法なら低レベルでの話だしGAEも全然関係ないだろし、と。書いていくと、すぐに"URLStreamHandler"クラスにエラーマーカーが。

とはいえ所詮Eclipse上のGoogleプラグインのValidateだけの話でJava的にはエラーではないし、Testコードのため実行時には問題は起きないし、まぁいいか?無視しちゃう?とは思ったが、Eclipseを使う事が多い人はずっとエラーマーカーが残ったままってのは気持ち悪いはずなので別の方法を考えてみる(警告のマーカーだったら無視してたかもw)。

んじゃ手を抜くのはあきらめて、たぶんAppEngineの試験という意味では王道であろう、ApiProxyのDelegateをいじるとするか、と。GDDのGAEJセッションでもそんな話が出てたし。

URLFetchでもApiProxyを経由させたい

ApiProxyを経由させるためには、SDK上で実行しているときと同じHttpURLConnectionの実装を適用したい訳で、これを設定しているメソッドを探す。デバッグしていくと、com.google.appengine.tools.development.StreamHandlerFactory.install();の中でURL.setURLStreamHandlerFactory()している事がわかるので、これをTestコード実行時の早い段階で実行してみると、無事にApiProxyを経由している事が確認できた。

ApiProxyLocalを実装

公式ドキュメントの単体テストの資料にあるソースでは

ApiProxy.setDelegate(new ApiProxyLocalImpl(new File(".")){});
とか書かれていたりする、ApiProxy.setDelegate()で設定するモジュール。こいつを実装してやるわけです。その実装の中でドキュメントにあるApiProxyLocalImplのインスタンスを保持し、こいつに各処理を委譲してやります。もちろん、全ての処理を委譲したら何の意味も無いので、一部のメソッドは委譲したりしなかったりするわけで、そのメソッドはbyte[] makeSyncCall(Environment, String, String, byte[])です。一見getService()だな、と思うけど、それは実はどーでも良い(実装の方法に依存するけれども、makeSyncCall->getService()という実行順なので)。

実行時には、まずサービス名とサービスクラスのメソッド名、メソッドの引数がmakeSyncCall()に渡されて、makeSyncCall()getService(サービス名)で実行すべきサービスを取得して実行すべきメソッドをディスパッチする、といったカンジ。引数や返り値はbyte[]配列で統一されているが、ProtocolBufferかなー、と。これらを考慮して、以下のように実装してみた。

コメントにある通り、とりあえずURLFetchServiceだけに対応している。が、 serviceMocksというMapを使ってサービス名をキーにLocalRpcServiceの実装を保持するようにしている。

で、TestCaseの抽象クラスは以下のようなカンジに。

そしてURLFetchService用にインターフェースと抽象クラスを用意した。

実際にこれを使用しているテストケースは以下のようなカンジ。テスト対象はここには書かないけど、FriendFeedのAPIを使用するクラスとなっている。ユーザ情報を渡さずにpublic timelineを取得したり、nicknameとremoteKeyでBasic認証を行ってユーザのHome Feedを取得したり。

UrlFetchServiceMock.AbstractUrlFetchServiceMockをインスタンス化し、抽象クラスから取得したApiProxyLocalMockaddService()をしてます。で、UrlFetchServiceMock.AbstractUrlFetchServiceMockではabstractになっていたURLFetchResponse fetch(URLFetchRequest)、つまり実際にレスポンスデータを作成するメソッドを実装しています。ここではURLやリクエストヘッダを見て返すデータ(テストデータとレスポンスコード)を振り分けています。

datastoreやmailサービスと違い、結構面倒臭いです。面倒くさいですが、テスト時に外に出て行って想定できないデータをとってきたりするのも困るワケで、データを固定に出来る(エラーも試しやすい)とでテストケースも書きやすくなるんじゃないかと。また、作業したソースは以下のSVNRepositoryに存在しています。

余談(SDKのソースについて)

実は作業を始める前に、SDKのソースが無いと不便だと思って、日本のGooglerに「Java版のSDKのソースが見つからないのですが、公開されていますか?」と質問してみた。すると「無いといぅ事は無いんじゃないかなー」と探してくださった。が、結論は「無いっぽいね」となった。それはそれで「んじゃ面倒だけどjadして確認します」とか言って作業に入ったんだけど、その後twitterでid:しげるんば(なぜかリンクされry)が「リバース禁止条項があるかも」と知らせてくれた。たしかに、そう書いてある…。特に改変配布もせず覗くだけなら良いだろうけど、ハッカソンの発表には使えないんじゃね?と思って、実はEasyMock等の使い慣れたやつで無理矢理片付けよぅとも考えていたり。が、松尾さんに相談したところそのまま海外のGooglerに持ち込んでくれて、「ま、改変して配布するとかがなく、こっそり覗くんならいーーんじゃね?」くらいのお話を効かせていただけた。おかげで調査も進んで、本来の姿かな?と思う方法に落ち着かせる事ができた。海外のGooglerの方も「公開されていると思うよ?」とおっしゃってたので、実は公開する気があるけど忘れてるだけ?とかも思う。それであると嬉しい。

また、今回書いた方法よりもいい方法があるんだろぅと思うし、どんくさい方法だな、と思ったらもっと良い方法を是非教えてください!

API Expertの方、Googler様、一緒に開発した方々、ありがとーございました。

2009年6月11日木曜日

GAE/Jでローカル実行時にApiProxyLocalから取得できるサービス一覧メモ

テスト時に必要ですよね。

ApiProxyそのもの

com.google.apphosting.api.ApiProxy.Delegate
下記ApiProxyLocalの親インターフェース
com.google.appengine.tools.development.ApiProxyLocal
上記を継承したインターフェース。getService()メソッドもこのインターフェースで定義されている。
com.google.appengine.tools.development.ApiProxyLocalImpl
ApiProxyLocalの実装

ApiProxyから取得するサービス

com.google.appengine.tools.development.LocalRpcService
ApiProxy#getService()で返るインターフェースの型。以下のサービスは全部これの実装。これを実装したクラスのgetPackage()が返す値が、ApiProxyLocal.getService()で指定すべき値。
ローカル用のサービスの実装
com.google.appengine.api.datastore.dev.LocalDatastoreService
データストアサービスの実装。getPackage()が返す値は"datastore_v3"
com.google.appengine.api.users.dev.LocalUserService
ユーザサービスの実装。getPackage()が返す値は"user"
com.google.appengine.api.urlfetch.dev.LocalURLFetchService
URL Fetchサービスの実装。getPackage()が返す値は"urlfetch"
com.google.appengine.api.mail.dev.LocalMailService
Mailサービス。getPackage()が返す値は"mail"
com.google.appengine.api.memcache.dev.LocalMemcacheService
memcacheサービス。getPackage()が返す値は"memcache"
com.google.appengine.api.images.dev.LocalImagesService
画像サービス。getPackage()が返す値は"images"

サービスの実装を指定している場所

正式なGoogleのSDKに含まれるjarは使ってないからわからんけども、mvnsearchのリポジトリにあるjarでいぅと"appengine-1.0-stubs-1.2.1.jar"の中の"META-INF/services/com.google.appengine.tools.development.LocalRpcService"で以下のように指定されている。

com.google.appengine.api.users.dev.LocalUserService com.google.appengine.api.datastore.dev.LocalDatastoreService
com.google.appengine.api.memcache.dev.LocalMemcacheService
com.google.appengine.api.urlfetch.dev.LocalURLFetchService
com.google.appengine.api.mail.dev.LocalMailService
com.google.appengine.api.images.dev.LocalImagesService

ちなみに、Webコンテナも同様にサービスとして実行時に解決されていて、インターフェースは"com.google.appengine.tools.development.ContainerService"で、定義は"appengine-api-1.0-runtime-1.2.1.jar(例のごとくmvnsearchのリポジトリ内のjarでの話)の、"META-INF/services/com.google.appengine.tools.development.ContainerService"で以下のように定義されている。

com.google.appengine.tools.development.JettyContainerService

2009年6月10日水曜日

Google Developer Dayに参加して来た [#gdd09]

元々はHackathonのみ参加する予定だったんだけど、超おすすめされたのでGoogle Developer Day 2009の方にも参加する事にした。

受付

普通に受付。グッズは、タオルとChromeの説明がコミック形式で書かれた冊子、おまけにマスクw マスクをつけてる人は殆どみかけなかったな…。

基調講演

昨年まで課題となっていたものが解決されていっている、という事で、html5の紹介。Canvas,Video,Cache Database,GeoLocation,Web Workers、それぞれのデモや組み合わせたデモ。めっちゃグリグリ動いていて正直驚いた。ChromeのDevPreview版よりももっと新しいバージョンなのかな?YouTubeがHtml5でプラグイン無しで動作していたように思う。

Androidの話で印象的だったのは、シェアが18%というデータソースもあるとか、USでモバイルブラウザのシェアが2位、とかそういう話。アプリも5000本以上存在しているそうだ。ちなみに、PalmPreを引き合いに出したりはしてなかったと思う。ちなみに、日本では最初は無償アプリのみでスタート、有償アプリが始まった後は最初はクレジットカードでの決済のみ、との事。あと、全員にAndroidあげるよ、と。これは意外だった。日本でもこれをやるとは思ってなかった。てっきりGoogle Waveのアカウントへの招待メールを全員に!てのがサプライズだと思ってました。嬉しい。みんな持って帰ってガンガンあぷりを作れよ!との事。

DoCoMoの方の話は「スマートフォンは成長度合いがすごい(既存市場は20%縮小ながらスマートフォンは20%成長)、でも、この成長の角度を落とさないためにはデバイスや料金体系ももちろんだが、なんせアプリだ、いいアプリつくってよ」みたいな話と認識した。HT03Aは「ケータイするGoogle」といううたい文句らしい。これはどぅだろう、と思う。それだけじゃ、普通の携帯でもGoogleできるやん、としか捉えられないような。Googleというより、AndroidのPushNotification、GeoLocation、それこそ自由なアプリ、をもっと全面に押した方がいいんじゃないかな、と感じた。より強力なiコンシェルにもなるし、リアルタイムストリームとして現状最適だと言ってもよさげなプラットフォームなんだから。予定している時期は6月末から7月上旬。専用CMを作ったとか、とにかく力は入れているっぽかった。

自分はOpenSocialはあまり興味が無かったんだけど、MixiのアプリとAndroidのPushNotificationを組み合わせたデモは興味を惹かれた。Mixiアプリの課金体系としては、開発者側が8割らしぃ。笠原氏曰く「もし今、自分が起業するのであれば、絶対にMixiアプリを作る」との押し具合。OpenSocialの開発ツールはEclipsePluginとして提供されている。

Google Friend Connectが一瞬紹介されて、Waveの話へ。これはアップロードされたビデオを見た人にはあんまり意味なしだった?主にデモ。何週間か待てば、参加者全員にGoogle Waveアカウントの招待メールが送付されるらしい。これも嬉しい。

GoogleMaps APIでは、もうすぐ日本語版にもルート検索が追加されるらしい。

本日 Tokyo Google Tech User Group が発足です、と。早速登録した。また、明後日にHackathonですよー、でもさすがに閉め切ってます、と。大丈夫、申し込んであります!がんがります!

HTML5 により拓かれる次世代 Web

自分としては「各ブラウザがhtml5を部分対応しているのは知ってる。QConでもDylan Schiemannがそんな事を言ってたし。でもhtml5を実際に使うなんてまだまだ先の話だよ」という認識があった。先のGoogleWaveの発表も「へぇ、Googleが何かhtml5を急いでるぽいな。でもGears依存でしょ」くらいでしか無かった。だが基調講演でショックを受け、ホントはGAEの話を聞く予定だったのをやめてhtml5を聞く事とした。「html5はアプリケーションプラットフォームです」に始まり、アプリケーションを構成するためのUI系のコンポーネントの紹介等。DataGridに興味津々になってしまったが、紹介が速攻で終わって残念。コンポーネント系意外で出て来たhtml5の新しい要素はおおむね基調講演の話通りだったと思うんだけど、最後列で立ち見(実際には座ってたけど)の状態で、スライドも全く見えなかったので完全に聞き取れたか自身が無い。その代わりshot6たんのtweetを極力favって後で見返す事にしたり。足がしびれたが、なんとなくイメージが掴めたのでおk。

Java で動かす Google App Engine

これがメインだったけど、ちょっと物足りない感じがした。Javaの人向けの説明であれば、EntityGroupとTransactionまわりをもう少し説明して欲しかったなーと思った。Low-level APIとかも。あとTapestry動きます、に少しうけた。紹介、という意味では良い、のかな。

Google & Open Source

Google内ではどのようにオープンソースに関わっているのか、また関わっていくのか。ちょっと、アピールがうさんくさく感じてしまったw あと、ライセンス関連は自分は知識が足りないのと、同時通訳の人も随分疲れておられたようで、理解が難しいセッションとなった気がする。

Google テクノロジー ライトニングトーク

すごい立ち見。ドアの外から立ち見する事となった。このラストに近い時間に立ち見はなかなかつらかったが、いくつも面白いLTを拝聴できた。自分的に印象的だったのはふたつ。

  • Androidと組み込みの話。QConTokyoで木南さんと江川さんから聞いたお話とかなーりかぶる点があり、fmfm、と。
  • 「少し時間に空きができたので、DalvikVMを実装しました」とかw DalvikVMのチューニングをされているよぅなので、期待。

総括

やっぱhtml5の衝撃につきる。細かい仕様だとかそんなのはどーでもいいとして、Google様が使う気満々な点、これに衝撃を受けた。着手せねばならんよぅです。あと、同時通訳の品質がQConTokyoと比べると雲泥の差があった。QConTokyoは4万(早期優待の2万で買ったけど)、こっちは無料なのに…。

受付で貰ったChromeのちょっとした小冊子が、想像以上によくできていた。結構力が入ってるなーと感心してしまいました。

ビミョーに残念なのは、Office Hoursで質問しようとしていた内容をぶつける先が無かった事。だって、Vnの人に「Javaはおことわりでお願いしますよー、Pythonでお願いします」とか言われたしw まぁそれは冗談として、聞きたかった内容は以下のとおり。自分で調べたり、明後日のHackathonで他の人に確認してみようと思います。

  • Localで動作させているSDKのソースは公開されているのか?単体テスト時に使用するruntimeのソースも見たい。
  • ApiProxy.getDelegate().getService("")で取得できるサービスの一覧ってどこにありますか?

Android

とりあえず使ってみた感想を述べると、操作性の面ではiPhoneに相当及ばない、と感じた。動作速度も、YouTube以外はiPhoneの方が格段に良い。文字入力なんかは初期の頃のiPhone3Gを彷彿させる、微笑ましいカンジ。このままの性能では、初期の段階では開発者以外には受け入れられないんじゃないかなーと思ったけど、操作性云々ハード云々パフォーマンス云々、は後からついてくるだろぅし、Androidをそういう目的では捉えていないので、結局「色々遊べるぞー」と張り切っている次第です。

スタッフの皆様、貴重な体験をありがとうございました、感謝しております!

追記

ゲットしたAndroid端末は、背面に"GoogleDeveloperDay2009"のロゴがプリントされていて、起動時のロゴも同じく。そしてModel numberは"GDDJ-09"と、GDD09モデルとなっていてまた嬉しかったり。

2009年6月1日月曜日

ActionScriptのエディタ

うちの嫁が開発している Amateras ProjectAIR GEAR に使ってもらおうと思っているActionScript用のエディタEclipseプラグインが少しずつ動き始めた。

AIR GEAR に足りない、構文解析が必要な機能(Outline, Type Hierarchy, Code assist)を主に組み込んでいくつもりなので、今はAIR GEARのテキストエディタよりも機能が貧弱だw

こいつはsf.jpにプロジェクトを立てて作業してます。sf.netはsvnが遅すぎて使い物にならない…。