Jbpm 프로 세 스 노드

46480 단어 apache.xmlqq각본jbpm
1. 노드 노드
노드 노드 는 자동 완성 노드 로 노드 노드 노드 에 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 &gt; 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(&quot;node1 enter&quot;);
			</script>
		</event>
		<transition to="join1"></transition>
	</node>
	<node name="node2">
		<event type="node-enter">
			<script>
				print(&quot;node2 enter&quot;);
			</script>
		</event>
		<transition to="join1"></transition>
	</node>
	<node name="node3">
		<event type="node-enter">
			<script>
				print(&quot;node3 enter&quot;);
			</script>
		</event>
		<transition to="join1"></transition>
	</node>
	<node name="node4">
		<event type="node-enter">
			<script>
				print(&quot;node4 enter&quot;);
			</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 &gt; 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(&quot;node1 enter&quot;)
		</script>
	</node>
	<node name="node2">
		<script>
			print(&quot;node2 enter&quot;)
		</script>
		<transition to="end-state1"></transition>
	</node>
	<node name="node3">
		<script>
			print(&quot;node3 enter&quot;)
		</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(&quot;main task node1 enter&quot;)
			</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(&quot;main task node2 enter&quot;)
			</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(&quot;sub task node1 enter&quot;)
			</script>
		</event>
		<task name="subtask1">
			<assignment actor-id="subtask1"></assignment>
		</task>
		<event type="node-enter">
			<script>
				print(&quot;sub task node1 enter&quot;)
			</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(&quot;enter mail node&quot;)
			</script>
		</event>
		<event type="node-leave">
			<script>
				print(&quot;leave mail node&quot;)
			</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^^^^^^^^^^^^
수신 함 을 열 어 보 니 메 일이 성공 적 으로 보 내 졌 고 메 시 지 는 모두 모드 에 따라 생 성 되 었 습 니 다.
이로써 우 리 는 절차 의 노드 를 기본적으로 한 번 훑 어 보 았 다.필기 가 마침내 끝났다.힘 들 면 한 글자 만.
내일 출장...
돌아 와 서 계속...

좋은 웹페이지 즐겨찾기