Jbpm4
經常使用操做
1、
ProcessEngine
:流程引擎。是
JBPM
上層類,至關於
Hibernate
的
SessionFactory
級別。
//
得到方式:
ProcessEngine
processEngine
= Configuration.getProcessEngine();
/*Configuration
類會讀取
classpath
下的
jbpm.cfg.xml
文件進行流程引擎的加載。
ProcessEngine
是單例模式,即整個系統只會有一個
processEngine
實例。
*/
2、流程定義
1.
部署流程定義
ProcessEngine
processEngine = Configuration.getProcessEngine();
RepositoryService
repositoryService
=
processEngine
.getRepositoryService();
例:佈署文件中的流程
//
佈署當前目錄下
pd.jpdl.xml
文件
String
deploymentId = repositoryService.createDeployment()
.addResourceFromClasspath(
"process.jpdl.xml"
).deploy();
/* deploymentId
是發佈的流程返回的
ID
號
*/
2.
刪除流程定義
類
ProcessDefinition
包含以下屬性:
ID
:流程定義
ID
號
DeploymentId
:流程定義的佈署
ID
號
Key
:關鍵字
name
:流程名
version
:版本號
數據以下
ID Key
名稱
版本
hello-1 hello hello 1
//
獲取類
ProcessDefinition
的屬性
ID
String
deploymentId
= request.getParameter(
"deploymentId"
);
//
根據流程
ID
獲取流程定義實例
ProcessDefinition
pd
=
repositoryService
.createProcessDefinitionQuery()
.processDefinitionId(
deploymentId
).uniqueResult();
//
根據流程定義的佈署
ID
號,刪除該流程定義(根據流程定義的
ID
號級聯刪除)
//
注意
:jbpm4
是不容許直接根據流程定義的
ID
來直接刪除流程定義的,由於還要刪除其它配置數據
repositoryService.deleteDeploymentCascade(pd.getDeploymentId());
3.
獲取所有流程定義
根據流程名獲取全部流程定義
List<ProcessDefinition> processDefinitions = repositoryService
.createProcessDefinitionQuery().orderAsc( ProcessDefinitionQuery.PROPERTY_NAME).list();
//
還能夠根據如下順序進行排序
(org.jbpm.api.ProcessDefinitionQuery)
public
static
final
java.lang.String
PROPERTY_DEPLOYMENT_TIMESTAMP
"deployment.timestamp"
public
static
final
java.lang.String
PROPERTY_ID
"idProperty.stringValue"
public
static
final
java.lang.String
PROPERTY_KEY
"keyProperty.stringValue"
public
static
final
java.lang.String
PROPERTY_NAME
"idProperty.objectName"
public
static
final
java.lang.String PROPERTY_VERSION
"versionProperty.longValue"
2、流程實例
1.
啓動一個流程實例
1.1
根據
key
啓動流程實例
//
用戶必須爲新啓動的流程實例分配一個
key
,
這個
key
是用戶執行的時候定義的且惟一。一般在業務流程領域找到這種
key
。
好比,一個訂單
id
或者一個保險單號。
ProcessInstance
processInstance = executionService.startProcessInstanceByKey(
"ICL"
,
"CL92837"
);
//key
能夠用來建立流程實例的
id
,
格式爲
{process-key}.{execution-id}
。
因此上面的代碼會建立一個
id
爲
ICL.CL92837
的流向
(
execution
)。
1.2
根據數據庫主鍵啓動流程實例
//
若是沒有提供用戶定義的
key
,數據庫就會把主鍵做爲
key
。
這樣能夠使用以下方式得到
id
:
ProcessInstance processInstance = executionService.startProcessInstanceByKey(
"ICL"
);
String
pid
=
processInstance
.getId();
//
最好使用一個用戶定義的
key
。提供給一個用戶定義的
key
,
你能夠組合流向的
id
,而不是執行一個基於流程變量的搜索
-
那種方式太消耗資源了。
1.3
根據變量啓動流程實例
//
爲一個新的流程實例啓動時就提供一組對象參數。
將這些參數放在
variables
變量裏,
而後能夠在流程實例建立和啓動時使用。
Map
<String,Object> variables =
new
HashMap<String,Object>();
variables.put(
"customer"
,
"John Doe"
);
variables.put(
"type"
,
"Accident"
);
variables.put(
"amount"
,
new
Float(763.74));
ProcessInstance processInstance = executionService.startProcessInstanceByKey(
"ICL"
, variables);
//
//JBPM4.4
支持變量歷史
//
變量能夠被標記爲做爲歷史記錄保存。這意味着,當流程實例結束,
它的運行階段的信息被刪除,歷史細節依然會被保存。
//
經過公共
API ExecutionService
啓用變量的歷史功能
void
createVariable(String executionId, String name, Object value,
boolean
historyEnabled);
void
createVariables(String executionId, Map<String, ?> variables,
boolean
historyEnabled);
//
經過變量定義
<variable name=
"declaredVar"
type=
"string"
init-expr=
"testing declared variable"
history=
"true"
/>
2.
根據流程定義,查看流程實例
//
根據類
ProcessDefinition
的屬性
ID
,查看該流程的全部實例
String processDefinitionId = request.getParameter(
"processDefinitionId"
);
return
executionService.createProcessInstanceQuery().processDefinitionId(processDefinitionId).list();
3.
執行實例
//
根據類
ProcessInstance
的屬性
ID(
流程實例
ID)
,執行流程實例
String processInstanceId = request.getParameter(
"processInstanceId"
);
executionService.signalExecutionById(processInstanceId);
四
.
任務
//
假設流程定義
4-1
以下:
<process name=
"TaskAssignee"
>
<start>
<transition to=
"review"
/>
</start>
<task name=
"review"
assignee=
"#{order.owner}"
>
<transition to=
"work"
/>
</task>
<task name=
"review"
assignee=
"de style="
color: rgb(255, 102, 0);
">johndoede>"
>
<transition to=
"wait"
/>
</task>
<state name=
"wait"
/>
</process>
assignee=
"johndoe"
//
表示任務會被分配給用戶
ID
爲
"johndoe"
的人。
assignee=
"#{order.owner}"
//
任務被分配給
#{order.owner}
。表示經過
Order
對的
getOwner()
方法會用來得到用戶
id
,該用戶負責完成這個任務。
public
class
Order
implements
Serializable {
String owner;
public
Order(String owner) {
this
.owner = owner;
}
public
String getOwner() {
return
owner;
}
public
void
setOwner(String owner) {
this
.owner = owner;
}
}
1.
獲取任務列表
1.1
根據用戶
ID
獲取任務列表
List<Task> taskList = taskService.findPersonalTasks(
"johndoe"
);
1.2
根據任務候選人或候選組獲取任務列表
任務可能被分配給一組用戶。
其中的一個用戶應該接受這個任務並完成它。
candidate-groups
:一個使用逗號分隔的組
id
列表。
全部組內的用戶將會成爲這個任務的候選人。
candidate-users
:一個使用逗號分隔的用戶
id
列表。
全部的用戶將會成爲這個任務的候選人。
例如:
<task name=
"review"
candidate-groups=
"sales-dept"
>
<transition to=
"wait"
/>
</task>
假設:
sales-dept
有兩個成員:
johndoe
和
joesmoe
//
這個任務被建立時,不顯示在任何人的我的任務列表中。
下面的任務列表會是空的。
taskService.getAssignedTasks(
"johndoe"
);
taskService.getAssignedTasks(
"joesmoe"
);
分組任務列表中,用戶接口必須只接受對這些任務的
「
接受
」
操做。
taskService.takeTask(task.getDbid(),
"johndoe"
);
當一個用戶接受了一個任務,這個任務的分配人就會變成當前用戶。任務會從全部候選人的分組任務列表中消失,它會出如今用戶的已分配列表中。
1.3
在一個列表中顯示該某人的全部任務
包括他的我的任務,候選任務,這時直接用
jbpm4
提供的
api
完成不了該功能要求。因而能夠使用如下方式進行擴展:
/**
*
取得用戶的對應的任務列表
*
@param
userId
*
@return
*/
public
List<TaskImpl> getTasksByUserId(String userId){
AppUser user=(AppUser)getHibernateTemplate().load(AppUser.
class
,
new
Long(userId));
Iterator<AppRole> rolesIt=user.getRoles().iterator();
StringBuffer groupIds=
new
StringBuffer();
int
i=0;
while
(rolesIt.hasNext()){
if
(i>0)groupIds.append(
","
);
groupIds.append(
"'"
+rolesIt.next().getRoleId().toString()+
"'"
);
}
/**
* select * from `jbpm4_task` task
left join jbpm4_participation pt on task.`DBID_`=pt.`TASK_`
where task.`ASSIGNEE_`='1' or ( pt.`TYPE_` = 'candidate' and (pt.`USERID_`='1')
or pt.`GROUPID_`in ('1'))
*/
StringBuffer hqlSb=
new
StringBuffer();
hqlSb.append(
"select task from org.jbpm.pvm.internal.task.TaskImpl task left join task.participations pt where task.assignee=?"
);
hqlSb.append(
" or (pt.type = 'candidate' and ((pt.userId=?)"
);
if
(user.getRoles().size()>0){
hqlSb.append(
" or (pt.groupId in ("
+groupIds.toString()+
"))"
);
}
hqlSb.append(
"))"
);
hqlSb.append(
" order by task.priority desc"
);
return
findByHql(hqlSb.toString(),
new
Object[]{userId,userId});
}
2
分配任務
若是在流程定義文件中將任務指定到了我的,則
jbpm
自動分配給我的。不然須要進行指定
2.1
給用戶組的用戶分配任務
流程定義文件
:
<task name=
"review"
candidate-groups=
"sales-dept"
>
<transition to=
"wait"
/>
</task>
假設:
sales-dept
有兩個成員:
johndoe
和
joesmoe
分組任務列表中,用戶接口必須只接受對這些任務的
「
接受
」
操做。
taskService.takeTask(task.getDbid(),
"johndoe"
);
當一個用戶接受了一個任務,這個任務的分配人就會變成當前用戶。任務會從全部候選人的分組任務列表中消失,它會出如今用戶的已分配列表中。
2.2
任務分配處理器分配任務
一個
AssignmentHandler
能夠經過編程方式來計算
一個任務的分配人和候選人
。
public
interface
AssignmentHandler
extends
Serializable {
void
assign(Assignable assignable, OpenExecution execution)
throws
Exception;
}
Assignable
是任務和泳道的通用接口。
因此任務分配處理器能夠使用在任務,
也能夠用在泳道中。
包含任務分配處理器的流程定義
4-2
以下:
<process name=
"TaskAssignmentHandler"
xmlns=
"http://jbpm.org/4.2/jpdl"
>
<start g=
"20,20,48,48"
>
<transition to=
"review"
/>
</start>
<task name=
"review"
g=
"96,16,127,52"
>
<assignment-handler
class
=
"org.jbpm.examples.task.assignmenthandler.AssignTask"
>
<field name=
"assignee"
>
<string value=
"johndoe"
/>
</field>
</assignment-handler>
<transition to=
"wait"
/>
</task>
<state name=
"wait"
g=
"255,16,88,52"
/>
</process>
類
AssignTask
代碼以下
:
public
class
AssignTask
implements
AssignmentHandler {
String
assignee
;
public
void
assign(Assignable assignable, OpenExecution execution) {
assignable.setAssignee(
assignee
);
}
}
請注意,默認
AssignmentHandler
實現能夠使用使用流程變量,任何其餘
Java
API
能夠訪問資源
,像你的應用數據庫來計算分配人和候選人用戶和組。
啓動一個
TaskAssignmentHandler
的新流程實例
,
會當即讓新流程實例運行到任務節點。
一個新
review
任務被建立,在這個時候
AssignTask
的分配處理器被調用
。這將設置
johndoe
爲分配人。
因此
John
Doe
將在他本身的任務列表中找到這個任務
。
2.3
給泳道分配任務
任務泳道以下面的流程文件
4
-3
:
<process name=
"TaskSwimlane"
xmlns=
"http://jbpm.org/4.2/jpdl"
>
<swimlane name=
"sales representative"
candidate-groups=
"sales-dept"
/>
<start>
<transition to=
"enter order data"
/>
</start>
<task name=
"enter order data"
swimlane=
"sales representative"
>
<transition to=
"calculate quote"
/>
</task>
<task name=
"calculate quote"
swimlane=
"sales representative"
>
</task>
</process>
在這個例子中,咱們在身份組件中
建立了下面的信息
:
identityService.createGroup(
"sales-dept"
);
identityService.createUser(
"johndoe"
,
"johndoe"
,
"John"
,
"Doe"
);
identityService.createMembership(
"johndoe"
,
"sales-dept"
);
在啓動一個新流程實例後,用戶
johndoe
將成爲
enter
order
data
的一個候選人
。仍是像上一個流程候選人例子同樣,
John
Doe
能夠像這樣接收任務
:
taskService.takeTask(task.getDbid(),
"johndoe"
);
接收這個任務將讓
johndoe
成爲任務的負責人。
直到任務與泳道
sales
representative
關聯
,
分配人
johndoe
也會關聯到泳道中做爲負責人。接下來,
John
Doe
能夠像下面這樣完成任務
:
taskService.completeTask(taskDbid);
完成任務會將流程執行到下一個任務,下一個任務是calculate quote。這個任務也關聯着泳道。所以,任務會分配給johndoe。java