2007年5月19日土曜日

grails でワークフロー

grails で jbpm が使えるかどうか, まずは試してみる. jbpm を選んだのは, 前にワークフロー・エンジンを使うときに一番まともそうで, これを使ったから.

grails でワークフローを扱おうと思ったら, とりあえず Java の既存のワークフロー・エンジンを取り込んでしまうのが簡単で (これが grails のいいところ), 例えば jbpm だとこんな感じになる.



まずは <project>/lib/ に jbpm の jbpm-jpdl.jar を放り込む.



次に, jbpm では残念ながら "def" というパッケージ名を多用していて, これは groovy では当然キーワードなので, 文法的に許してもらえない. 仕方がないので, (とりあえず最小限必要な) 次のようなラッパを作って,



package jp.co.metabolics.jbpm.grails;



public class ProcessDefinition extends org.jbpm.graph.def.ProcessDefinition {

public static org.jbpm.graph.def.ProcessDefinition parseXmlString(String xml) {

return org.jbpm.graph.def.ProcessDefinition.parseXmlString(xml);

}



}


これをjar にして, 同じく <project>/lib/ に放り込んでおく. これだけ.



jbpm のユーザ・ガイドにある最初の例題を groovy で書いてみよう.







MarkupBuilder のおかげでこんな感じに書ける.



import jp.co.metabolics.jbpm.grails.ProcessDefinition

import org.jbpm.graph.exe.ProcessInstance

import org.jbpm.graph.exe.Token



void testHelloWorldProcess() {

// ここでワークフローを定義している.

def writer = new StringWriter()

def b = new groovy.xml.MarkupBuilder(writer)

b.'process-definition' {

b.'start-state' { transition(to:'s') }

state(name:'s') { transition(to:'end') }

b.'end-state'(name:'end')

}

def processDefinition = ProcessDefinition.parseXmlString(writer.toString())

assert processDefinition

println processDefinition



// プロセス・インスタンスを作る

def processInstance = new ProcessInstance(processDefinition);

assert processInstance

println processInstance



// トークンを得る

def token = processInstance.getRootToken();

assert token

println token.getNode()



assertSame(processDefinition.getStartState(), token.getNode());



// 開始

token.signal();

assertSame(processDefinition.getNode("s"), token.getNode());

println token.getNode()



// 次のノードへ

token.signal();

assertSame(processDefinition.getNode("end"), token.getNode());

println token.getNode()

}


jbpm はワークフロー・エンジンとしても, 状態機械としても, BPEL エンジンとしても使える. ワークフローそのものは, eclipse でグラフィカルに描くこともできる. 基本的な使い方は (def パッケージのクラスを使う場合にラッパを挟む以外は) Java の場合と一緒. Java と一緒というのは楽と言えば楽だけど, groovy / grails の強力さを生かし切れていないとも言えるので, できれば, plug-in を作って, builder を提供したり, 必要なメソッドは inject したいところだ.



その辺はまたそのうち.