jBPM はワークフローやタスク管理に対して優れた機能を提供します。 jBPM の Seam との統合例として、 簡単な「todo 一覧」アプリケーションを見てみます。 タスク一覧の管理は jBPM の中核となる機能のため、 このサンプルには Java コードがほとんどありません。
このサンプルの中心は jBPM のプロセス定義です。 2 種類の JSP と 2種類の基本的な JavaBean も使用します。 (セッション Bean はデータベースにアクセスせず、トランザクション動作も持たないためここでは必要ありません。) プロセス定義から始めましょう。
例1.16 todo.jpdl.xml
<process-definition name="todo">
<start-state name="start">
<transition to="todo"/>
</start-state>
<task-node name="todo">
<task name="todo" description="#{todoList.description}">
<assignment actor-id="#{actor.id}"/>
</task>
<transition to="done"/>
</task-node>
<end-state name="done"/>
</process-definition>
<process-definition name="todo">
<start-state name="start">
<transition to="todo"/>
</start-state>
<task-node name="todo">
<task name="todo" description="#{todoList.description}">
<assignment actor-id="#{actor.id}"/>
</task>
<transition to="done"/>
</task-node>
<end-state name="done"/>
</process-definition>
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow

|
<start-state> ノードはプロセスの論理的な開始を表します。プロセスが開始すると、直ちに todo ノードに遷移します。
|

|
<task-node> ノードは、待ち状態 を表します。 ビジネスプロセスの実行が一時停止され、1 つまたは複数のタスクが行われるのを待機します。
|

|
<task> エレメントはユーザーにより実行されるタスクを定義します。このノードでは 1 つのタスクしか定義されていないため、それが完了すると実行が再開し、終了状態に遷移します。このタスクは todoList (JavaBeans の 1 つ) という Seam コンポーネントからその詳細を取得します。
|

|
タスクは生成されるとユーザーまたはユーザーグループに割り当てられる必要があります。 このサンプルでは、タスクは現在のユーザーに割り当てられ、actor という名前の Seam 組み込みコンポーネントから取得されます (いずれの Seam コンポーネントを使ってもタスク割り当てを実行できます)。
|

|
<end-state> ノードは、ビジネスプロセスの論理的な終了を定義します。 実行がこのノードに到達したとき、 プロセスインスタンスは破棄されます。
|
JBossIDE で提供されるプロセス定義エディタを使用してプロセス定義を見た場合、 以下のようになります。
このドキュメントはノードのグラフとして ビジネスプロセス を定義します。 これは可能な限りシンプルにしたビジネスプロセスです。 実行すべき タスク がひとつあり、 そのタスクが完了するとビジネスプロセスが終了します。
最初の JavaBean はログイン画面 login.jsp を処理します。 単に actor コンポーネントを使用して jBPM actor ID を初期化します。 実際のアプリケーションではユーザー認証も必要となります。
例1.17 Login.java
@Name("login")
public class Login {
@In
private Actor actor;
private String user;
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String login() {
actor.setId(user);
return "/todo.jsp";
}
}
@Name("login")
public class Login {
@In
private Actor actor;
private String user;
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String login() {
actor.setId(user);
return "/todo.jsp";
}
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
ここでは、組み込み Actor コンポーネントをインジェクトするために @In を使用しているのがわかります。
次の JSP 自体は重要ではありません。
例1.18 login.jsp
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<html>
<head>
<title>Login</title>
</head>
<body>
<h1>Login</h1>
<f:view>
<h:form>
<div>
<h:inputText value="#{login.user}"/>
<h:commandButton value="Login" action="#{login.login}"/>
</div>
</h:form>
</f:view>
</body>
</html>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<html>
<head>
<title>Login</title>
</head>
<body>
<h1>Login</h1>
<f:view>
<h:form>
<div>
<h:inputText value="#{login.user}"/>
<h:commandButton value="Login" action="#{login.login}"/>
</div>
</h:form>
</f:view>
</body>
</html>
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
2 つ目の JavaBean は、ビジネスプロセスインスタンスの開始とタスクの終了を担当します。
例1.19 TodoList.java
@Name("todoList")
public class TodoList
{
private String description;
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
@CreateProcess(definition="todo")
public void createTodo() {}
@StartTask @EndTask
public void done() {}
}
@Name("todoList")
public class TodoList
{
private String description;
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
@CreateProcess(definition="todo")
public void createTodo() {}
@StartTask @EndTask
public void done() {}
}
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow

|
description プロパティは JSP ページからユーザ入力を受け取りプロセス定義に公開して、タスクの description が設定されるようにします。
|

|
Seam @CreateProcess アノテーションは、名前付きプロセス定義のために jBPM プロセスインスタンスを生成します。
|

|
Seam @StartTask アノテーションはタスク上で作業を開始します。@EndTask はタスクを終了し、ビジネスプロセスの再開を可能にします。
|
より現実的なサンプルでは、 @StartTask と @EndTask は同じメソッドには登場しません。 タスクを完了するためにはアプリケーションを使用して何らかの作業が行われる必要があるためです。
最後に、このアプリケーションの中核となるのは todo.jsp です。
例1.20 todo.jsp
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://jboss.com/products/seam/taglib" prefix="s" %>
<html>
<head>
<title>Todo List</title>
</head>
<body>
<h1>Todo List</h1>
<f:view>
<h:form id="list">
<div>
<h:outputText value="There are no todo items."
rendered="#{empty taskInstanceList}"/>
<h:dataTable value="#{taskInstanceList}" var="task"
rendered="#{not empty taskInstanceList}">
<h:column>
<f:facet name="header">
<h:outputText value="Description"/>
</f:facet>
<h:inputText value="#{task.description}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Created"/>
</f:facet>
<h:outputText value=
"#{task.taskMgmtInstance.processInstance.start}">
<f:convertDateTime type="date"/>
</h:outputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Priority"/>
</f:facet>
<h:inputText value="#{task.priority}" style="width: 30"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Due Date"/>
</f:facet>
<h:inputText value="#{task.dueDate}" style="width: 100">
<f:convertDateTime type="date" dateStyle="short"/>
</h:inputText>
</h:column>
<h:column>
<s:button value="Done" action="#{todoList.done}"
taskInstance="#{task}"/>
</h:column>
</h:dataTable>
</div>
<div>
<h:messages/>
</div>
<div>
<h:commandButton value="Update Items" action="update"/>
</div>
</h:form>
<h:form id="new">
<div>
<h:inputText value="#{todoList.description}"/>
<h:commandButton value="Create New Item"
action="#{todoList.createTodo}"/>
</div>
</h:form>
</f:view>
</body>
</html>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://jboss.com/products/seam/taglib" prefix="s" %>
<html>
<head>
<title>Todo List</title>
</head>
<body>
<h1>Todo List</h1>
<f:view>
<h:form id="list">
<div>
<h:outputText value="There are no todo items."
rendered="#{empty taskInstanceList}"/>
<h:dataTable value="#{taskInstanceList}" var="task"
rendered="#{not empty taskInstanceList}">
<h:column>
<f:facet name="header">
<h:outputText value="Description"/>
</f:facet>
<h:inputText value="#{task.description}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Created"/>
</f:facet>
<h:outputText value=
"#{task.taskMgmtInstance.processInstance.start}">
<f:convertDateTime type="date"/>
</h:outputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Priority"/>
</f:facet>
<h:inputText value="#{task.priority}" style="width: 30"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Due Date"/>
</f:facet>
<h:inputText value="#{task.dueDate}" style="width: 100">
<f:convertDateTime type="date" dateStyle="short"/>
</h:inputText>
</h:column>
<h:column>
<s:button value="Done" action="#{todoList.done}"
taskInstance="#{task}"/>
</h:column>
</h:dataTable>
</div>
<div>
<h:messages/>
</div>
<div>
<h:commandButton value="Update Items" action="update"/>
</div>
</h:form>
<h:form id="new">
<div>
<h:inputText value="#{todoList.description}"/>
<h:commandButton value="Create New Item"
action="#{todoList.createTodo}"/>
</div>
</h:form>
</f:view>
</body>
</html>
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
簡単にするためにセクションごとに見ていきます。
ページはタスク一覧を表示しています。 taskInstanceList と呼ばれる Seam 組み込みコンポーネントから取得します。 この一覧は JSF フォームの中で定義されています。
例1.21 todo.jsp (taskInstanceList)
<h:form id="list">
<div>
<h:outputText value="There are no todo items."
rendered="#{empty taskInstanceList}"/>
<h:dataTable value="#{taskInstanceList}" var="task"
rendered="#{not empty taskInstanceList}">
...
</h:dataTable>
</div>
</h:form>
<h:form id="list">
<div>
<h:outputText value="There are no todo items."
rendered="#{empty taskInstanceList}"/>
<h:dataTable value="#{taskInstanceList}" var="task"
rendered="#{not empty taskInstanceList}">
...
</h:dataTable>
</div>
</h:form>
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
一覧の各エレメントは jBPM クラス TaskInstance のインスタンスです。 以下のコードは一覧中の各タスクの特定のプロパティを表示しています。 記述内容 (Description)、 優先順 (Priority)、 納期の値 (Due Date) には入力コントロールを使用し、ユーザーはこれらの値を更新することができます。
例1.22 TaskInstance List のプロパティ
<h:column>
<f:facet name="header">
<h:outputText value="Description"/>
</f:facet>
<h:inputText value="#{task.description}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Created"/>
</f:facet>
<h:outputText value="#{task.taskMgmtInstance.processInstance.start}">
<f:convertDateTime type="date"/>
</h:outputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Priority"/>
</f:facet>
<h:inputText value="#{task.priority}" style="width: 30"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Due Date"/>
</f:facet>
<h:inputText value="#{task.dueDate}" style="width: 100">
<f:convertDateTime type="date" dateStyle="short"/>
</h:inputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Description"/>
</f:facet>
<h:inputText value="#{task.description}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Created"/>
</f:facet>
<h:outputText value="#{task.taskMgmtInstance.processInstance.start}">
<f:convertDateTime type="date"/>
</h:outputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Priority"/>
</f:facet>
<h:inputText value="#{task.priority}" style="width: 30"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Due Date"/>
</f:facet>
<h:inputText value="#{task.dueDate}" style="width: 100">
<f:convertDateTime type="date" dateStyle="short"/>
</h:inputText>
</h:column>
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
Seam では文字列を日付に変換するデフォルトの JSF 日付コンバータを提供しているので、 #{task.dueDate} にバインドされるフィールドにはコンバータは必要ありません。
このボタンは @StartTask @EndTask アノテーション付きのアクションメソッドを呼び出すことによりタスクを終了します。 タスク ID を要求パラメータとして Seam に渡します。
<h:column>
<s:button value="Done" action="#{todoList.done}"
taskInstance="#{task}"/>
</h:column>
<h:column>
<s:button value="Done" action="#{todoList.done}"
taskInstance="#{task}"/>
</h:column>
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
seam-ui.jar パッケージから Seam <s:button> JSF コントロールを使用していることに留意してください。 このボタンがタスクのプロパティを更新します。 フォームがサブミットされると、 Seam と jBPM はタスクの永続に対して変更を加えます。 アクションリスナーメソッドには必要ありません。
<h:commandButton value="Update Items" action="update"/>
<h:commandButton value="Update Items" action="update"/>
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow
ページの 2 つ目のフォームでは @CreateProcess アノテーション付きアクションメソッドを使って新しい項目を作成します。
<h:form id="new">
<div>
<h:inputText value="#{todoList.description}"/>
<h:commandButton value="Create New Item"
action="#{todoList.createTodo}"/>
</div>
</h:form>
<h:form id="new">
<div>
<h:inputText value="#{todoList.description}"/>
<h:commandButton value="Create New Item"
action="#{todoList.createTodo}"/>
</div>
</h:form>
Copy to Clipboard
Copied!
Toggle word wrap
Toggle overflow