jbpm java节点_Jbpm 流程节点

1、Node节点

Node节点是一个自动完成节点,如果没有在Node节点上定义Action,流程达到Node节点后不会停留,而是继续往下执行到Node节点的下一个节点。利用之前的Helloworld例子,我们在Node节点上加上一个Action(Action的执行是在node-enter之后node-leave之前)

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-state1

node action……………………

2:流程现在所处节点:node1

3:流程现在所处节点:state1

4:流程现在所处节点:end-state1

流程状态是否结束:true

2、State节点

State节点属性类似Node,不过当流程流转到State节点时就会停下来,直到外部向其发送流转的命令,如signal().

3、Task-Node

Task Node节点在Jbpm中是很重要的一个节点,可以用来添加任务,产生任务实例。一个Task Node 可以定义多个Task,为Task分配执行人等等。下面我们通过一个例子来解释Task Node。

上面流程文件定义了一个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-node1

查看jbpm_taskinstance表看到一个名叫mytask的任务,指定给了royzhou说明我们的任务创建成功了。

Task Node有几个比较重要的属性:

Signal:

last:最后一个完成之后继续往下流转,如果没有任务被创建直接流转到下一节点

last-wait:最后一个完成之后继续往下流转,如果没有任务被创建处于等待状态

first:只要有一个完成就继续往下流转,如果没有任务被创建直接流转下一个节点

first-wait:只要一个完成就继续往下流转,如果没有任务被创建则处于等待状态

never:必须显示调用processInstance.signal()才继续流转

unsynchronized:不停留,直接流转到下个节点

task-creates:流程流转到这个节点上时是不是自动创建任务,默认是true。通过设置为false,配合其他事件我们可以实现会签的功能。

4、Start节点

Start节点在每个流程中有且只能有一个。Start中可以配置Task,但是配置在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文件如下:

forkTransition = new ArrayList();

if(param > 1000) {

forkTransition.add("to node1");

forkTransition.add("to node2");

} else {

forkTransition.add("to node3");

forkTransition.add("to node4");

}

print("node1 enter");

print("node2 enter");

print("node3 enter");

print("node4 enter");

默认情况下,当流程进入fork节点之后会分成四个分支,分别经过Node节点。在上面定义文件中我们在fork节点下做了判断,如果流程变量param>1000的时候走分支1和分支2,如果小于则走分支3和分支4。

forkTransition = new ArrayList();

if(param > 1000) {

forkTransition.add("to node1");

forkTransition.add("to node2");

} else {

forkTransition.add("to node3");

forkTransition.add("to node4");

}

注意这里的forkTransition必须是集合类型,它存放的是流程经过fork之后生成的分支名称。access属性设置为write表示是写入流程实例对应的Fork节点,才能生成我们指定的分支。在Expression标签下是我们做的逻辑处理,通过流程变量param来判断Fork节点具体要生成那些分支。

默认我们不为Fork节点添加script,流程到Fork节点时将生成所有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节点是判断节点,当流程到达decision节点之后会有多个路由选择,我们可以在这个节点上定义handler或者是使用脚本等等来决定流程走向。Decision节点不同于Fork节点,它只能选择多个Transition中的其中一个,而Fork节点是并行的。

举例说明一下:

流程定义由一个start节点,一个end节点,一个Decision节点以及分支中的3个node节点组成,在Decision我们设置了delegation,使用实现DecisionHandler接口的类SelectNode来判断流程走向,它返回的结果是其中分支的名称,流程定义的xml文件如下:

print("node1 enter")

print("node2 enter")

print("node3 enter")

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 node1 重新运行,后台打印出:

node1 enter

说明我们的decision节点正确处理了其走向。

除了使用delegation,我们也可以在流程文件中直接定义decision节点的expression属性,如下所示:

这里采用的是JPDL表达式来指定流程走向,JPDL表达式是一种类似EL表达式的语言。

上面expression表示从流程变量中获取whichWay这个变量作为我们流程走向的选择。

重新运行我们的测试类。发现结果与上面一种做法相同。

此外我们还可以直接在transition节点下定义condition标签,配合JPDL表达式来作为我们的判断依据

再次运行测试程序发现结果仍然一致。

由此可见 Decision节点支持我们使用delegation、condition以及expression三种方式来指定流程走向。

7、Process State节点

子流程节点可以简化我们的复杂流程。主流程与子流程之间可以共享变量。如果使用子流程,在主流程发布之前必须先发布子流程。

举例说明一下主流程与子流程及其变量共享:

主流程定义文件mainprocess/processdefinition.xml

print("main task node1 enter")

print("main task node2 enter")

主流程中设置了process-state节点,其sub-process 的name属性表示子流程的名称,

表示从主流程读取mainParam变量

表示子流程将变量subParam写回主流程中。

子流程定义文件:subprocess/processdefinition.xml

print("sub task node1 enter")

print("sub task node1 enter")

测试类:

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

subtask1子流程读取主流程变量,mainParam的值是:主流程设置的变量

main task node2 enter

maintask2主流程读取子流程变量,subParam的值是:子流程设置的变量

8、Mail Node 节点

该节点可以实现邮件的发送,具有通知提醒功能。

具体有两种配置方式:

通过mail node节点的template属性设置,采用此种方式需要修改jbpm.mail.template.xml文件里的模版,加上我们需要的模版,具体模版设置可参照里面已有模版。举例说明下:

流程模版文件:start -> mail node ->end

print("enter mail node")

print("leave mail node")

我们使用的模版是test,但是jbpm.mail.template.xml没有,所以需要我们自己加:

#{actorId}

mail node 节点测试

这是mail node节点的测试内容。

]]>

这个是我们自己定义的模版,其中actors标签表示的是收件人的地址,需要使用邮件解析类解析,邮件解析类是一个实现AddressResolver接口的类。并且需要在jbpm.cfg.xml中配置,告诉jbpm要使用这个类去解析获取发送邮件的地址。

package com.royzhou.util;

import org.jbpm.mail.AddressResolver;

public class MailAddressResolver implements AddressResolver {

public Object resolveAddress(String actorId) {

return "royzhou1985@foxmail.com";

}

}

下面是jbpm.cfg.xml的配置内容。

class="com.royzhou.util.MailAddressResolver" singleton="true" />

邮箱配置信息如下:

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^^^^^^^^^^^^

打开你的收件箱发现邮件发送成功并且信息都是根据模版生成的。。

至此,我们将流程的节点基本上都过了一遍。。。。 笔记终于写完。。。累就一个字

明天出差。。。。

回来继续。。。。。

分享到:

18e900b8666ce6f233d25ec02f95ee59.png

72dd548719f0ace4d5f9bca64e1d7715.png

2009-07-21 19:56

浏览 5110

评论

2 楼

Storm_Four

2011-06-18

38687d1a1ad71d37c86f287056834d1a.gif 牛叉

1 楼

zhuchao_ko

2011-03-08

38687d1a1ad71d37c86f287056834d1a.gif

Mail这个类写的太牛逼了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值