Jbpm 프로 세 스 노드
노드 노드 는 자동 완성 노드 로 노드 노드 노드 에 Action 을 정의 하지 않 으 면 노드 노드 노드 에 도달 한 후에 멈 추 지 않 고 노드 노드 노드 의 다음 노드 로 계속 내 려 갑 니 다.이전의 Helloworld 예 를 이용 하여 노드 노드 에 Action 을 추가 합 니 다. (Action 의 실행 은 node - enter 이후 node - leve 이전 입 니 다)
<node name="node1">
<action class="com.royzhou.action.NodeAction"></action>
<transition to="state1"></transition>
</node>
Action 클래스 는 다음 과 같 습 니 다:
package com.royzhou.action;
import org.jbpm.graph.def.ActionHandler;
import org.jbpm.graph.exe.ExecutionContext;
public class NodeAction implements ActionHandler {
public void execute(ExecutionContext executionContext) throws Exception {
System.out.println("node action……………………");
}
}
테스트 클래스 는 다음 과 같 습 니 다:
package com.royzhou.test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.zip.ZipInputStream;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
public class HelloWorldDB {
public static void deploy() throws FileNotFoundException {
JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
FileInputStream fis = new FileInputStream("F:/workspace/jbpm-test/src/main/jpdl/helloworld/helloworld.zip ");
ZipInputStream zis = new ZipInputStream(fis);
ProcessDefinition processDefinition = ProcessDefinition.parseParZipInputStream(zis);
jbpmContext.deployProcessDefinition(processDefinition);
fis.close();
zis.close();
} catch(Exception e) {
e.printStackTrace();
} finally {
jbpmContext.close();
}
}
public static void main(String[] args) throws FileNotFoundException {
HelloWorldDB.deploy();
JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
jbpmContext.setActorId("royzhou");
//
ProcessDefinition processDefinition = jbpmContext.getGraphSession().findLatestProcessDefinition("helloworld");
ProcessInstance processInstance = new ProcessInstance(processDefinition);
//
Token token = processInstance.getRootToken();
//
System.out.println("1: :" + token.getNode().getName());
// Node
token.signal();
/**
* Node Action
* Node
*/
System.out.println("2: :" + token.getNode().getName());
// State
token.signal();
System.out.println("3: :" + token.getNode().getName());
token.signal();
System.out.println("4: :" + token.getNode().getName());
System.out.println(" :" + token.getProcessInstance().hasEnded());
jbpmContext.close();
}
}
테스트 결 과 는 다음 과 같 습 니 다. (Node 에 Action 을 설정 할 때 절차 가 대기 상태 임 을 검증 하 였 습 니 다)
1: 프로 세 스 가 현재 있 는 노드: start - state 1
node action……………………
2: 프로 세 스 현재 위치 노드: node 1
3: 프로 세 스 가 현재 있 는 노드: state 1
4: 프로 세 스 현재 위치 노드: end - state 1
프로 세 스 상태 종료 여부: true
2. 상태 노드
State 노드 속성 은 Node 와 유사 하지만, 프로 세 스 가 State 노드 로 흐 를 때 외부 에서 흐 르 는 명령 을 보 낼 때 까지 멈 춥 니 다. 예 를 들 어 signal ().
3、Task-Node
Task Node 노드 는 Jbpm 에서 매우 중요 한 노드 로 작업 을 추가 하고 작업 인 스 턴 스 를 생 성 할 수 있 습 니 다.하나의 Task Node 는 여러 개의 Task 를 정의 할 수 있 고 Task 에 집행 자 를 배정 할 수 있 습 니 다.다음은 하나의 예 를 통 해 Task Node 를 설명 하 겠 습 니 다.
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="tasknode">
<start-state name="start-state1">
<transition to="task-node1"></transition>
</start-state>
<task-node name="task-node1">
<task name="mytask">
<assignment actor-id="royzhou"></assignment>
</task>
<transition to="end-state1"></transition>
</task-node>
<end-state name="end-state1"></end-state>
</process-definition>
위의 프로 세 스 파일 은 Task Node 를 정 의 했 습 니 다. Task Node 아래 에 Task 노드 를 정의 하여 royzhou 라 는 사람 에 게 할당 되 었 습 니 다. (실제 개발 중인 작업 분 배 는 더욱 복잡 합 니 다)
이어서 우 리 는 테스트 클래스 를 쓰기 시작 했다.
package com.royzhou.test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.zip.ZipInputStream;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
public class TaskNode {
public static void deploy() throws FileNotFoundException {
JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
FileInputStream fis = new FileInputStream("F:/workspace/jbpm-test/src/main/jpdl/tasknode/tasknode.zip");
ZipInputStream zis = new ZipInputStream(fis);
ProcessDefinition processDefinition = ProcessDefinition.parseParZipInputStream(zis);
jbpmContext.deployProcessDefinition(processDefinition);
fis.close();
zis.close();
} catch(Exception e) {
e.printStackTrace();
} finally {
jbpmContext.close();
}
}
public static void main(String[] args) throws FileNotFoundException {
TaskNode.deploy();
JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
ProcessDefinition processDefinition = jbpmContext.getGraphSession().findLatestProcessDefinition("tasknode");
ProcessInstance processInstance = new ProcessInstance(processDefinition);
Token token = processInstance.getRootToken();
token.signal();
System.out.println(" :" + token.getNode().getName());
jbpmContext.close();
}
}
배경 인쇄 결과:
프로 세 스 현재 위치 노드: task - node 1
jbpm 보기taskinstance 표 는 my task 라 는 임 무 를 보 았 습 니 다. royzhou 에 지정 하여 우리 의 임 무 를 성공 적 으로 만 들 었 음 을 설명 합 니 다.
Task Node 는 몇 가지 중요 한 속성 이 있 습 니 다:
Signal:
last: 마지막 완성 후 계속 아래로 이동 합 니 다. 작업 이 생 성 되 지 않 으 면 다음 노드 로 바로 이동 합 니 다.
last - wait: 마지막 완성 후 계속 아래로 이동 합 니 다. 작업 이 생 성 되 지 않 으 면 대기 상태 입 니 다.
first: 한 개 만 완성 하면 계속 아래로 이동 합 니 다. 작업 이 생 성 되 지 않 으 면 다음 노드 로 이동 합 니 다.
first - wait: 한 개 만 완성 하면 계속 아래로 이동 합 니 다. 작업 이 생 성 되 지 않 으 면 대기 상태 입 니 다.
never: 호출 프로 세 스 인 스 턴 스. signal () 을 표시 해 야 계속 돌아 갑 니 다.
unsynchronized: 멈 추 지 않 고 다음 노드 로 바로 이동 합 니 다.
task - creates: 프로 세 스 가 이 노드 로 흘러 갈 때 자동 으로 작업 을 만 드 는 지, 기본 값 은 true 입 니 다.false 로 설정 하여 다른 이벤트 에 맞 춰 서명 할 수 있 습 니 다.
4. Start 노드
Start 노드 는 모든 절차 에 있 고 하나만 있 을 수 있 습 니 다.Start 에서 작업 을 설정 할 수 있 지만,
Start 노드 에 설 정 된 task 는 작업 할당 체 제 를 호출 하지 않 습 니 다.이 건 Task Node 와 는 다른...
5. fork 와 join 노드
두 사람 은 쌍 을 지어 나 타 났 다.Fork 노드 는 프로 세 스 를 여러 개의 병렬 로 나 눌 수 있 습 니 다. 즉, Token 을 여러 개의 키 Token 으로 나 누고 join 노드 가 될 때 하나의 Token 으로 모여 계속 아래로 실행 합 니 다.
일반적으로 fork 노드 를 거 친 후에 모든 하위 token 이 다 갈 때 까지 기 다 려 야 join 노드 를 통 해 계속 내 려 갈 수 있 습 니 다. 그러나 우 리 는 join 노드 의 discriminator 속성 을 수정 하여 true 로 설정 한 후에 하나의 키 token 이 join 노드 에 도착 하면 아래로 돌아 갈 수 있 습 니 다.그러나 이렇게 하 는 데 미 치 는 영향 중 하 나 는 끝나 지 않 은 다른 하위 token 의 작업 인 스 턴 스 가 존재 하고 대기 상태 에 있 으 며 작업 참여 자 는 이러한 임 무 를 처리 할 수 있다 는 것 이다.따라서 join 노드 의 discriminator 를 true 로 설정 할 때 다른 분기 의 작업 인 스 턴 스 를 수 동 으로 끝내 야 합 니 다.
fork 노드 에서 우 리 는 조건 을 설정 하여 조건 만 만족 하 는 가 지 를 선택 할 수 있 습 니 다.주로 앞서 언급 한 beanshell 스 크 립 트 를 통 해 이 루어 집 니 다.예 를 들 어 이 실현 을 설명 하 자.
프로 세 스 정 의 는 하나의 start 노드, 하나의 end 노드, 한 쌍 의 fork / join 노드 와 분기 중의 네 개의 node 노드 로 구성 되 고 프로 세 스 정의 xml 파일 은 다음 과 같다.
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="forkjoin">
<start-state name="start-state1">
<transition to="fork1"></transition>
</start-state>
<fork name="fork1">
<script>
<variable name="forkTransition" access="write"></variable>
<expression>
forkTransition = new ArrayList();
if(param > 1000) {
forkTransition.add("to node1");
forkTransition.add("to node2");
} else {
forkTransition.add("to node3");
forkTransition.add("to node4");
}
</expression>
</script>
<transition to="node1" name="to node1"></transition>
<transition to="node2" name="to node2"></transition>
<transition to="node3" name="to node3"></transition>
<transition to="node4" name="to node4"></transition>
</fork>
<join name="join1">
<transition to="end-state1"></transition>
</join>
<node name="node1">
<event type="node-enter">
<script>
print("node1 enter");
</script>
</event>
<transition to="join1"></transition>
</node>
<node name="node2">
<event type="node-enter">
<script>
print("node2 enter");
</script>
</event>
<transition to="join1"></transition>
</node>
<node name="node3">
<event type="node-enter">
<script>
print("node3 enter");
</script>
</event>
<transition to="join1"></transition>
</node>
<node name="node4">
<event type="node-enter">
<script>
print("node4 enter");
</script>
</event>
<transition to="join1"></transition>
</node>
<end-state name="end-state1"></end-state>
</process-definition>
기본 적 인 상황 에서 절차 가 fork 노드 에 들 어간 후에 네 개의 갈래 로 나 뉘 어 각각 Node 노드 를 거 칩 니 다.위 정의 파일 에서 우 리 는 fork 노드 에서 판단 을 했 습 니 다. 만약 에 절차 변수 param > 1000 일 때 분기 1 과 분기 2 를 가 고 작 으 면 분기 3 과 분기 4 를 가 집 니 다.
<script>
<variable name="forkTransition" access="write"></variable>
<expression>
forkTransition = new ArrayList();
if(param > 1000) {
forkTransition.add("to node1");
forkTransition.add("to node2");
} else {
forkTransition.add("to node3");
forkTransition.add("to node4");
}
</expression>
</script>
이 곳 의 forkTransition 은 집합 형식 이 어야 합 니 다. 프로 세 스 가 fork 를 거 친 후에 생 성 된 분기 이름 을 저장 합 니 다.access 속성 을 write 로 설정 하면 프로 세 스 인 스 턴 스 에 대응 하 는 Fork 노드 를 기록 해 야 지정 한 가 지 를 만 들 수 있 습 니 다.Expression 태그 에서 우리 가 하 는 논리 적 처리 입 니 다. 절차 변수 param 을 통 해 Fork 노드 가 구체 적 으로 그 가 지 를 생 성 해 야 한 다 는 것 을 판단 합 니 다.
기본적으로 포크 노드 에 script 을 추가 하지 않 습 니 다. 포크 노드 로 프로 세 스 를 진행 할 때 모든 transition 을 생 성 합 니 다.script 이 설정 되 어 있 으 면 위의 forkTransition 과 같은 변 수 를 설정 해 야 합 니 다.
테스트 클래스 는 다음 과 같 습 니 다. (테스트 를 편리 하 게 하기 위해 절 차 를 데이터베이스 에 발표 하지 않 았 습 니 다. 아래 테스트 사례 도 같은 방법 을 사용 합 니 다)
package com.royzhou.test;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
public class ForkJoin {
public static void main(String[] args) {
ProcessDefinition processDefinition = ProcessDefinition.parseXmlResource("forkjoin/processDefinition.xml");
ProcessInstance processInstance = new ProcessInstance(processDefinition);
processInstance.getContextInstance().setVariable("param", 10);
Token token = processInstance.getRootToken();
token.signal();
}
}
실행 성공 후 배경 출력:
node3 enter
node4 enter
우리 의 param 을 2000 으로 바 꾸 고 다시 실행 합 니 다. 배경 은 다음 과 같 습 니 다.
node1 enter
node2 enter
6. 의사 결정 노드
Decision 노드 는 노드 를 판단 하 는 것 입 니 다. 절차 가 decision 노드 에 도착 하면 여러 개의 경로 가 선택 되 고 우 리 는 이 노드 에서 handler 를 정의 하거나 스 크 립 트 등 을 사용 하여 절차 의 방향 을 결정 할 수 있 습 니 다.Decision 노드 는 Fork 노드 와 달리 여러 개의 Transition 중 하 나 를 선택 할 수 있 고 Fork 노드 는 병행 합 니 다.
예 를 들 어 설명 하 다.
프로 세 스 정 의 는 하나의 start 노드, 하나의 end 노드, 하나의 Decision 노드 와 분기 중의 3 개의 node 노드 로 구성 되 어 있 습 니 다. Decision 에서 우 리 는 delegation 을 설정 하고 DecisionHandler 인 터 페 이 스 를 실현 하 는 클래스 SelectNode 를 사용 하여 프로 세 스 의 방향 을 판단 합 니 다. 그 결 과 는 그 중의 분기 의 이름 이 고 프로 세 스 정의 xml 파일 은 다음 과 같 습 니 다.
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="decision">
<start-state name="start-state1">
<transition to="decision1"></transition>
</start-state>
<decision name="decision1">
<handler class="com.royzhou.action.SelectNode"></handler>
<transition to="node1" name="to node1"></transition>
<transition to="node2" name="to node2"></transition>
<transition to="node3" name="to node3"></transition>
</decision>
<node name="node1">
<script>
print("node1 enter")
</script>
</node>
<node name="node2">
<script>
print("node2 enter")
</script>
<transition to="end-state1"></transition>
</node>
<node name="node3">
<script>
print("node3 enter")
</script>
</node>
<end-state name="end-state1"></end-state>
</process-definition>
SelectNode 클래스: (decisionHandler 인 터 페 이 스 를 실현 하고 decide 방법 을 다시 써 야 합 니 다. 값 을 되 돌려 주 는 transition 의 이름 입 니 다)
package com.royzhou.action;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.graph.node.DecisionHandler;
// DecisionHandler
public class SelectNode implements DecisionHandler {
public String decide(ExecutionContext executionContext) throws Exception {
// transition
String whichWay = executionContext.getVariable("whichWay").toString();
return whichWay;
}
}
테스트 클래스:
package com.royzhou.test;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
public class Decision {
public static void main(String[] args) {
ProcessDefinition processDefinition = ProcessDefinition.parseXmlResource("decision/processDefinition.xml");
ProcessInstance processInstance = new ProcessInstance(processDefinition);
processInstance.getContextInstance().setVariable("whichWay", "to node2");
Token token = processInstance.getRootToken();
token.signal();
}
}
테스트 클래스 실행, 배경 인쇄 :
node2 enter
프로 세 스 변수 whichWay 를 to node 1 로 다시 실행 하고 배경 인쇄:
node1 enter
우리 의 decision 노드 가 그 방향 을 정확하게 처리 했다 는 것 을 설명 한다.
delegation 을 사용 하 는 것 외 에 우 리 는 프로 세 스 파일 에서 decision 노드 의 expression 속성 을 직접 정의 할 수 있 습 니 다. 다음 과 같 습 니 다.
<decision name="decision1" expression="#{whichWay}">
<!--
<handler class="com.royzhou.action.SelectNode"></handler>
-->
<transition to="node1" name="to node1"></transition>
<transition to="node2" name="to node2"></transition>
<transition to="node3" name="to node3"></transition>
</decision>
JPDL 표현 식 을 사용 하여 프로 세 스 방향 을 지정 합 니 다. JPDL 표현 식 은 EL 표현 식 과 유사 한 언어 입 니 다.
위의 expression 은 프로 세 스 변수 에서 whichWay 라 는 변 수 를 우리 프로 세 스 의 방향 으로 선택 하 는 것 을 나타 낸다.
우리 의 테스트 클래스 를 다시 실행 합 니 다.발견 결 과 는 위의 방법 과 같다.
그 밖 에 저 희 는 transition 노드 에서 condition 라벨 을 직접 정의 하고 JPDL 표현 식 과 결합 하여 저희 의 판단 근거 로 삼 을 수 있 습 니 다.
<decision name="decision1">
<transition to="node1" name="to node1">
<condition expression="#{whichWay == 'to node1'}"></condition>
</transition>
<transition to="node2" name="to node2">
<condition expression="#{whichWay == 'to node2'}"></condition>
</transition>
<transition to="node3" name="to node3">
<condition expression="#{whichWay == 'to node3'}"></condition>
</transition>
</decision>
테스트 프로그램 을 다시 실행 한 결과 결과 결과 가 일치 합 니 다.
이 를 통 해 알 수 있 듯 이 Decision 노드 는 우리 가 delegation, condition 과 expression 세 가지 방식 으로 절차 의 방향 을 지정 하 는 것 을 지원 합 니 다.
7. 프로 세 스 상태 노드
하위 프로 세 스 노드 는 우리 의 복잡 한 절 차 를 간소화 할 수 있다.주류 프로 세 스 와 하위 프로 세 스 사이 에 변 수 를 공유 할 수 있 습 니 다.하위 프로 세 스 를 사용 하면 주류 프로 세 스 가 발표 되 기 전에 하위 프로 세 스 를 먼저 발표 해 야 한다.
예 를 들 어 주류 프로 세 스 와 하위 프로 세 스 와 그 변수 공 유 를 설명 한다.
주류 프로그램 정의 파일 mainprocess / processdefinition. xml
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="mainprocess">
<start-state name="start-state1">
<transition to="task-node1"></transition>
</start-state>
<task-node name="task-node1">
<event type="node-enter">
<script>
print("main task node1 enter")
</script>
</event>
<task name="maintask1">
<assignment actor-id="maintask1"></assignment>
</task>
<transition to="process-state1"></transition>
</task-node>
<process-state name="process-state1">
<sub-process name="subprocess"/>
<variable name="mainParam" access="read"></variable>
<variable name="subParam" access="write"></variable>
<transition to="task-node2"></transition>
</process-state>
<task-node name="task-node2">
<event type="node-enter">
<script>
print("main task node2 enter")
</script>
</event>
<task name="maintask2">
<assignment actor-id="maintask2"></assignment>
</task>
<transition to="end-state1"></transition>
</task-node>
<end-state name="end-state1"></end-state>
</process-definition>
주류 프로 세 스에 프로 세 스 - state 노드 를 설 정 했 습 니 다. sub - processs 의 name 속성 은 하위 프로 세 스 의 이름 을 표시 합 니 다.
< variable name = "mainParam" access = "read" > < / variable > 는 주류 에서 mainParam 변 수 를 읽 는 것 을 나타 낸다.
< variable name = "subParam" access = "write" > < / variable > 는 하위 프로 세 스 가 변 수 를 subParam 으로 주류 프로 세 스 로 되 돌려 줍 니 다.
하위 프로 세 스 정의 파일: subprocess / processdefinition. xml
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="subprocess">
<start-state name="start-state1">
<transition to="task-node1"></transition>
</start-state>
<task-node name="task-node1">
<event type="node-enter">
<script>
print("sub task node1 enter")
</script>
</event>
<task name="subtask1">
<assignment actor-id="subtask1"></assignment>
</task>
<event type="node-enter">
<script>
print("sub task node1 enter")
</script>
</event>
<transition to="end-state1"></transition>
</task-node>
<end-state name="end-state1"></end-state>
</process-definition>
테스트 클래스:
package com.royzhou.test;
import java.io.FileNotFoundException;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
import org.jbpm.taskmgmt.exe.TaskInstance;
public class SubProcess {
public static void init() {
JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
jbpmConfiguration.createSchema();
}
public static void deploySub() throws FileNotFoundException {
JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
ProcessDefinition subProcessDefinition = ProcessDefinition.parseXmlResource("subprocess/processDefinition.xml");
jbpmContext.deployProcessDefinition(subProcessDefinition);
} catch(Exception e) {
e.printStackTrace();
} finally {
jbpmContext.close();
}
}
public static void deployMain() throws FileNotFoundException {
JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
ProcessDefinition mainProcessDefinition = ProcessDefinition.parseXmlResource("mainprocess/processDefinition.xml");
jbpmContext.deployProcessDefinition(mainProcessDefinition);
} catch(Exception e) {
e.printStackTrace();
} finally {
jbpmContext.close();
}
}
public static void startProcess() {
JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
ProcessDefinition processDefinition = jbpmContext.getGraphSession().findLatestProcessDefinition("mainprocess");
ProcessInstance processInstance = new ProcessInstance(processDefinition);
Token token = processInstance.getRootToken();
token.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
jbpmContext.close();
}
}
public static void startMainTask1() {
JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
// maintask1
TaskInstance mainTaskInstance1 = jbpmContext.loadTaskInstance(1L);
//
mainTaskInstance1.getContextInstance().setVariable("mainParam", " ");
mainTaskInstance1.end();
} catch (Exception e) {
e.printStackTrace();
} finally {
jbpmContext.close();
}
}
public static void startSubTask1() {
JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
// subtask1
TaskInstance subTaskInstance1 = jbpmContext.loadTaskInstance(2L);
//
System.out.println(subTaskInstance1.getName() + " ,mainParam :" + subTaskInstance1.getContextInstance().getVariable("mainParam").toString());
//
subTaskInstance1.getContextInstance().setVariable("subParam", " ");
subTaskInstance1.end();
} catch (Exception e) {
e.printStackTrace();
} finally {
jbpmContext.close();
}
}
public static void startMainTask2() {
JbpmConfiguration jbpmConfiguration = JbpmConfiguration.getInstance();
JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
try {
TaskInstance mainTaskInstance2 = jbpmContext.loadTaskInstance(3L);
//
System.out.println(mainTaskInstance2.getName()+" ,subParam :" + mainTaskInstance2.getContextInstance().getVariable("subParam").toString());
mainTaskInstance2.end();
} catch (Exception e) {
e.printStackTrace();
} finally {
jbpmContext.close();
}
}
public static void main(String[] args) throws FileNotFoundException {
//
SubProcess.init();
// ,
SubProcess.deploySub();
SubProcess.deployMain();
SubProcess.startProcess();
SubProcess.startMainTask1();
SubProcess.startSubTask1();
SubProcess.startMainTask2();
}
}
위의 프로그램 을 실행 하고 성공 적 으로 실행 한 결 과 는 다음 과 같 습 니 다.
main task node1 enter
sub task node1 enter
sub task node1 enter
subtask 1 서브 프로 세 스 는 주류 프로 세 스 변 수 를 읽 습 니 다. mainParam 의 값 은 주류 프로 세 스 설정 변수 입 니 다.
main task node2 enter
maintask 2 주류 프로 세 스 에서 하위 프로 세 스 변 수 를 읽 습 니 다. subParam 의 값 은 하위 프로 세 스 설정 변수 입 니 다.
8. Mail 노드
이 노드 는 메 일의 발송 을 실현 할 수 있 고 알림 알림 기능 이 있 습 니 다.
구체 적 으로 두 가지 설정 방식 이 있 습 니 다.
mail node 노드 의 template 속성 설정 을 통 해 jbpm. mail. template. xml 파일 의 모델 을 수정 하고 우리 가 필요 로 하 는 모델 을 추가 해 야 합 니 다. 구체 적 인 모델 설정 은 안에 있 는 모델 을 참조 할 수 있 습 니 다.예 를 들 어 다음 과 같이 설명 한다.
프로 세 스 모드 파일: start - > mail node - > end
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="mail">
<start-state name="start-state1">
<transition to="mail-node1"></transition>
</start-state>
<mail-node name="mail-node1" template="test">
<event type="node-enter">
<script>
print("enter mail node")
</script>
</event>
<event type="node-leave">
<script>
print("leave mail node")
</script>
</event>
<transition to="end-state1"></transition>
</mail-node>
<end-state name="end-state1"></end-state>
</process-definition>
우리 가 사용 하 는 모델 은 test 이지 만 jbpm. mail. template. xml 이 없 기 때문에 우리 스스로 추가 해 야 합 니 다.
<mail-template name="test">
<actors>#{actorId}</actors>
<subject>mail node </subject>
<text><![CDATA[Hi #{actorId},
mail node 。
]]></text>
</mail-template>
이것 은 우리 가 정의 한 모델 입 니 다. 그 중에서 actors 라벨 은 받 는 사람의 주 소 를 표시 합 니 다. 메 일 분석 류 를 사용 하여 분석 해 야 합 니 다. 메 일 분석 류 는 address Resolver 인 터 페 이 스 를 실현 하 는 클래스 입 니 다.또한 jbpm. cfg. xml 에 설정 하여 jbpm 에 이 종 류 를 사용 하여 메 일 을 보 내 는 주 소 를 분석 하 라 고 알려 야 합 니 다.
package com.royzhou.util;
import org.jbpm.mail.AddressResolver;
public class MailAddressResolver implements AddressResolver {
public Object resolveAddress(String actorId) {
return "[email protected]";
}
}
다음은 jbpm. cfg. xml 설정 내용 입 니 다.
<jbpm-configuration>
<!-- -->
<bean name="jbpm.mail.address.resolver"
class="com.royzhou.util.MailAddressResolver" singleton="true" />
<!-- -->
<string name="resource.mail.properties" value="jbpm.mail.properties" />
<!-- -->
<string name="mail.class.name" value="com.royzhou.util.Mail" />
<!-- -->
<string name="jbpm.mail.from.address" value="[email protected]"></string>
</jbpm-configuration>
메 일 설정 정 보 는 다음 과 같 습 니 다.
mail.smtp.host=smtp.163.com
mail.smtp.user=test
mail.smtp.password=test
mail.smtp.auth=true
설정 에서 저 희 는 자신의 메 일 발송 류 를 사용 합 니 다. 이것 은 jbpm 가 제공 한 메 일 발송 류 가 신분 인증 을 제공 하지 않 았 기 때문에 직접 사용 하면 이상 을 알 릴 수 있 습 니 다.
수 정 된 메 일 발송 클래스 는 다음 과 같 습 니 다.
package com.royzhou.util;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.Authenticator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmException;
import org.jbpm.graph.def.ActionHandler;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.jpdl.el.ELException;
import org.jbpm.jpdl.el.VariableResolver;
import org.jbpm.jpdl.el.impl.JbpmExpressionEvaluator;
import org.jbpm.mail.AddressResolver;
import org.jbpm.util.ClassLoaderUtil;
import org.jbpm.util.XmlUtil;
public class Mail implements ActionHandler {
private static final long serialVersionUID = 1L;
String template = null;
String actors = null;
String to = null;
String bcc = null;
String bccActors = null;
String subject = null;
String text = null;
ExecutionContext executionContext = null;
public Mail() {
}
public Mail(String template,
String actors,
String to,
String subject,
String text) {
this.template = template;
this.actors = actors;
this.to = to;
this.subject = subject;
this.text = text;
}
public Mail(String template,
String actors,
String to,
String bccActors,
String bcc,
String subject,
String text) {
this.template = template;
this.actors = actors;
this.to = to;
this.bccActors = bccActors;
this.bcc = bcc;
this.subject = subject;
this.text = text;
}
public void execute(ExecutionContext executionContext) {
this.executionContext = executionContext;
send();
}
public List getRecipients() {
List recipients = new ArrayList();
if (actors!=null) {
String evaluatedActors = evaluate(actors);
List tokenizedActors = tokenize(evaluatedActors);
if (tokenizedActors!=null) {
recipients.addAll(resolveAddresses(tokenizedActors));
}
}
if (to!=null) {
String resolvedTo = evaluate(to);
recipients.addAll(tokenize(resolvedTo));
}
return recipients;
}
public List getBccRecipients() {
List recipients = new ArrayList();
if (bccActors!=null) {
String evaluatedActors = evaluate(bccActors);
List tokenizedActors = tokenize(evaluatedActors);
if (tokenizedActors!=null) {
recipients.addAll(resolveAddresses(tokenizedActors));
}
}
if (bcc!=null) {
String resolvedTo = evaluate(to);
recipients.addAll(tokenize(resolvedTo));
}
if (JbpmConfiguration.Configs.hasObject("jbpm.mail.bcc.address")) {
recipients.addAll(tokenize(
JbpmConfiguration.Configs.getString("jbpm.mail.bcc.address")));
}
return recipients;
}
public String getSubject() {
if (subject==null) return null;
return evaluate(subject);
}
public String getText() {
if (text==null) return null;
return evaluate(text);
}
public String getFromAddress() {
if (JbpmConfiguration.Configs.hasObject("jbpm.mail.from.address")) {
return JbpmConfiguration.Configs.getString("jbpm.mail.from.address");
}
return "jbpm@noreply";
}
public void send() {
if (template!=null) {
Properties properties = getMailTemplateProperties(template);
if (actors==null) {
actors = properties.getProperty("actors");
}
if (to==null) {
to = properties.getProperty("to");
}
if (subject==null) {
subject = properties.getProperty("subject");
}
if (text==null) {
text = properties.getProperty("text");
}
if (bcc==null) {
bcc = properties.getProperty("bcc");
}
if (bccActors==null) {
bccActors = properties.getProperty("bccActors");
}
}
send(getMailServerProperties(),
getFromAddress(),
getRecipients(),
getBccRecipients(),
getSubject(),
getText());
}
public static void send(Properties mailServerProperties, String fromAddress, List recipients, String subject, String text) {
send(mailServerProperties, fromAddress, recipients, null, subject, text);
}
public static void send(Properties mailServerProperties, String fromAddress, List recipients, List bccRecipients, String subject, String text) {
if ( (recipients==null)
|| (recipients.isEmpty())
) {
log.debug("skipping mail because there are no recipients");
return;
}
mailServerProperties.put("mail.smtp.auth", "true");
log.debug("sending email to '"+recipients+"' about '"+subject+"'");
/**
*
* royzhou 2009.07.21
*/
String userName = mailServerProperties.getProperty("mail.smtp.user").toString();
String password = mailServerProperties.getProperty("mail.smtp.password").toString();
MyAuthentication myAuthentication = new MyAuthentication(userName,password);
Session session = Session.getDefaultInstance(mailServerProperties, myAuthentication);
MimeMessage message = new MimeMessage(session);
try {
if (fromAddress!=null) {
message.setFrom(new InternetAddress(fromAddress));
}
Iterator iter = recipients.iterator();
while (iter.hasNext()) {
InternetAddress recipient = new InternetAddress((String) iter.next());
message.addRecipient(Message.RecipientType.TO, recipient);
}
if (bccRecipients!=null) {
iter = bccRecipients.iterator();
while (iter.hasNext()) {
InternetAddress recipient = new InternetAddress((String) iter.next());
message.addRecipient(Message.RecipientType.BCC, recipient);
}
}
if (subject!=null) {
message.setSubject(subject);
}
if (text!=null) {
message.setText(text);
}
message.setSentDate(new Date());
Transport.send(message);
} catch (Exception e) {
throw new JbpmException("couldn't send email", e);
}
}
protected List tokenize(String text) {
if (text==null) {
return null;
}
List list = new ArrayList();
StringTokenizer tokenizer = new StringTokenizer(text, ";:");
while (tokenizer.hasMoreTokens()) {
list.add(tokenizer.nextToken());
}
return list;
}
protected Collection resolveAddresses(List actorIds) {
List emailAddresses = new ArrayList();
Iterator iter = actorIds.iterator();
while (iter.hasNext()) {
String actorId = (String) iter.next();
AddressResolver addressResolver = (AddressResolver) JbpmConfiguration.Configs.getObject("jbpm.mail.address.resolver");
Object resolvedAddresses = addressResolver.resolveAddress(actorId);
if (resolvedAddresses!=null) {
if (resolvedAddresses instanceof String) {
emailAddresses.add((String)resolvedAddresses);
} else if (resolvedAddresses instanceof Collection) {
emailAddresses.addAll((Collection)resolvedAddresses);
} else if (resolvedAddresses instanceof String[]) {
emailAddresses.addAll(Arrays.asList((String[])resolvedAddresses));
} else {
throw new JbpmException("Address resolver '"+addressResolver+"' returned '"+resolvedAddresses.getClass().getName()+"' instead of a String, Collection or String-array: "+resolvedAddresses);
}
}
}
return emailAddresses;
}
Properties getMailServerProperties() {
Properties mailServerProperties = new Properties();
if (JbpmConfiguration.Configs.hasObject("resource.mail.properties")) {
String mailServerPropertiesResource = JbpmConfiguration.Configs.getString("resource.mail.properties");
try {
InputStream mailServerStream = ClassLoaderUtil.getStream(mailServerPropertiesResource);
mailServerProperties.load(mailServerStream);
} catch (Exception e) {
throw new JbpmException("couldn't get configuration properties for jbpm mail server from resource '"+mailServerPropertiesResource+"'", e);
}
} else if (JbpmConfiguration.Configs.hasObject("jbpm.mail.smtp.host")) {
String smtpServer = JbpmConfiguration.Configs.getString("jbpm.mail.smtp.host");
mailServerProperties.put("mail.smtp.host", smtpServer);
} else {
log.error("couldn't get mail properties");
}
return mailServerProperties;
}
static Map templates = null;
static Map templateVariables = null;
synchronized Properties getMailTemplateProperties(String templateName) {
if (templates==null) {
templates = new HashMap();
String mailTemplatesResource = JbpmConfiguration.Configs.getString("resource.mail.templates");
org.w3c.dom.Element mailTemplatesElement = XmlUtil.parseXmlResource(mailTemplatesResource).getDocumentElement();
List mailTemplateElements = XmlUtil.elements(mailTemplatesElement, "mail-template");
Iterator iter = mailTemplateElements.iterator();
while (iter.hasNext()) {
org.w3c.dom.Element mailTemplateElement = (org.w3c.dom.Element) iter.next();
Properties templateProperties = new Properties();
addTemplateProperty(mailTemplateElement, "actors", templateProperties);
addTemplateProperty(mailTemplateElement, "to", templateProperties);
addTemplateProperty(mailTemplateElement, "subject", templateProperties);
addTemplateProperty(mailTemplateElement, "text", templateProperties);
addTemplateProperty(mailTemplateElement, "bcc", templateProperties);
addTemplateProperty(mailTemplateElement, "bccActors", templateProperties);
templates.put(mailTemplateElement.getAttribute("name"), templateProperties);
}
templateVariables = new HashMap();
List variableElements = XmlUtil.elements(mailTemplatesElement, "variable");
iter = variableElements.iterator();
while (iter.hasNext()) {
org.w3c.dom.Element variableElement = (org.w3c.dom.Element) iter.next();
templateVariables.put(variableElement.getAttribute("name"), variableElement.getAttribute("value"));
}
}
return (Properties) templates.get(templateName);
}
void addTemplateProperty(org.w3c.dom.Element mailTemplateElement, String property, Properties templateProperties) {
org.w3c.dom.Element element = XmlUtil.element(mailTemplateElement, property);
if (element!=null) {
templateProperties.put(property, XmlUtil.getContentText(element));
}
}
String evaluate(String expression) {
if (expression==null) {
return null;
}
VariableResolver variableResolver = JbpmExpressionEvaluator.getUsedVariableResolver();
if (variableResolver!=null) {
variableResolver = new MailVariableResolver(templateVariables, variableResolver);
}
return (String) JbpmExpressionEvaluator.evaluate(expression, executionContext, variableResolver, null);
}
class MailVariableResolver implements VariableResolver, Serializable {
private static final long serialVersionUID = 1L;
Map templateVariables = null;
VariableResolver variableResolver = null;
public MailVariableResolver(Map templateVariables, VariableResolver variableResolver) {
this.templateVariables = templateVariables;
this.variableResolver = variableResolver;
}
public Object resolveVariable(String pName) throws ELException {
if ( (templateVariables!=null)
&& (templateVariables.containsKey(pName))
){
return templateVariables.get(pName);
}
return variableResolver.resolveVariable(pName);
}
}
private static Log log = LogFactory.getLog(Mail.class);
}
/**
*
* @author royzhou
* 2009.07.21
*/
class MyAuthentication extends Authenticator {
private String userName;
private String password;
public MyAuthentication(String userName, String password) {
this.userName = userName;
this.password = password;
}
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(userName,password);
}
}
다음은 우리 의 테스트 클래스 를 쓰기 시작 합 니 다: MailNode
package com.royzhou.test;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
public class MailNode {
public static void main(String[] args) {
ProcessDefinition processDefinition = ProcessDefinition.parseXmlResource("mail/processDefinition.xml");
ProcessInstance processInstance = new ProcessInstance(processDefinition);
processInstance.getContextInstance().setVariable("actorId", "royzhou");
Token token = processInstance.getRootToken();
token.signal();
System.out.println("end^^^^^^^^^^^^");
}
}
테스트 프로그램 실행, 배경 인쇄:
enter mail node
test====test
leave mail node
end^^^^^^^^^^^^
수신 함 을 열 어 보 니 메 일이 성공 적 으로 보 내 졌 고 메 시 지 는 모두 모드 에 따라 생 성 되 었 습 니 다.
이로써 우 리 는 절차 의 노드 를 기본적으로 한 번 훑 어 보 았 다.필기 가 마침내 끝났다.힘 들 면 한 글자 만.
내일 출장...
돌아 와 서 계속...
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
자바 파일 압축 및 압축 풀기파일 의 간단 한 압축 과 압축 해 제 를 실현 하 였 다.주요 테스트 용 에는 급 하 게 쓸 수 있 는 부분 이 있 으 니 불편 한 점 이 있 으 면 아낌없이 가르쳐 주 십시오. 1. 중국어 문 제 를 해 결 했 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.