前にApache Felix について書いたポストと同じように、名前を受け取って挨拶を返すサービスと、それを標準出力に表示するクライアントを作ってみる。ただし、Spring DM も併用するので、OSGi 定義のクラスの派生ではなく POJO でサービスを記述するという事になる。こういった、ちょっと新しいプロダクトの組み合わせは、最初期の段階でかなりハマる事がたまにあるので、この Getting Started で技術リスクを今のうちに減らしておきたい。
便宜上、下表のようなディレクトリを作業場所とした。
c:\work2\ | ルート作業ディレクトリ |
├ client\ | クライアント用バンドル作業ディレクトリ |
├ service\ | サービス用バンドル作業ディレクトリ |
└ felix\ | 実験用 Felix 環境 |
■ 用意
- felix を落としてどっかに展開しておく(以降 {felix base}と書く)
- spring-osgi-1.2.0-with-dependencies.zipを落として、どっかに展開する。あとでspring-osgi-1.2.0の中身を使う。
- jcl104-over-slf4j-1.4.3.jarをダウンロードしておく
■ 環境作り
解凍直後の もともとの felix の構成がゴチャゴチャすると嫌なので、c:\work2\felix\を実験用 Felix 環境とする。以下は c:\work2\felix\ 下での作業。必要なものは適宜 {felix base} からオリジナルをコピーする事にする。
- {felix base}/bin/ から、felix.jar を持ってくる。
- {felix base}/から以bundle/とconf/を持ってくる
- spring-dm フォルダを作って以下のものを置く。
- spring-osgi-1.2.0/lib 下から、以下をコピーする
- com.springsource.org.aopalliance-1.0.0.jar
- com.springsource.slf4j.api-1.5.0.jar
- com.springsource.slf4j.log4j-1.5.0.jar
- com.springsource.slf4j.org.apache.commons.logging-1.5.0.jar
- log4j.osgi-1.2.15-SNAPSHOT.jar
- org.apache.felix.main-1.4.1.jar
- org.springframework.aop-2.5.6.A.jar
- org.springframework.beans-2.5.6.A.jar
- org.springframework.context-2.5.6.A.jar
- org.springframework.core-2.5.6.A.jar
- ダウンロードしておいた jcl104-over-slf4j を入れる
- spring-osgi-1.2.0/dist 下から、以下をコピーする
- spring-osgi-core-1.2.0.jar
- spring-osgi-extender-1.2.0.jar
- spring-osgi-io-1.2.0.jar
- spring-osgi-1.2.0/lib 下から、以下をコピーする
- conf/config.properties のファイル末尾に以下を追加
felix.auto.start.1=\ file:bundle/org.apache.felix.shell-1.4.1.jar \ file:bundle/org.apache.felix.shell.tui-1.4.1.jar \ file:bundle/org.apache.felix.bundlerepository-1.4.2.jar \ file:spring-dm/com.springsource.org.aopalliance-1.0.0.jar \ file:spring-dm/jcl104-over-slf4j-1.4.3.jar \ file:spring-dm/com.springsource.slf4j.org.apache.commons.logging-1.5.0.jar \ file:spring-dm/log4j.osgi-1.2.15-SNAPSHOT.jar \ file:spring-dm/org.apache.felix.main-1.4.1.jar \ file:spring-dm/com.springsource.slf4j.api-1.5.0.jar \ file:spring-dm/com.springsource.slf4j.log4j-1.5.0.jar \ file:spring-dm/org.springframework.aop-2.5.6.A.jar \ file:spring-dm/org.springframework.beans-2.5.6.A.jar \ file:spring-dm/org.springframework.context-2.5.6.A.jar \ file:spring-dm/org.springframework.core-2.5.6.A.jar \ file:spring-dm/spring-osgi-core-1.2.0.jar \ file:spring-dm/spring-osgi-extender-1.2.0.jar \ file:spring-dm/spring-osgi-io-1.2.0.jar
- log4j.properties を適当に書く(例えば以下のように)
log4j.rootCategory=INFO, LOGFILE log4j.appender.LOGFILE=org.apache.log4j.FileAppender log4j.appender.LOGFILE.File=felix.log log4j.appender.LOGFILE.Append=true log4j.appender.LOGFILE.Threshold=INFO log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout log4j.appender.LOGFILE.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
- 立ち上げて確認してみる。
C:\work2\felix>java -Dlog4j.configuration=file:log4j.properties -Dfelix.config.properties=file:config.properties -jar felix.jar Welcome to Felix ================ Auto-properties start: org.osgi.framework.BundleException: Fragment bundles can not be started. -> ps START LEVEL 1 ID State Level Name [ 0] [Active ] [ 0] System Bundle (2.0.1) [ 1] [Active ] [ 1] Apache Felix Bundle Repository (1.4.2) [ 2] [Active ] [ 1] Apache Felix Shell Service (1.4.1) [ 3] [Active ] [ 1] Apache Felix Shell TUI (1.4.1) [ 4] [Active ] [ 1] AOP Alliance API (1.0.0) [ 5] [Active ] [ 1] jcl104-over-slf4j (1.4.3) [ 6] [Active ] [ 1] SLF4J Jakarta Commons Logging Over SLF4J Binding (1.5.0) [ 7] [Active ] [ 1] log4j.osgi (1.2.15.SNAPSHOT) [ 8] [Active ] [ 1] Apache Felix (1.4.1) [ 9] [Active ] [ 1] SLF4J API (1.5.0) [ 10] [Resolved ] [ 1] SLF4J Log4J Binding (1.5.0) [ 11] [Active ] [ 1] Spring AOP (2.5.6.A) [ 12] [Active ] [ 1] Spring Beans (2.5.6.A) [ 13] [Active ] [ 1] Spring Context (2.5.6.A) [ 14] [Active ] [ 1] Spring Core (2.5.6.A) [ 15] [Active ] [ 1] spring-osgi-core (1.2.0) [ 16] [Active ] [ 1] spring-osgi-extender (1.2.0) [ 17] [Active ] [ 1] spring-osgi-io (1.2.0) ->
■ バンドル作り
前と同じように、Greeting Service と Greeting Service Client を連携させるが、ただし Clientはもっとシンプルに、固定文字列"Client"を Greeting Serviceに渡して結果を得るだけにする。つまり start コマンドでクライアントバンドルを実行すると、Felixのコンソールに固定文字列 "Hello Client"が表示されるのがゴール。
◆ Greeting Service
※以下、c:\work2\service\下の作業 ・以下のような2つのソースを書いて、適切なファイル名で適切なディレクトリに置く
package greeting.service; public interface GreetingService { public String greet(String name); }
package greeting.service.impl; import greeting.service.GreetingService; public class GreetingServiceImpl implements GreetingService { public void start() { System.out.println("Greeting Service registered"); } public String greet(String name) { return "Hello " + name; } }・コンパイルする。classes ディレクトリを作ってそこに入れる。
$ javac -d classes greeting/service/*.java greeting/service/impl/*.java・bean 定義ファイルを書いて、META-INF/spring 下に置く greetingservice.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean name="greetingService" class="greeting.service.impl.GreetingServiceImpl" init-method="start"/> </beans>greetingservice-osgi.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd"> <osgi:service id="greetingOSGiService" ref="greetingService" interface="greeting.service.GreetingService"> </osgi:service> </beans>・以下のようなmanifest.mf を書く
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Greeting Service Bundle-SymbolicName: greetingservice Bundle-Version: 1.0.0 Import-Package: org.springframework.beans.factory.xml, org.springframework.aop, org.springframework.aop.framework, org.aopalliance.aop, org.xml.sax, org.osgi.framework, org.springframework.osgi.service.importer.support, org.springframework.beans.propertyeditors, org.springframework.osgi.service.exporter.support, org.springframework.osgi.service.exporter Export-Package: greeting.service・jar にする
$ jar cvfm service.jar manifest.mf META-INF -C classes greeting・念のため jar tvf service.jar で、怪しいところがないか見ておく
◆ Greeting Service Client
※以下、c:\work2\client\下の作業 ・以下のようなソースを書いて、適切なファイル名で適切なディレクトリに置く
package greeting.client; import greeting.service.GreetingService; public class GreetingClient { private GreetingService greetingService; public void setGreetingService(GreetingService greetingService) { this.greetingService = greetingService; } public void removeService() { System.out.println("service removed"); this.greetingService = null; } public void start() { System.out.println(greetingService.greet("Client")); } }・サービス側と同様に、spring 定義ファイルと、manifest.mf を書く。 greetingclient.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean name="greetingClient" class="greeting.client.GreetingClient" init-method="start"> <property name="greetingService" ref="greetingService"/> </bean> </beans>greetingclient-osgi.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd"> <osgi:reference id="greetingService" interface="greeting.service.GreetingService"/> </beans>manifest.mf
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Greeting Service Client Bundle-SymbolicName: greetingclient Bundle-Version: 1.0.0 Import-Package: org.springframework.beans.factory.xml, org.springframework.aop, org.springframework.aop.framework, org.aopalliance.aop, org.xml.sax, org.osgi.framework, org.springframework.osgi.service.importer.support, org.springframework.beans.propertyeditors, org.springframework.osgi.service.importer, org.springframework.osgi.service.exporter.support, greeting.service・コンパイル
$ javac -cp ../service/service.jar -d classes greeting/client/GreetingClient.java・jar にする
$ jar cvfm client.jar manifest.mf META-INF -C classes greeting以上、service.jar とclient.jar が作成され、デプロイできる状態になった。
■ 動かす
◆ Greeting Service ・インストールは以下のような感じ
-> install file:../service/service.jar Bundle ID: 18・start 18 で以下の出力。ちゃんと bean 定義の init-method で指定した start() が呼ばれたのがわかる。
-> start 18 -> Greeting Service registered
◆ Greeting Service Client ・インストールは以下のような感じ
-> install file:../client/client.jar Bundle ID: 19・開始すると、以下のように Greeting Service と協働しているのが分かる。
-> start 19 -> Hello Client
■ まとめ
- 参考にした記事は→「OSGi と Spring:第 2 回」
- 正直、上の記事のアプリを思い通りに動かすまでちょっと苦労したけど、おかげで大分 Felix + Spring DMに慣れた。
- 最初は何かと面倒だけど、バンドルが増えてくると段々と効果が出てくるのだと思う。特に POJO でサービスを書く事による、テスト効率向上に期待できそう。
- 今回使ったSpring DM は 1.x で、Java 1.4ベースという事になる。Tiger ベースの2.x系があるらしい
- 今回やってみて、やはり Spring の XML がちょっと面倒くさい。Spring DM 2.x 系は未見だけど、できれば EoD の方向でアノテーション・ベースになってくれてたら嬉しい。
0 件のコメント:
コメントを投稿