2011-04-30

The Vanished Man

"マジックのトリックはどれも効果(エフェクト)と手段(メソッド)の二つから成り立っています。エフェクトというのは、観客の目に映るもののこと。...メソッドは、マジシャンがその裏でしていること。"

2011-04-26

Morphia Feasibility Study, part 3 - Spring configuration

Morphia の DAO オブジェクトを Spring で設定してみる。Morphia グループディスカッションのスレッド「IoC in Morphia BasicDao」を参考にした。


エンティティの定義
Spring Data Document の例から引用。


それぞれ、MongoDB コレクション "spring.person" と "spring.account" に対応付ける。これらのコレクション名は一見すると階層的だが、MongoDB にとってはフラットである。すなわち、"spring" というコレクションが存在するわけではなく、両者に依存関係もない。しかし、このような名前を使用することで、データどうしの関係が人間にとってわかりやすくなる。


DAO の定義
Morphia にはBasicDAO クラスが用意されており、エンティティと id の型をパラメータに指定するだけで簡単に DAO を定義できる。




Spring コンテナの設定
さて本題。Spring の XML による設定は以下のとおり。


ここで、"#{ T(example.spring.Person) }" は、java.lang.Class のインスタンス、すなわち example.spring.Person.class を表す。part 1part 2 の例では、Morphia.map() メソッドで一つずつクラスを指定したが、コンストラクタの引数に Set でまとめて与えることもできる。


アプリケーションコード
DAO オブジェクトを生成し、エンティティを操作するコードは以下のとおり。上の XML が クラスパス上の app-context.xml ファイルに保存されているとする。


Person クラスでは、accounts フィールドに対して @Reference アノテーションを付けている。つまり、Account オブジェクトを独立したドキュメントとして保存し、Person ドキュメントは Account ドキュメントを id で参照する。

注意すべきは、Account オブジェクトを先に保存することである。保存してはじめて Account ドキュメントの id 値が決定するからである。


保存されたドキュメント
上のコードで保存されたドキュメントの JSON 表現を見てみる。


Account ドキュメントへの参照は、コレクション名とドキュメント id で与えられる。


課題:
  • TypeConverter を設定する方法
リソース:

2011-04-22

(BETA) Visualizing radioactivity level using Google public data explorer, part 3

環境放射能水準データ(文部科学省提供)の可視化について、その後も Google Public Data Explorer のデータを更新している。しかし、本日(2011-04-22)、PDF ファイルを取得しようとしたところ、文部科学省の Web ページの URL が変更されていた。新しい URL は以下のとおり。

最新のデータはこちらでご覧あれ。

2011-04-21

Morphia Feasibility Study, part 2 - enum

part 1 で示した2番目の要求、「インスタンス変数を持つ enum を扱えること」を試す。

インスタンス変数を持つ enum とは?
ここでの目的は、Java の識別子ではない定数のリストを定義することである。以下の Enum 型 ComplexEnum は一つの例である。AT_LEAST_ONE 定数の「値」"at least one" は、空白を含むので、enum 定数として直接宣言できない。ONLY_ONE も同様。



これまで、Java オブジェクトの永続化に RDB を利用し、O/Rマッピングに Castor を利用してきた。Castor は多態性をサポートし、上記のような enum 型も「ある約束」に従えば問題なく SQL CHAR/VARCHAR にマップしてくれる。ある約束とは、上記の fromValue と value メソッドである。

さて、MongoDB ではどうか?


単純な enum 型
まず、以下の単純な enum 型 SimpleEnum を試す。コンテナクラス SimpleEnumContainer を MongoDB のコレクション "enum" に対応付ける。



Morphia を使って、MongoDB への保存と読み出すコードは以下のとおり。特に何もせずに、単純型の値と同じように保存できる。



MongoDB に保存されたドキュメントは以下のとおり。




インスタンス変数を持つ enum 型
いよいよ本題。最初に示した ComplexEnum 型を試す。コンテナクラスは以下のとおり。



Java オブジェクトと MongoDB ドキュメントとの間で特別なマッピングを行うには、TypeConverter を使う。ComplexEnum に対して、以下のように encode/decode メソッドを定義する。


update (2011-04-26): implements SimpleValueConverter を追加。


この ComplexEnumConverter を使ったオブジェクトの保存/読み出しのコードを以下に示す。



MongoDB に保存されたドキュメントは以下のとおり。



これで Morphia が所期の要件を満たすことがわかった。

次は、オブジェクト間の関連(1:n や m:n)について試したい。


リソース:

2011-04-20

Morphia Feasibility Study, part 1 - polymorphism

MorphiaSpring Data for MongoDB のどちらを使うか? を検討している。要求は次のとおり。
  • 多態性 (polymorphism) に対応していること
  • インスタンス変数を持つ Enum を扱えること
Spring Data のドキュメントやコードをざっと見た限り、多態性には対応していないようだ。一方、 Morphia はドキュメントで説明しているように、この要件を満たす。そこで、Morphia を試すことにする。


ここでいう多態性とは?
抽象クラスやインタフェースのレベルで永続オブジェクトを操作できること。例えば、クラスA、B、C が次のような関係にあるとする。



このとき、db.find( A.class ) のように、B と C を区別せずに読み出したり検索したい。


なぜ Morphia は多態性を扱えるか?
ドキュメント内の className という特別なプロパティに Java のクラス名を保存しているから。例えば、Java のクラス B の完全修飾名が org.example.B だとすると、B オブジェクトを MongoDB に保存した場合、ドキュメントの JSON 表現は以下のようになる。



この仕組みによって、データベースからドキュメントを読み出したときに、どのクラス型の Java オブジェクトを生成すればよいかを(Morphia が)判断できる。多態性を扱う必要がない場合など、この className プロパティを保存しないように設定することもできる。


テスト
以下に示すコードでは、import 文、コンストラクタ、setter/getter を略す。MongoDB のデータベースを test、コレクションを polymorphism とする。

ドメインモデルのクラスは以下のとおり。Java クラスと MongoDB コレクションとの対応付けを @Entity アノテーションで行う。@Id アノテーションは MongoDB の _id プロパティへの対応付けを示し、org.bson.types パッケージで定義された ObjectId 型にしておくと Morphia が自動的に値を割り当てる



注意すべき点は、多態的に操作したい抽象クラスもコレクションに対応付けておかねばならないことである。

インスタンスの保存と読み出しの簡単なコードを以下に示す。



get では個々の具象クラスを指定して読み出している。find では A 型のインスタンスをすべて読み出している。元のコレクションが空だとすると、listA.size() は3になる。

Mongo シェルで db.polymorphism.find() して、コレクションに保存されたインスタンス(ドキュメント)の JSON 表示を見てみる。



Morphia の多態的操作について、最も基本的な動作を試した。今後、検索や更新についても試していく予定。


リソース:

2011-04-15

Spring Data for MongoDB 1.0.0 M2

Spring Data for MongoDB 1.0.0 M2 を試そうとしたが、以下のクラスで ClassNotFoundException。
  • org.springframework.data.mapping.context.MappingContextAware
いずれの JAR ファイルにもこのクラスが含まれていない。

フォーラムをみると、 リリースをアナウンスしたスレッドに同症状の応答あり。(おそらく)Maven の設定で spring-data-commons-core のバージョンを 1.0.0.RC1 に書き換えたら解決したとのこと。



Maven は使っていないので、同 JAR のダウンロードリンクの URL を RC1 用に変更して直接ダウンロードした。その URL は次のとおり。
これを解凍して得た spring-data-commons-core-1.0.0.RC1.jar には問題のクラスが含まれており、この JAR に差し替えて解決した。



リソース:

2011-04-13

Painted Ladies

''幸運とは計画の残留物である''

2011-04-12

MongoDB 1.8.1 and Java Driver 2.5.3 released

2011-04-06 付けで MongoDB 1.8.1 がリリースされていた。

変更内容:
  • sharding migrate fix when moving larger chunks
  • durability fix with background indexing
  • fixed mongos concurrency issue with many incoming connections
 フィクス:

Java Driver も同時にアップデートされた。

Spring Data for MongoDB の 1.0.0 M2 もリリースされた。MongoDB Java Language Center からもリンクされている。
Morphia とどちらを使うか検討したい。

2011-04-08

(BETA) Visualizing radioactivity level using Google public data explorer, part 2

2011-04-06に環境放射能水準データ(文部科学省提供)の可視化について投稿した。4月4日19時から4月5日17時までのデータ (1304665_040519.pdf) を追加しようとしたところ、問題が起きた。

原因を探っていたところ、PDFからのテキスト抽出に問題があることがわかった。抽出したテキストのJava Stringをプリントしたところ、行数はある程度の分量があるが、印刷可能文字がほとんど含まれていない。PDFからのテキストの抽出には iText を使っていた。

解決方法として、まずは iText の PdfReader や PdfReaderContentParser クラスを調べたが、テキスト抽出に関する設定は見つからない。別のPDFライブラリを使ってみようと思い、探したところ、Apache PDFBox を見つけた。

さて、PDFBox に置き換えてみたところ、テキスト抽出はうまくいった(ようだ)。しかし、CSV への変換がうまくいかない。Java String を byte[] にしてプリントしてみたところ、行末に '\f' (form-feed) が付いていた!

元のPDFにこれまでと違いがあるのか? セキュリティプロパティの「互換性があるバージョン」が「Acrobat 7.0およびそれ以降」に対して、これ以前のPDFでは「Acrobat 5.0およびそれ以降」であった。これが原因か?

最終的に、PDFのテキスト抽出は PDFBox で行い、各行を String.trim() してから処理することで解決した。

4月5日分までのデータを追加したデータセットを Google public data explorer にアップロードしたのでご覧あれ。福島県のデータも追加されている。


(2011-04-07分までのデータを追加し、スクリーンショットを2011-04-08に貼りこみ)


リソース:

2011-04-06

(BETA) Visualizing radioactivity level using Google public data explorer

文部科学省が公開している都道府県ごとの環境放射能水準の時系列データ
Google Public Data Explorerで可視化してみた。



数値の単位 (μSv/h) が付いていないなど、完成度はまだ低い。Windows XP上のIE8とChorome 11で動作を確認した。Safariでは、「読み込み中...」で止まってしまう。

3月17日から4月4日までの正午のデータだけを登録してある。手元では全ての時間帯のデータを用意したが、Public Data Explorerが1日よりも短い単位を可視化できないからである。

文部科学省は Windows Azure 上に可視化サービスを構築しているようだ。現在の日本語トップページに日本地図があり、各都道府県をクリックするとグラフが表示される。

元データはPDFで公開されている。このPDFからテキストを抽出するには iText を使った。まずは如何様にもデータを加工できるようにすべく、ニュートラルなCSVを作成。これを DSPL 用のCSVに変換した。プログラミングにはJavaを使用。

iTextでPDFから抽出したプレインテキストでは、表の空セルを判別できない。よって、空セルがある表に対しては、データの修正が必要になる。ここはdirty hack。特に埼玉県に空セルが目立つ。PDFで発信された情報から機械可読データを作るのは難しい。


リソース:

2011-04-01

Failed to create the Java Virtual Machine.

Eclipseの起動直後、次のようなエラーが発生した。



環境:

Eclipse Java EE, 3.6 Helios
Java2 SDK, 1.6.0 update24

Eclipse Community Forumsを検索したところ、次のスレッドを発見。
eclipse.iniの設定を調整するいくつかの対処法が解説されている。この中で自分の環境の対処に成功したのは message# 656933 の -vmオプションを指定するものであった。