[OSGi][Spring Framework] OSGi + Spring-DM = High Cohesion + Low Coupling

Cytoscapeは、Version 3からOSGiベースのアプリケーションになります。ユーザー側から見て大きな変化はありませんが、プラグインを書いて独自の解析を行なおうと言う場合などには、色々と新しい概念を憶えなくてはならなくなります。最初は面倒かもしれませんが、一度憶えると、きれいな実装を実現することが比較的容易になります。

自分も色々試行錯誤しながらやっていますが、なにぶん新しいテクノロジーなので、文献が充実しているとは言いがたい情况です。特に日本語の資料になると、概念の説明ばかりで、「じゃあ実際どうやるの?」と言うところで行き詰まる場合が多いと思います。そこで、少しでも将来Cytoscapeプラグインを書いてくれる方が増えれば、と言うことで、少しずつこのあたりの技術のチュートリアル的なものを書いて行こうと思います。

前堤条件

  • Javaを一通り知っている
  • Mavenが何かくらいは分かる
  • Springが何をするのかなんとなく分かる

Hello World

まず環境の整備。必要なものは以下の通りです:
- UnixマシンかMac(Windowsではまだ試してないので、後ほど)
- Java SE 5以降のJDK
- PAX-Construct
- Maven(の素晴らしいチュートリアル)
- Eclipseとm2eclipseプラグイン

「あれ?SpringとかOSGi関連のライブラリは?」と思うかも知れませんが、その辺は上記のツールが勝手にやってくれます。便利。

実際の手順
  • Mavenをインストール。そして、上のリンクを読んで、凡その概念を学ぶ。要するに、便利なAntとでも憶えておけば大体あっています。
  • Pax-Constructをインストール。と言っても、ただのスクリプト集なので、ダウンロードした後、binディレクトリにパスを通せば完了です。ためしに、
pax-update

とタイプし、

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------

と言う感じに表示されれば、インストールできてます。

#!/bin/sh

pax-create-project -g org.cytoscape -a hello
cd hello

pax-add-repository -i spring-maven-milestone -u http://maven.springframework.org/milestone
pax-import-bundle -g org.springframework.osgi -a spring-osgi-extender -v 1.1.0-m2 -- -DimportTransitive -DwidenScope
pax-import-bundle -g org.slf4j -a slf4j-simple -v 1.4.3

pax-create-module -a wrappers
cd wrappers

pax-wrap-jar -a asm -v 2.2.3
pax-wrap-jar -a aopalliance -v 1.0

cd ..

pax-create-bundle -p org.cytoscape.helloservice -- -Dspring -Djunit
pax-create-bundle -p org.cytoscape.helloserviceuser -- -Dspring -Djunit
  • 実行が終ると、helloと言うディレクトリが出来ているはずなので、その中に入ります。こんな感じになっているはずです:
org.cytoscape.helloservice       pom.xml  provision
org.cytoscape.helloserviceuser  poms     wrappers
mvn clean install pax:provision

長々とメッセージが表示されたあと、エンターキーを押せば、プロンプトが表示されていると思います。ここでpsとタイプして下さい:

  • > ps
START LEVEL 6 ID State Level Name [ 0] [Active ] [ 0] System Bundle (1.0.3) [ 1] [Active ] [ 5] spring-osgi-extender (1.1.0.m2) [ 2] [Active ] [ 5] spring-osgi-core (1.1.0.m2) [ 3] [Active ] [ 5] jcl104-over-slf4j (1.4.3) [ 4] [Active ] [ 5] slf4j-api (1.4.3) [ 5] [Installed ] [ 5] slf4j-log4j12 (1.4.3) [ 6] [Active ] [ 5] spring-osgi-io (1.1.0.m2) [ 7] [Active ] [ 5] spring-aop (2.5.4) [ 8] [Active ] [ 5] spring-beans (2.5.4) [ 9] [Active ] [ 5] spring-context (2.5.4) [ 10] [Active ] [ 5] spring-core (2.5.4) [ 11] [Active ] [ 5] spring-test (2.5.4) [ 12] [Active ] [ 5] aopalliance.osgi (1.0.0.SNAPSHOT) [ 13] [Active ] [ 5] slf4j-simple (1.4.3) [ 14] [Active ] [ 5] asm 2.2.3 [osgi] (2.2.3) [ 15] [Active ] [ 5] aopalliance 1.0 [osgi] (1.0) [ 16] [Active ] [ 5] org.cytoscape.helloservice (1.0.0.SNAPSHOT) [ 17] [Active ] [ 5] org.cytoscape.helloserviceuser (1.0.0.SNAPSHOT) [ 18] [Active ] [ 1] osgi.compendium (4.0.1) [ 19] [Active ] [ 1] Apache Felix Shell Service (1.0.0) [ 20] [Active ] [ 1] Apache Felix Shell TUI (1.0.0)

先ほど作った二つのバンドルがしっかり実行されているのが分かると思います。基本的にこれだけでひな型から実行環境まで全て整備されます。便利でしょ?

何が起こったのか?

先ほどのスクリプトを実行して、最後のmavenコマンドを実行したところまでに以下のことが自動的に実行されています:

  • helloという新しいプロジェクトを作製
  • アーキタイプから必要なpomファイルを自動的に作製
  • OSGi, Springを使うのに必要なファイルを自動ダウンロード
  • バンドル化されていないライブラリについては、ダウンロードの後メタデータを付加、OSGiバンドル化
  • helloservice, helloserviceuserと言う二つのバンドルを作製。いずれもSpring設定ファイルのひな型を自動的に作製。
  • Apache Felixを使った実行環境を自動的に整備
  • 作製されたバンドルを全て読み込み実行

これらを全部手作業でやるととんでもなくめんどくさいのですが、pax-constructを使うことで大幅に負担を軽減できます。これらの作業がOSGiの世界に踏みこむのを躊躇させる原因にもなっていると思うので、素晴しい仕事だと思います>PAXプロジェクト

続き
  • では、ここから先はEclipse内でいじりますので、Eclipseで読めるようにプロジェクトを作製しましょう:
mvn pax:eclipse

とタイプすると、自動的にEclipseプロジェクトが作製されます。m2eclipseプラグインがインストールされたEclipseに、Importメニューから読み込ませます。

とりあえずこの状態でひな型が自動的に作製されたので、これを元に作りましょう。ここで作るものは、helloserviceと言う、OSGiサービスを提供するバンドルと、そのサービスを消費するhelloserviceuserというバンドルです。直にOSGiAPIをいじるのではなく、その辺のワイアリングはSpring Dynamic Modulesにまかせます。こうする事により、バンドル内のオブジェクトは完全にPOJOとなります。つまり、OSGiSpring FrameworkのどちらのAPIも直に叩きません。

OSGiサービスって何?

ちょっとだけ概念の説明。OSGiサービスと言う言葉は非常に誤解しやすいのですが、要するにOSGiのサービスレジストリによって監理されているオブジェクトへのリファレンスだと考えて下さい。あるユーザーバンドルが、「このオブジェクトをください」とサービスレジストリに問い合わせると、そこで監理されたオブジェクトヘのリファレンスを受け取ることが出来ます。Spring Dynamic Moduleでは、このサービスを、beanの組み合わせとして構成し、エクスポートすることが出来ます。

第ニ回へ続く)