- Eclipse 모델링 환경 구축
- jBPM Command Line 실행 환경 구축
- java
- script
- hql
- event
- timer
- group
- TaskService
- Task
- HistoryService
- ManagementService
- Migration
- jBPM 엔진 및 도구
BPM 솔루션인 JBoss jBPM을 정리 한다.
홈페이지 : http://sourceforge.net/projects/jbpm/, http://www.jboss.org/jbpm/
라이선스 : GNU LGPL
플랫폼 : Java
Eclipse 모델링 환경 구축
JBoss jBPM에 jpdl을 모델링하기 위한 Eclipse 모델링 환경을 구축해 보자.
다운로드 사이트에서 jbpm-4.3.zip 을 다운로드 하여 c:/zzdir/ 폴더 아래에 압축을 풀어 둔다.
Eclipse에 GPD plugin을 설치 한다.
Eclipse에서 "Help -> Install New Software..." 메뉴를 선택 한다.
"Add..." 버튼을 누른 후 "Archive..." 버튼을 눌러 c:/zzdir/jbpm-4.3/install/src/gpd/jbpm-gpd-site.zip 파일을 선택 한다.
"OK" 버튼을 누르고, 목록에 표시된 것을 모두 선택한 후 설치 한다.
Eclipse에 jBPM 실행환경을 설정 한다.
"Window -> Preferences -> JBoss jBPM -> jBPM 4 --> Runtime Locations" 메뉴를 선택 한다.
"Add..." 버튼을 눌러 다음과 같이 등록 한다.
Name : "jbpm-4.0"
Location : "c:/zzdir/jbpm-4.3"
Eclipse에 jBPM 사용자 라이브러리를 등록 한다.
"Window -> Preferences -> Java -> Build Path -> User Libraries" 메뉴를 선택 한다.
"New..." 버튼을 선택한 후 User library name에 "jBPM Libraries"을 입력한 후 "OK" 버튼을 누른다.
"jBPM Libraries"을 선택한 후 "Add JARs..." 버튼을 눌러 jBPM에 c:/zzdir/jbpm-4.3/lib/ 폴더에 있는 모든 jar 파일을 등록 한다.
"jBPM Libraries"을 선택한 후 "Add JARs..." 버튼을 눌러 jBPM에 c:/zzdir/jbpm-4.3/jbpm.jar 파일을 등록 한다.
Eclipse에 jPDL 4 schema를 등록 한다.
"Window -> Preferences -> XML -> XML Catalog" 메뉴를 선택 한다.
"Add..." 버튼을 누른 후 "File System..." 버튼을 눌러 c:/zzdir/jbpm-4.3/src/jpdl-4.0.xsd 파일을 선택하여 등록 한다.
이때 Key Type은 "Namespace Name"이 Key는 "http://jbpm.org/4.3/jpdl"이 자동으로 설정 된다.
jBPM Command Line 실행 환경 구축
JBoss jBPM을 실행하기 위한 환경을 구축해 보자.
다운로드 사이트에서 jbpm-4.3.zip 을 다운로드 하여 c:/zzdir/ 폴더 아래에 압축을 풀어 둔다.
Eclipse에서 jBPM 이라는 Java Project를 생성 한다. 앞으로 jBPM 프로젝트의 홈 디렉토리를 $JBPM_HOME 이라 한다.
[Eclipse 모델링 환경 구축](JBPM.md#Eclipse 모델링 환경 구축.md)에서 생성한 "jBPM Libraries"를 Java Build Path에 아래와 같이 등록 한다.
"jBPM"을 선택한 후 오른쪽 마우스를 눌러 "Properties" 메뉴을 선택 한다.
"Java Build Path -> Libraries -> Add Library..."를 선택 한다.
"User Library"를 선택한 후 "jBPM Libraries"를 선택하여 등록 한다.
$JBPM_HOME/src/jbpm.cfg.xml 파일을 생성 한다.
$JBPM_HOME/src/jbpm.hibernate.cfg.xml 파일을 생성 한다.
Database에 대한 접속 정보를 관리 한다. 여기서는 HSQLDB의 메모리 DB를 사용 한다.
org.hibernate.dialect.HSQLDialect
org.hsqldb.jdbcDriver
jdbc:hsqldb:mem:.
sa
create-drop
true
자 여기까지 진행이 되었으면 JBoss jBPM을 실행할 환경의 구성은 완료 되었다. JBoss jBPM에서도 HelloWrold를 만들어 정상적으로 동작하는지 확인해 보자.
$JBPM_HOME/src/printHelloWorld.jpdl.xml 파일을 생성 한다.
JBoss jBPM에서 실행할 프로세스 정의 파일을 생성 한다.
$JBPM_HOME/src/com/jopenbusiness/jbpm/cli/Printer.java 파일을 생성 한다.
```
package com.jopenbusiness.jbpm.cli;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.jbpm.api.Configuration;
import org.jbpm.api.ExecutionService;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.RepositoryService;
//--- http://www.javaplex.com/blog/getting-started-with-jbpm/
public class Printer {
//--- http://docs.jboss.com/jbpm/v4/userguide/html_single/#services
public static void main(String args) {
ProcessEngine processEngine = null;
RepositoryService repositoryService = null;
ExecutionService executionService = null;
processEngine = new Configuration().setResource("jbpm.cfg.xml").buildProcessEngine();
repositoryService = processEngine.getRepositoryService();
executionService = processEngine.getExecutionService();
repositoryService.createDeployment().addResourceFromClasspath("printHelloWorld.jpdl.xml").deploy();
executionService.startProcessInstanceByKey("helloWorld");
}
//--- JBoss jBPM의 프로세스 정의 파일에 정의되어 호출되는 함수
public void printHelloWorld() {
File tmpFile = null;
BufferedWriter out = null;
SimpleDateFormat formatDate = null;
tmpFile = new File("c:/jbpm.out");
try {
formatDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
out = new BufferedWriter(new FileWriter(tmpFile));
out.append("jBPM: printHelloWorld - " + formatDate.format(new Date()));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
out = null;
}
}
}
- 작성된 Print.java를 실행하여 c:/jbpm.out 파일이 잘 생성 되는지 확인해 보자.
- Eclipse에서 Print.java를 선택한 후 오른쪽 마우스를 누른다.
- "Run AS -> 2 Java Application" 메뉴을 선택 한다.
- c:/jbpm.out 파일이 잘 생성 되었는지 확인 한다.
## 사용자 가이드
### jBPM service API
{|cellspacing="0" cellpadding="2" border="1" width="100%" bgcolor="#FFFFFF" align="center"
|-
|width="30%" align="center" style="color:#15470a; background-color:#91ce5c;"|RepositoryService
|width="70%"|
- 프로세스 정의 데이터를 관리
- JPDL로 정의된 프로세스를 등록할 수 있음
|-
|align="center" style="color:#15470a; background-color:#91ce5c;"|IdentityService
|
- User와 Group 관리
|-
|align="center" style="color:#15470a; background-color:#91ce5c;"|ExecutionService
|
- 프로세스 실행 및 관리
- 실행되고 있는 Process Instance 목록 등을 제공
|-
|align="center" style="color:#15470a; background-color:#91ce5c;"|TaskService
|
- 프로세스의 각 단위 작업을 관리
- 사용자에 의해서 실행되는 Task를 관리하는 서비스
- Process Instance에서 사용자별로 할당된 Task 목록 등을 제공
|-
|align="center" style="color:#15470a; background-color:#91ce5c;"|HistoryService
|
- 프로세스의 실행 내역 관리
|-
|align="center" style="color:#15470a; background-color:#91ce5c;"|ManagementService
|
- jBPM을 관리하기 위해서 jBPM 관리 콘솔에서 사용하는 서비스
|}
### RepositoryService
import org.jbpm.api.Configuration;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.RepositoryService;
ProcessEngine processEngine = null;
RepositoryService repositoryService = null;
String deploymentId = null;
processEngine = new Configuration().setResource("jbpm.cfg.xml").buildProcessEngine();
repositoryService = processEngine.getRepositoryService();
//--- jPDL deploy
deploymentId = repositoryService.createDeployment().addResourceFromClasspath("printHelloWorld.jpdl.xml").deploy();
//--- repositoryService.deleteDeployment(deploymentId);
### IdentityService
import org.jbpm.api.IdentityService;
IdentityService identityService = processEngine.getIdentityService();
identityService.createGroup("sales-dept");
identityService.createUser("johndoe", "firstName", "lastName", "email");
identityService.createMembership("johndoe", "sales-dept");
identityService.createUser("joesmoe", "joesmoe", "Joe", "Smoe");
identityService.createMembership("joesmoe", "sales-dept");
//--- groupid를 반환 한다.
String createGroup(String groupName);
String createGroup(String groupName, String groupType)
String createGroup(String groupName, String groupType, String parentGroupId);
### ExecutionService
#### ExecutionService
import org.jbpm.api.ExecutionService;
import org.jbpm.api.ProcessInstance;
//--- Process 관리
ExecutionService executionService = null;
ProcessInstance processInstance = null;
String pid = null;
executionService = processEngine.getExecutionService();
Map<String,Object> variables = new HashMap<String,Object>();
variables.put("customer", "홍길동"); //--- jpdl에서 #{customer} 라는 이름으로 지정 가능
variables.put("type", "Accident");
variables.put("amount", new Float(283.2));
//--- Start new process
//--- processInstance = executionService.startProcessInstanceByKey("hello");
processInstance = executionService.startProcessInstanceById("hello-1", variables);
pid = processInstance.getId();
#### State
Execution executionInA = processInstance.findActiveExecutionIn("a");
assertNotNull(executionInA);
processInstance = executionService.signalExecutionById(executionInA.getId());
processInstance = executionService.signalExecutionById(executionId, "accept");
#### Decision
- 사례 1
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("content", "good");
ProcessInstance processInstance =
executionService.startProcessInstanceByKey("DecisionConditions", variables);
assertTrue(processInstance.isActive("submit document"));
- 사례 2
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("content", "good");
ProcessInstance processInstance =
executionService.startProcessInstanceByKey("DecisionExpression", variables);
- 사례 3
public class ContentEvaluation implements DecisionHandler {
public String decide(OpenExecution execution) {
String content = (String) execution.getVariable("content");
if (content.equals("you're great")) {
return "good";
}
if (content.equals("you gotta improve")) {
return "bad";
}
return "ugly";
}
}
#### sub-process
- 사례 1
<sub-process name="review" sub-process-key="SubProcessReview">
</sub-process>
사례 2
<sub-process name="review"
sub-process-key="SubProcessReview"
outcome="#{result}">
</sub-process>
사례 3
<sub-process name="review"
sub-process-key="SubProcessReview">
</sub-process>
java
JBoss jBPM에 의해서 자동으로 실행되는 단계로 특정 Java Class의 Method를 호출 한다.
{|cellspacing="0" cellpadding="2" border="1" width="100%" bgcolor="#FFFFFF" align="center"
|-
|width="30%" style="background-color:#eee;" align="center" valign="middle"|name="이름"
|width="70%"|
이 단계의 이름, 분기(transition)시 사용 한다. style="background-color:#eee;" align="center" valign="middle" width="75%" 실행할 Java 클래스 지정
class 대신 expr="#{변수}" 를 사용하여 실행할 Java 클래스를 지정할 수도 있다. style="background-color:#eee;" align="center" valign="middle" Java 클래스에서 실행될 함수명(Method)을 지정 한다. style="background-color:#eee;" align="center" valign="middle" 반환되는 객체가 저장될 변수명을 정의 한다.
다른 단계에서 "#{반환되는 객체명}" 으로 지정하여 사용할 수 있다. style="background-color:#eee;" align="center" valign="middle" 이 단계를 그림으로 그릴 때 표시되는 위치 style="background-color:#eee;" align="center" valign="middle" Java Method에 인수로 전달하는 값을 정의
문자열 :
-> String 숫자 :
-> Integer 객체 : -> Object 또는 해당 객체의 타입 style="background-color:#eee;" align="center" valign="middle" 함수에 전달되는 값이 아닌 Java 클래스에 선언된 변수에 전달되는 값을 정의 한다.
변수값은 위 에 전달되는 값과 동일한 문법을 사용하여 정의 한다. style="background-color:#eee;" align="center" valign="middle" Java 클래스의 함수를 실행한 후 분기할 다음 단계를 명시 한다.
|}JBoss jBPM의 java 실행 사례
//--- com.groupware.approve.manager.ApproveWorkflowManager 클래스의 documentMove 함수가 자동 실행 된다.
//--- processInfo는 Process를 처음 실행할 때 전달된 HashMap
import com.groupware.approve.manager;
public class ApproveWorkflowManager {
public String documentMove(String stepInfo, HashMap processInfo,
String beforeUser, String beforeBox, String afterUser, String afterBox) {
processInfo.put("result", "ok");
return "result";
}
}
script
참고 문헌
사례 1
사례 2
hql
사례 1
select activity.name
from org.jbpm.pvm.internal.model.ActivityImpl as activity
where activity.name like :activityName
select count(*)
from org.jbpm.pvm.internal.model.ActivityImpl
사례 1
Reminder: ${person} celebrates his birthday!
Do not forget: ${date} is the birthday of ${person}
event
public class LogListener implements EventListener {
// value gets injected from process definition
String msg;
public void notify(EventListenerExecution execution) {
List logs = (List) execution.getVariable("logs");
if (logs==null) {
logs = new ArrayList();
execution.setVariable("logs", logs);
}
logs.add(msg);
execution.setVariable("logs", logs);
}
}
timer
jbmp.cfg.xml
Dudate 문법
quantity [business](business.md) {second | seconds | minute | minutes |
hour | hours | day | days | week |
weeks | month | months | year | years}
사례 1
사례 2
group
group
group timer
TaskService
import org.jbpm.api.TaskService;
import org.jbpm.api.task.Task;
TaskService taskService = null;
List taskList = null;
Task task = null;
String taskId = null;
taskService = processEngine.getTaskService();
//--- 사용자의 Task 목록을 반환
taskList = taskService.findPersonalTasks("johndoe");
//--- 그룹의 Task 목록을 반환
//--- taskService.findGroupTasks(groupid);
task = taskList.get(0);
taskId = task.getId();
Set variableNames = taskService.getVariableNames(taskId);
Map variables = taskService.getVariables(taskId, variableNames);
variables = new HashMap();
variables.put("category", "small");
variables.put("lires", 923874893);
taskService.setVariables(taskId, variables);
String outcome = null;
taskService.completeTask(taskId);
taskService.completeTask(taskId, variables);
taskService.completeTask(taskId, outcome);
taskService.completeTask(taskId, outcome, variables);
Task
사용자에게 할당되어 실행되는 단계
{|cellspacing="0" cellpadding="2" border="1" width="100%" bgcolor="#FFFFFF" align="center"
|-
|width="30%" style="background-color:#eee;" align="center" valign="middle"|name="이름"
|width="70%"|이 단계의 이름, 분기(transition)시 사용 한다. style="background-color:#eee;" align="center" valign="middle" Task 단계에 할당된 사용자 아이디 style="background-color:#eee;" align="center" valign="middle" Task 단계를 종료할 수 있도록 할당된 사용자 아이디 목록 style="background-color:#eee;" align="center" valign="middle" Task 단계를 종료할 수 있도록 할당된 그룹 아이디 목록
|}jPDL에서 Task 정의
사례
//--- 특정 Process에서 특정 사용자의 특정 Task를 가져 온다.
public Task getTask(String processid, String userid, String taskname) {
TaskService taskService = null;
TaskQuery query = null;
List taskList = null;
taskService = WorkflowManager.getProcessEngine().getTaskService();
query = taskService.createTaskQuery();
taskList = query.processInstanceId(processid).assignee(userid).activityName(taskname).list();
if (0 < taskList.size()) {
return taskList.get(0);
}
return null;
}
사례 1
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;
}
}
Map variables = new HashMap();
variables.put("order", new Order("johndoe"));
ProcessInstance processInstance = executionService
.startProcessInstanceByKey("TaskAssignee", variables);
List taskList = taskService.findPersonalTasks("johndoe");
사례 2
taskService.getAssignedTasks("johndoe");
taskService.findGroupTasks("johndoe");
taskService.takeTask(task.getDbid(), "johndoe");
사례 3
public class AssignTask implements AssignmentHandler {
String assignee;
public void assign(Assignable assignable, OpenExecution execution) {
assignable.setAssignee(assignee);
}
}
사례 4
사례 5
HistoryService
import org.jbpm.api.HistoryService;
import org.jbpm.api.history.HistoryProcessInstance;
import org.jbpm.api.history.HistoryProcessInstanceQuery;
HistoryService historyService = null;
List historyProcessInstances = null;
historyService = processEngine.getHistoryService();
historyProcessInstances = historyService.createHistoryProcessInstanceQuery()
.processDefinitionId("hello-1")
.orderAsc(HistoryProcessInstanceQuery.PROPERTY_STARTTIME)
.list();
ManagementService
import org.jbpm.api.ManagementService;
ManagementService managementService = null;
managementService = processEngine.getManagementService();
Migration
foobar.jpdl.xml
Migration in Java program
ProcessDefinition pd1 = deployProcessDefinition("foobar", originalVersion);
ProcessDefinition pd5 = deployProcessDefinition("foobar", versionWithAbsoluteVersionRange);
관리자 가이드
jBPM 엔진 및 도구
Runtime Engine (LGPL)
Eclipse Designer (EPL, 준비중)
Web Modeller (MIT, Signavio)
참고 문헌
매뉴얼
Evaluations : Workflow 솔루션 비교
분류: 오픈소스