読者です 読者をやめる 読者になる 読者になる

Project Fuji を使った ESB - jruby, file

OpenESB v3 のカーネルコンポーネント Fuji に自作の処理フローを登録してみる事にする。
Fuji は JBI・OSGi をベースとした軽量マイクロカーネルコンテナ(ServiceMix Kernel と同じようなもの)で、IFL (Integration Flow Language) と呼ばれる DSL で処理を記述できたり、Web エディタが使えたりと ESB を容易にするための工夫がされている。

今回、使用した環境は以下の通り。

  • Maven 2.0.9
  • Fuji Milestone 3

Fuji の準備

まずは、Fuji の実行環境を準備する。
OpenESB ダウンロードサイトから fujifelix-1.0-M3.jar をダウンロードして、適当なディレクトリに解凍。
解凍先のディレクトリをカレントディレクトリにして、以下のコマンドで Fuji を実行する。今のところ Fuji は Apache Felix をベースとしているため、操作は Felix そのもの。

Fuji の起動
>java -jar bin\felix.jar
Fuji editor

Fuji が起動した後、以下の URL に Web ブラウザ(FireFox 3 でのみ動作確認済)でアクセスすると GUI を使って簡単に処理フローを作成し、デプロイするための Web エディタが立ち上がる。

このエディタは、マッシュアップ感覚で手軽に ESB の処理を定義できるので、けっこう有望なツールだと思う。
実は、以降で作成するような処理フローも、Fuji editor を使った方が簡単に作成できる。

fujiアプリケーション用 Maven プロジェクトを作成

さて、ここから本題に入っていく事にする。

まず、以下の fuji アプリケーション用の archetype を使って、Maven のプロジェクトを適当なディレクトリに生成する。

下記コマンドを実行するとカレントディレクトリに Maven のプロジェクト(sample1)が生成される。

>mvn archetype:generate -DgroupId=fits.sample -DartifactId=sample1 -DarchetypeGroupId=open-esb.fuji -DarchetypeArtifactId=app-archetype -DarchetypeVersion=1.0-M3 -DarchetypeRepository=http://download.java.net/maven/esb

IFL ファイルを編集

src/main/ifl/app.ifl に生成された IFL ファイルに処理フローを記述する。
IFL では、「<サービスタイプ> <論理サービス名>」で使用するサービスを定義し、route 内で from/to/broadcast を使った処理フローを定義していく。

以下では、ファイルを入力とし JRuby で処理した後にファイルに出力するフローを定義している。

src/main/ifl/app.ifl ファイル(処理内容: File -> JRuby -> File)
#使用するサービスの定義(<サービスタイプ> <論理サービス名>)
file "infile"
file "outfile"
jruby "filterruby"

#処理フローの定義
route do
    #処理の定義
    #フォーマット: from|to|broadcast "<論理サービス名>.<操作>"
    from "infile"
    to "filterruby"
    to "outfile"
end

なお、IFL では EIP(Enterprise Integration Patterns)もサポートされている模様。
IFL の定義内容は Apache Camel に近い。

ファイルの自動生成

IFL ファイルの編集が完了したら、以下のコマンドを実行して IFL で定義したサービスを使用するために必要なファイルを自動生成する。(JRuby や File サービスを使用するための設定ファイルやスクリプトファイルが自動的に生成される)

>mvn fuji:generate-artifacts

処理の実装

次に、fuji:generate-artifacts で自動生成されたファイルを編集して処理の記述や設定の変更を行っていく。
なお、以下のようにサービスによって編集対象ファイルが異なる点に注意。

  • file サービス
    • src/main/config/file/[論理サービス名]/service.properties ファイル
  • jruby サービス
    • src/main/jruby/[論理サービス名]/service.rb
src/main/config/file/infile/service.properties ファイル

ファイル入力の設定を変更

file.use=literal
file.fileName=file_in.xml
file.pollingInterval=1000
file.fileDirectory=e:/tmp/input
file.fileNameIsPattern=false
src/main/config/file/outfile/service.properties ファイル

ファイル出力の設定を変更

file.use=literal
file.fileName=file_out.xml
file.pollingInterval=1000
file.fileDirectory=e:/tmp/output
file.fileNameIsPattern=false
src/main/jruby/filterruby/service.rb ファイル

JRuby でフィルター処理を実装

require 'java'
require 'XPath'
require 'ESB'
include_class "javax.xml.namespace.QName"

@@service = QName.new "http://fuji.dev.java.net/application/[app]", "[service]"

def process(inMsg)
  doc = inMsg.getPayload
  # your code goes here

  node = XPath.findNode(doc, "//data[@id=1]")

  if node
    #入力の XML から id 属性が 1 の data 要素を削除
    node.getParentNode().removeChild(node)
  end

  # return message  
  inMsg
end

ビルド

以下のコマンドを実行してビルドを行う。

>mvn fuji:dist

ビルドに成功すると target/sample1-1.0-SNAPSHOT.jar が生成される。

デプロイと動作確認

"mvn fuji:run" コマンドでそのまま実行できそうなのだが、正常に動作しているかどうかわからなかったので、今回は Fuji Milestone 3 にインストールして動作確認した。

Fuji の起動後、sample1-1.0-SNAPSHOT.jar をインストールし実行する。
なお、sample2-1.0-SNAPSHOT.jar を Fuji のホームディレクトリにコピーした上で、start コマンド(インストール後に開始するためのコマンド)を実行した。

>java -jar bin\felix.jar
・・・
->start file:sample1-1.0-SNAPSHOT.jar

e:/tmp/input ディレクトリに file_in.xml ファイルを配置すると

e:/tmp/input/file_in.xml ファイル
<root>
  <data id="0" />
  <data id="1" />
  <data id="2" />
</root>

以下のような e:/tmp/output/file_out.xml ファイルが出力され、処理が正常に動作している事を確認できる。

e:/tmp/output/file_out.xml ファイル
<root>
  <data id="0" />
  
  <data id="2" />
</root>

補足

Fuji の Felix にインストールした後、JRuby のソース等は JBI OSGi Framework のキャッシュに展開される。

  • cache/bundle26/data/service-assemblies/sample1
    • sun-file-binding_sample1-sun-file-binding
    • sun-jruby-engine_sample1-sun-jruby-engine

処理の実行時にはこの展開されたファイルが使用されているようなので、JRuby の処理を一時的に編集して動作確認するなら、展開されたファイル(sun-jruby-engine_sample1-sun-jruby-engine/filterruby/service.rb)を直接編集した方が手っ取り早い。