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 したいところだ.
その辺はまたそのうち.