アーカイブ

‘slim3’ カテゴリーのアーカイブ

オープンソース徹底活用 Slim3 on Google App Engine for Java

2010 年 9 月 3 日 tdtsh コメントはありません

読みました。

オープンソース徹底活用 Slim3 on Google App Engine for Java
オープンソース徹底活用 Slim3 on Google App Engine for Java ひが やすを,小川 信一

Amazonで詳しく見る by AZlink

内容を要約すると、GAEのデータストアはこうなってて、GAE/JのLow Level APIでデータストア操作はこうで、最後にslim3でのデータストア操作はこう、あと設計や開発のTipsが少々、と言う内容です。

残念ながら、slim3のコントローラ周りの話とか、Serviceの設計におけるベストプラクティスとか、そういうのはありません。テストに関しては若干書かれています。

slim3の生みの親であるひがやすをさんと小川信一さんの共著です。

Google App Engineのデータストアについての説明のがっつり1章45頁、Low Level APIでのデータストア操作にはなんと100頁弱も裂いて説明されています。
一回読んだ上で、リファレンスとしても使えそうです。
Google Codeの日本語ドキュメントがアレだし。

GAE/Jでアプリケーションを開発するなら、Datastoreを使うなら、買って手元に置いておくべき1冊です。slim3を使わないとしても。

そういう意味では、タイトルは著者の意向とも内容とも少し離れているかもしれません。
大人の事情なんでしょうか。

ところで紙の書籍は手元に置いてさっと参照できたりできるんでそれはそれで有用です。
でもわがままを言えば、電子書籍版が欲しかった。

この本に限らずオープンソースとかの技術書は、時を経ると内容が陳腐化してしまう。
iPhoneとかの単体アプリとしての電子書籍なら、改訂版を配布しやすいと思うんです。
ニッチな分野ですから、この本にソコまで求めるのは酷であり採算が合わないとは思いますが・・・

それほど、GAE/Jとslim3の進化のスピードは速い訳です。

カテゴリー: Google App Engine, slim3, 書評 タグ:

java の AntiSamyでサニタイズ、任意のHTMLタグを許可しscriptタグとかを無効化

2010 年 8 月 24 日 tdtsh コメントはありません

一般公開するWEBサービスを作る場合、慣れてないと手がかかるのがセキュリティへの配慮です。

Google App Engineとか使っている時点でSQLインジェクションとかディレクトリ・トラバーサルとかOSコマンド・インジェクションとか関係ありませんが、セッションハイジャックとかアプリケーションの作りに依存する部分は他のフレームワークと同じです。

気をつけたいのがXSS(クロスサイト・スクリプティング)です。

HTMLタグ不許可な場合は簡単なんですが、昨今のWEBサービスではブログをはじめフォームにHTMLタグを入力できる様なサービスが増えてきたので大変です。

良い子のウェブプログラマはIPAのガイドライン、安全なウェブサイトの作り方 (PDFファイル、2.09MB) を参考にします。

同ガイドラインでは根本解決策を「入力されたHTMLテキストから構文解析木を作成し、スクリプトを含まない必要な要素のみを抽出する」としています。
そんなもん自力で書いてられません。

そこで、OWASP(Open Web Application Security Project)謹製のAntiSamyを使いたいと思います。

 

 


ダウンロード

Google Codeから antisamy-bin.1.4.1.jar をダウンロードします。

設定はポリシーファイルで行います。テンプレが用意されていますのでダウンロードします。
ここを参考に、antisamy-ebay.xml をダウンロードしました。

 

 


インストール

基本的にjarファイルをクラスパスに置くだけ、の筈ですが、私の環境ではそれだけでは動きませんでした。(slim3 1.0.5、Eclipse 3.5、google app engine for java 1.3.6)
いろんなクラスが見つからないと怒られます。

先ほどのGoogle CodeでAll downloadsをSearch すると、antisamy-required-libs-1.2.zip が出てきます。こいつをダウンロードして解党し、依存性があるであろうjar達をクラスパスに置いたら動きました。

 

 


使い方

またもやここを参考にしてください。

一応書いときます。

import org.owasp.validator.html.AntiSamy;
import org.owasp.validator.html.CleanResults;
import org.owasp.validator.html.Policy;
import org.owasp.validator.html.PolicyException;
import org.owasp.validator.html.ScanException;
...
	public static final String PATH_ANTISAMY_POLICY = "WEB-INF/antisamy-ebay-1.4.1.xml";
...
	public static String doSamy(String str)
		throws PolicyException, ScanException
	{
		Policy policy = Policy.getInstance(PATH_ANTISAMY_POLICY);
		AntiSamy as = new AntiSamy();
		CleanResults cr = as.scan(str, policy);
		return cr.getCleanHTML();
	}
...

 

 


Youtubeを動かしたい

Youtubeのタグが弾かれる事に気がつきました。

一番なんでもアリのポリシーファイル(antisamy-anythinggoes-1.4.1.xml)に変えてもダメです。

色々ググっているウチに、先人の知恵を発見。
AntiSamy Policy to allow YouTube Videos

無事Youtubeも動くようになりました。

FireFoxのプラグインXSS MEでテストしてみましたが、機嫌よくサニタイズしている様に見えます。

満足です。

 

 


カテゴリー: Google App Engine, java, slim3 タグ:

slim3、Google App Engine for Java 1.3.6 で Blobstore APIをためす

2010 年 8 月 19 日 tdtsh コメント 2 件

slim3、Google App Engine for Java 1.3.6 で Blobstore API

Google App Engine/Java (以下 GAE/J) のBlobstore APIについて調べています。

環境はSlim3 (1.0.5) + Velocity + app engine sdkは1.3.6です。

 


Blobstore概要

まずはドキュメントを見てみます。

  • 最大2GBのデータオブジェクトを扱える
  • アプリケーションから直接Blobを作成、保存する事は出来ない
  • ここでいうBlobはBlobstoreはDatastoreのblobプロパティとは関係ない
  • Blobの削除は出来る
  • Blobの更新は出来ない
  • Blobの作成は基本的にユーザがブラウザからBlobstoreにPOST(アップロード)する
  • ImageServiceの#getServingUrl(BlogKey)でURLを取得できる(ブラウザで見られる)
  • アプリケーションからBlobの取得は制限されているが方法はある
  • Blob保存と同時にDatastoreにBlobInfoエンティティが保存されるらしい
  • 管理コンソールのDatastore ViewerではBlobInfoエンティティは見えない。
    (Blob Viewerで見えるのが多分ソレ)

要するにBlobstoreは、文字中心のDatastoreとは別に、ビデオとか画像などの大容量ファイルをストアするためのものです。

BlobstoreはGAEと連携可能な画像サーバが使える様なイメージで考えてよいと思います。

Picasaのインフラを使っている様で、個人的には予想どおりで嬉しいです。
GAEからGoogleアカウントのPicasaデータを出し入れ出来る様になる日が来ると予想&期待して待っています。

 


アップロード

基本的にformでPOSTするだけです。
ただ、actionに指定するURLを、BlobstoreServiceの#getBlobUploadUrl(戻りURL)で生成する必要があります。
サンプルコードは擬似的にVTLで書いたものです。
実際にはactionのURLはこのページのController側で生成しておくとかします。

#set($returnUrl="/path/to/return/url")
<form action="$BlobstoreService.getBlobUploadUrl($returnUrl)" method="post" enctype="multipart/form-data">
	<input type="file" name="myImage">
	<input type="submit" value="Submit">
</form>

 


戻りURLのコントローラ

アップロードしたままでは、後でアプリケーションからBlobstoreのBlobを探せません。
Blobのキーを取得し、Datastoreとかに保存しておく必要があると思います。

なので先述のアップロードの際に指定する戻りURLに該当するコントローラを作成します。
先述の例にあわせると path.to.return.UrlController.javaって事になります。

こんな感じでしょうか。

public Navigation run() throws Exception {
	...
	HttpServletRequest request = RequestLocator.get()
	// ControllerクラスのFieldにrequestがセットされているので上の行は不要です。
	// ひがやすをさんご指摘有難う御座いました。

	BlobstoreService service = BlobstoreServiceFactory.getBlobstoreService();
	Map blobs = service.getUploadedBlobs(request);
	BlobKey blobKey = blobs.get("myImage");
	String keyString = blobKey.getKeyString();
	....
	keyStringをなんかのEntityにセットしDatastoreに保存

 


BlobInfoの取得

Blobのキーさえ後で判れば、いつでもアプリケーションで BlobInfo を取得できます。

管理コンソールのBlob Viewerでも参照できます。
BlobInfoはBlobKey、FileName、Content Type、Size、CreationDate等を保持しています。

BlobInfoFactory factory = new BlobInfoFactory();
BlobInfo blobInfo = factory.loadBlobInfo(blobKey);

 


Billingの設定

ここまではローカルでテストできますが、画像閲覧とかは本番環境にデプロイしないと出来ませんでした。

で、本番でBlobstore APIを使うには、課金を有効にする必要があるようです。
そういえばやっていませんでした。

わたしは以前Picasaの有料ユーザになった事もあり既にGoogle Checkoutのアカウントがありましたので簡単でしたが、初めての場合は多分クレジットカード番号の入力とかが必要です。

課金を有効にしたからといって、Quotaを超えなければ課金されない(はず)です。
しらないウチにアクセスが集中したりして課金されるのは嫌なので、Stored Data以外は$0の方向でリソースを割り当てました。

ただBilling Settingは1週間変更できないので、すぐに沢山のデータを登録する予定があるとか、既に公開しているサービスの場合とかは、Unit Costは考えて入れた方がいいかもしれません。

 


コントローラで画像閲覧(画像のURL取得)

SDK 1.3.6から、画像URLが簡単に取得出来る様になったようです。
こんな感じです。

public Navigation run() throws Exception {
	...
	ImagesService imagesService = ImagesServiceFactory.getImagesService();
	String url = imagesService.getServingUrl(blobKey);
	return redirect(url);
}

私の環境ではURLはこんなんでした。

http://lh4.ggpht.com/XXXXXXXXXXXX

URLをブラウザで見てみると、faviconが思いっきりPicasaのソレでした。

詳しくは、Images Java API のドキュメントか、ImageServiceのJavaDocを見てください。

今日はコレくらいにします。

 


参考サイト、Blobstoreの先人の知恵

Google App Engine Blog: Multi-tenancy Support, High Performance Image Serving, Increased Datastor…

今は昔のkonjak翻訳 φ(・ω・? )…: The Blobstore Java API

Song of Cloud: AppEngine1.3.0 Blobstore API入門

App Engine 1.3.0 とBlobstore – hidemonの日記

cochica – slideshare

Images APIの制約について – Google-App-Engine-Japan | Google グループ

Song of Cloud: Blobstoreのデータをアプリケーションで利用する

カテゴリー: Google App Engine, slim3 タグ:

slim3での1対多関連での参照整合性

2010 年 7 月 29 日 tdtsh コメント 2 件

slim3での1対多関連(片方向でも双方向でもどっちも)での参照整合性の話です。

親モデルが削除された時 Datastore#deleteで親モデルを削除した場合、子モデルにセットされている関連(ModelRef< 親モデル>)は消えない様です。(2010/07/30修正)

RDBMSのいわゆる参照整合性制約での ON DELETE NO ACTION に相当する仕様みたい。

ON DELETE CASCADEとか、ON DELETE SET NULLとか、SET DEFAULT とかは出来ないようです。
ON DELETE CASCADEにしたい場合は、Datastore#deleteAllで親モデルを削除すると、子孫モデルは連鎖削除されるようです※。
※ひがやすをさん、コメント有難う御座いました。

制約が必要ならアプリケーション側での実装することになります。
残念。
あんまりメンドクサイようならがんばってissueを投げてみよう。

参照整合性は連鎖削除のみサポートされていて、ON DELETE SET NULLとかSET DEFAULT は出来ないようです。多分。
コンシューマ向けのWEBサービスの場合は通常はコレで十分でしょう。
(2010/07/30修正)

※後で確認しましたが、参照整合性の連鎖削除(deleteAllで子孫モデルも削除)
を実現するには、親と子孫エンティティを同じEntityGroupにする必要がある様です。
つまり、slim3の機能としての「リレーション」だけではやはりダメで、
EntityGroupを併用する必要があるようです。
(2010/07/30追記)

でも、RDBMS側の制約に頼ったDAOのコードを書いて仕様書やDBのスキーマを見ないとビジネスルールが判んなくなる、といった事が起こりえないというメリットはありますね。

兎に角スキーマレスは素敵。一貫性の維持とかが自己責任になり大変だったとしても。

で、親モデルを削除した後、子モデルのModelRefでgetModel()しようとすると、
org.slim3.datastore.EntityNotFoundRuntimeException
がスローされます。

こうなった時とかには、ModelRefを削除します。

削除する方法ですが、ドキュメントに明示していませんでした。
試しに ModelRefでsetModel(null) した後にDatastoreにput したら、削除された様に見えます。

その後、Slim3のJavaDocでorg.slim3.datastore.ModelRefのんを見た所、clear()メソッドありました。

ModelRefでclear() してputしても削除された様に見えます。

どっちの作法が正しいんでしょうね。
取りあえず後者を使うことにします。

カテゴリー: Google App Engine, slim3 タグ:

RDBMS脳では app engineのデータストアの概念で混乱する

2010 年 7 月 5 日 tdtsh Comments off

RDBMSを長くやっている人ほど、app engineのデータストアの概念で混乱する可能性が高いと思います。
自分もまだ時々判らなくなるので、一発整理しておきます。

まず、Entity (エンティティ) と聞くと、Codd博士のERモデルや、IDEF1Xとかの拡張ERモデルを思い浮かべてしまいます。
いわゆるリレーショナル・データモデリングにおける「実態」を表すEntityは、RDB上のスキーマの設計の元になるもの、と刷り込まれているんです。

ですが、app engine の話をするとき、Entityという言葉は文字通り実体のほう、RDBにストアされた個々のインスタンス、つまり行、タプルをイメージするべきの様です。

私だけでしょうか。微妙に混乱します。

このへんの微妙な言葉のニュアンスから、Entity Group と リレーションを混同してしまうという弊害があるんじゃないでしょうか。
実は私もそうでしたので。

Entity Group は Entity (=オブジェクト、≒タプル) を保存するときに決まる(決める)もの。
リレーションはデータクラスで定義し、Entityに保存する時に決めるもの。

エンティティグループはリレーションではない

祖先とか親とか子とかいう単語が出てくるので誤解しがちだけど、エンティティグループは、1:多のようなリレーションを表現するものではない。

トランザクションによりACID特性を保障したいときに設定するもの。

リレーションはkeyをコレクションで持ったり、Slim3のModelRefなどを使って表現する。
app engineのエンティティグループ – 理系のためのTIPS集

あとkindという言葉も、これからGAEを学ぼうとする人には鬼門になるかもしれません。

Google App Engineの本とか記事とかを読んでいると良く出てくるんですけど、日本語のGoogle Codeのドキュメントを見ても、kindの説明はありません。原文で読むとなんとなく判ってきます。

整理しておきます。

Entity (エンティティ)
	App Engine データストア内のデータ オブジェクト。
	key と プロパティ がセットされる。
	リレーショナルデータモデルで言うところのタプル。
	RDBMSで言うところの行、レコード。
	Javaでデータモデルを定義し、そのモデルのインスタンスを生成してDatastoreに
	保存したら、それがエンティティ。

プロパティ
	名前のついた値。Entityには1つ以上のプロパティがある。
	そのデータ型は整数、浮動小数点値、文字列、日付、バイナリ データなど。
	Jデータクラスのフィールドと(ほぼ)同義。

データクラス
	Javaでデータモデルを定義たクラス。

kind
	正確にはEntity's kindでしょう。
	Datastoreに保存されたエンティティのデータクラスの種類。
	リレーショナルモデルで言うところのスキーマ。
	RDBMSで言うところのテーブル。
カテゴリー: DBA, Google App Engine, slim3 タグ: