作为一个工作流,能进行提醒,是一个基本功能。但是作为一个开源产品,JBPM3似乎做得不好,很有鸡肋的感觉,吃起来不好吃,扔了又可惜。现在把结局方案发过来。不过这里要感谢的javaeye另一位大牛的文章。后面有备注。
1.
<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="" 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>
这是processdefinition.xml
然后是:
<jbpm-configuration>
<string name="jbpm.mail.smtp.host" value="smtp.163.com" />
<bean name="jbpm.mail.address.resolver" class="com.whqhoo.mail.TestMail"
singleton="true" />
<string name="mail.class.name" value="com.whqhoo.utils.Mail" />
<string name="jbpm.mail.from.address" value="[email protected]" />
<string name='resource.mail.properties' value='jbpm.mail.properties' />
</jbpm-configuration>
jbpm.cfg.xml
要新建一个properties
mail.smtp.host=smtp.163.com
mail.smtp.port=25
mail.smtp.user=你的用户名
mail.smtp.password=你的密码
mail.smtp.ssl=true
mail.smtp.auth=true
package com.whqhoo.utils;
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);
}
}
因为在jbpm核心包org.jbpm.mail包中 Mail类 没有对smtp登陆时候有用户名和密码认证的方法。所以,重新写一个类,把相关方法添加进来。并在jbpm.cfg.xml中
<jbpm-configuration>
<string name="mail.class.name" value="com.whqhoo.utils.Mail" />
<string name='resource.mail.properties' value='jbpm.mail.properties' />
</jbpm-configuration>
把properties和重新写的Mail类,注入进去。
然后编写获取收取邮件的类
package com.whqhoo.mail;
import org.jbpm.mail.AddressResolver;
public class TestMail implements AddressResolver {
public Object resolveAddress(String actorId) {
return "[email protected]";
}
}
也要在jbpm.cfg.xml中进行注入
<bean name="jbpm.mail.address.resolver" class="com.whqhoo.mail.TestMail"
singleton="true" />
以上完成后测试类
public class TestMailNode {
public static void main(String[] args) {
ProcessDefinition processDefinition = ProcessDefinition.parseXmlResource("mail/processDefinition.xml");
ProcessInstance processInstance = new ProcessInstance(processDefinition);
processInstance.getContextInstance().setVariable("actorId", "whqhoo");
Token token = processInstance.getRootToken();
token.signal();
System.out.println("end^^^^^^^^^^^^");
}
}
以上实现,可以正常收发邮件,有问题可以留言。请务必检查配置文件是否正确
503错误,及其他错误,均和配置文件有关系。
注:以上jbpm.cfg.xml都是一个文件,下面只是说明该文件中每行代表的意义
感谢royzhou先生的博文
http://royzhou.iteye.com