简介: 自动决策在内容管理系统中变得越来越重要。核心应用逻辑中的外化决策逻辑能够根据动态的业务需求管理和快速修改业务规则。IBM WebSphere ILOG JRules 是一个业务规则管理系统(BRMS),它有许多制作、部署和管理业务规则的功能,管理者可以通过它更好、更快地作出决策。IBM WebSphere ILOG JRules 和 IBM Content Manager Enterprise Edition 的整合扩大了内容管理解决方案在一个组织中更有效管理业务决策的范围。
本文首先阐述了整合 IBM Content Manager Enterprise Edition 与 IBM WebSphere ILOG JRules 的方法。然后概述了事件框架,简单介绍了 ILOG JRules 业务规则管理系统,本文使用一个贷款场景来说明如何开发一个定制的事件处理器从而将 ILOG JRules 整合到一个内容管理应用中。
自动决策在内容管理系统中变得越来越重要。然而,对于不断增加的用例,在一个应用中嵌入决策规则可能并不能满足一个快速发展的业务环境的复杂需求。因此,拥有一个专门的支持业务规则建模、规则执行和规则管理的业务规则管理系统变得非常重要。
IBM WebSphere ILOG JRules 是一个业务规则管理系统(BRMS),它提供支持业务敏捷性和效率的业务规则创建、部署和管理功能。ILOG JRules 和 IBM Content Manager Enterprise Edition Version 8.4.2(下面称为 Content Manager)的整合是基于一个事件框架的。这个整合扩展了 Content Manager 的功能,使之能在一个组织中实现更高效的业务决策管理。
Content Manager 支持一个事件基础架构,它能够整合外部应用。本文阐述了如何开发一个定制的事件处理器,同时该处理器是通过能与 ILOG JRules 交互的感知内容的业务逻辑驱动的。
本文概述了 Content Manager 事件框架,并介绍了 ILOG JRules 业务规则管理系统。然后使用一个示例的贷款申请场景说明如何开发一个定制的整合 ILOG JRules 和 Content Manager 的事件处理器。
图 1 说明了一个支持 Content Manager 和外部应用整合的事件框架的体系结构。
如上图所示,事件框架实现了 3 个主要功能:
自动化业务决策可以用于接受一个贷款申请以支付一个汽车保险赔付。这些决策是一个完整元素的业务操作。IBM WebSphere ILOG JRules Business Rule Management System (BRMS) 能够使用一组面向业务分析人员、解决方案架构师和应用开发人员的工具以灵活和可预见的方式控制自动业务决策。
图 2 说明了 ILOG JRules 的主要组件。
如上图所示,ILOG JRules 组件分成了 3 个方面:
本节将介绍一个示例场景,它将说明在一个业务上下文中如何整合 ILOG JRules 和事件框架。
一个地区银行的按揭部门计划自动化一个贷款申请过程。这个贷款申请过程由三个工作状态组成:SubmitLoan、Approved 和 Rejected。当一个贷款申请提交后,它会到达 SubmitLoan 操作区。如果申请获得批准,那么它就会转到 Approved 操作区。如果被拒绝,它会转到 Rejected 操作区。一个 Rejected 状态的贷款申请可以重新提交到 SubmitLoan 操作区进行重新评估。
ILOG JRules 被整合到 SubmitLoan 操作区以实现自动决策。在贷款申请提交过程中,贷款代理人负责提供诸如贷款号、贷款数额、利率、期限等贷款信息。当该申请到达 SubmitLoan 操作区时,这个贷款信息就被发送到 ILOG JRules 规则引擎进行评估。如果评估通过,这个贷款申请会自动转移到 Approved 操作区。否则,它会被自动转移到 Rejected 操作区。进入 Rejected 操作区的一个贷款申请可以重新发送到 SubmitLoan 操作区。当它的贷款信息更新后,它会被重新评估。当一个贷款申请转到 Approved 或 Rejected 操作区时,规则引擎都会生成和发送电子邮件通知,通知贷款申请相关人关于该笔申请的状态。
上述具有 SubmitLoan、Approved 和 Rejected 操作区的贷款申请流程见图 3 所示。
如图 4 所示,我们定义了三个操作列表(SubmittedWL、ApprovedWL 和 RejectedWL),它们将监控各个操作区的工作项。
Content Manager 中定义了贷款申请处理的 Loan 项目类型。 如图 5 所示,它由以下属性组成:
Library Server Configuration 对话框(图 6)中的 Enable Event Subscription 复选框必须选中,以便激活一个库服务器实例的事件日志功能。在项目类型级别,图 7 显示一个项目类型 Loan 的事件订阅例子。这个项目类型所订阅的事件是 Add Item 和 Update Item 事件。当管理员单击 Event Subscription 页面的 Add 按钮时,页面就会显示一个 Define Event Subscription 对话框。管理员也可以选择 General integration 选项,因为这个场景是与一个通用外部应用有关的。这个 Loan 项目类型的所有文档属性都会被选中,以便在 Add Item 和 Update Item 事件中进行监控。
图 6. Library Server Configuration
图 7. 事件订阅
本文的重点是整合 ILOG JRules 和 Content Manager,以及一个贷款例子的业务规则。这个贷款例子来自于 IBM WebSphere ILOG JRules 信息中心(见 参考资料 中的信息中心链接)的“Getting started”小节。
图 8 显示了贷款例子所使用的两组业务规则:
在图中,ILOG Rule Team Server 的 Explore 选项卡中显示了两组规则。对于本场景,业务规则是通过 Rule Studio 发布到 Rule Team Server 的,并且它们是以一个规则归档文件(jar 格式)部署的。Rule Execution Server 是一个规则运行环境。为了简单起见,我们选择了 Java SE 规则会话类型,并且在一个规则会话中嵌入 Java SE 运行单元。
图 9 说明了一个业务规则是如何表示的。它在 Rule Team Server 的 Compose 选项卡中显示了最小信用评分业务规则的内容。这个规则规定如果借款人的信用评分小于 200,贷款申请就会被拒绝。
本节阐述了创建贷款申请场景所使用的体系架构。这个体系架构整合了 ILOG JRules 和 Content Manager。如图 10 所示,这个体系架构由三个部分组成:
图 10. Content Manager / ILOG 整合体系架构
下面概括了一个贷款申请场景在整合体系架构中是如何流转的。
一个定制的事件处理器的基本功能是使用 JMS 队列中的事件消息,然后相应地与外部应用进行交互。对于本文的场景,这个事件处理器必须连接到一个 Content Manager 服务器,查询事件消息中所引用的项目的文档属性。接下来,处理器会创建一个规则会话,然后发送一个请求到 ILOG JRules 规则引擎,以评估贷款申请。然后这个事件处理器会使用 JavaMail API 生成发送到接收人的电子邮件通知。
下载 示例程序,它定义了一个支持本文的场景所描述的定制的事件处理器。这个定制的事件处理器是一个名为 myEventHandler 的 JMS 应用。它使用一个异步消息发送机制。它实现了一个消息监听器,这个监听器可以在新消息到达 JMS 队列时接收这些新消息。
清单 1 显示了 myEventHandler 示例程序的总体结构。下面是关于这个程序功能的总体描述:
myEventHandler
类实现了两个 JSM 监听器:
javax.jms.MessageListener
接口的 onMessage
方法负责监听 JMS 队列。 javax.jms.ExceptionListener
接口的 onException
负责处理 JMS 异常。 myContentHandler
类扩展了 SAX API 的 DefaultHandler
类,它负责解析事件消息。 myErrorHandler
类实现了 SAX API 的 ErrorHandler
接口。 sendMail
负责创建电子邮件并使用 JavaMail API 将通知发送给接收者。它是在接收到一个事件消息时由函数 onMessage
调用的。 executeILOGRules
将一个请求发送到 ILOG JRules 规则引擎再执行规则。这个规则引擎会评估贷款申请,然后返回响应给调用者。 myEventHandler
类初始化时,函数 waitForQUIT
就会被调用。它会提示用户执行 quit
命令。当接收到一个 quit
命令时,myEventHandler
类就会退出。 // JMS API import javax.jms.*; // JNDI API import javax.naming.*; // Java IO and utility import java.io.*; import java.util.*; // SAX abd XML parsing import org.xml.sax.*; import org.xml.sax.helpers.*; // JavaMail API import javax.mail.*; import javax.mail.internet.*; // CM API import com.ibm.mm.sdk.server.*; import com.ibm.mm.sdk.common.*; // ILOG API import ilog.rules.res.session.*; import ilog.rules.res.model.*; import ilog.rules.res.session.ruleset.*; public class myEventHandler extends Thread implements javax.jms.MessageListener, javax.jms.ExceptionListener { static class myContentHandler extends DefaultHandler { // methods in the myContentHandler class } static class myErrorHandler implements ErrorHandler { // methods in the myErrorHandler } public void run() { this.waitForQUIT(); } private void waitForQUIT() throws Throwable { // prompt for the QUIT command to exit } public myEventHandler(String database, String userid, String pw) throws Throwable { // set up JMS connection // initialize SAX parser // start the thread for waiting the QUIT command to exit } public static void main(String[] argv) { // start the myEventHandler instance myEventHandler eh = new myEventHandler(argv[0], argv[1], argv[2]); } public void onMessage(javax.jms.Message message) { // listen to the JMS queue // retrieve a JMS message // parse the JMS message to obtain the event data // process the event data // compose an e-mail // call the sendMail function to send out an e-mail notification } public void onException(JMSException exc) { // print the error message when a JMS exception occurs } public void sendMail(String mailhost, String from, String[] to, String subject, String text) { // send an e-mail notification to the claim reviewers } public IlrSessionResponse executeILOGRules(String firstName, String lastName, int loanAmount, int duration, float interestRate, int creditScore, int yearlyIncome) { // send a request to ILOG JRules rule engine for rule execution // an IlrSessionResponse object is returned with the evaluation result } } |
文章的下面几个小节更详细地检查了示例的一些主要部分:
清单 2 显示了 myEventHandler 示例程序中与一个 JMS 队列建立连接的一部分代码。
首先,这个程序通过查找上下文对象获得一个指定名称的队列连接工厂。其次,它在队列连接中创建一个队列会话,并通过查找上下文对象获得一个指定名称的队列。然后它会为一个特定的队列创建一个作为消息接收的队列接收器。这个队列接收器会使用一个消息选择器 APPLICATION = 'none'
来监听队列,这表示数据来自于一般整合。JMS 队列中只有那些带有消息属性 APPLICATION
且属性值为 'none'
的消息会被查询到。
当队列接收器创建后,这个程序会在队列接收器中创建消息监听器。而异常监听器则是在队列连接中创建。在开始连接 JMS 之前,这个程序会执行另外两个任务:
最后一步是启动 JMS 连接。在 JMS 连接建立后,onMessage
消息监听器和 onException
异常监听器可以接收来自于 JMS 队列的输入消息。
// obtain the queue connection factory factory = (QueueConnectionFactory)ctx.lookup(_qcf_name); // create a queue connection connection = factory.createQueueConnection(); System.out.println("Queue connection created"); // create a queue session qSession = connection.createQueueSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE); System.out.println("Queue session created"); // create a queue testQueue = (javax.jms.Queue)ctx.lookup(_queue_name); System.out.println("Queue = [" + _queue_name + "]"); // create a consumer listening to the specified queue // for message property APPLICATION = 'none' (general integration) qReceiver = (QueueReceiver)qSession.createConsumer(testQueue, "APPLICATION = 'none'"); // set the message listener qReceiver.setMessageListener(this); // set the exception listener connection.setExceptionListener(this); // initialize the SAX parser try { _parser = initParser(_dh); } catch (SAXException se) { System.out.println("SAXException - " + se.getMessage()); throw se; } // connect to the Content Manager dsICM = new DKDatastoreICM(); dsICM.connect(database, userid, pw, ""); System.out.println("datastore connected."); // start the JMS connection connection.start(); System.out.println("Queue connection started");
在 JMS 连接启动后,onMessage
消息监听器就能够以先进/先出的方式从 JMS 队列查询消息。一个 JMS 消息首先会被强制转换成一个 TextMessage
对象。
清单 3 显示了 myEventHandler 示例程序中用于查询事件数据的一部分程序。这个程序能够从 TextMessage
对象查询到消息字符串以及下面六个消息属性:
DATABASE
是生成事件的 Content Manager 服务器名。TYPE
是事件的类型(例如,"item-create"
)。LAUNCH
表示这个消息是否请求运行一个工作流。这个属性的值可能是 "true"
或 "false"
。对于一般整合,这个值是 "false"
。ID
是事件的标识符(例如, "A1001001A10B19B12751I284680000000000000000225000"
)。APPLICATION
是与一个工作流运行相关的应用。对于与 FileNet Business Process Manager (BPM) 整合的过程,这个值是 "BPM"
。对于一般整合,这个值是 "none"
。COUNT
表示事件中包含了多少数据元素。如果事件的长度小于或等于 1024,那么事件中只有一个上下文数据元素。否则,如果计数大于 1,那么定制的事件处理器需要将多个上下文数据元素连接在一起。接下来,这个程序会解析消息字符串,这个字符串是用一种通用基础事件(CBE)格式表示的。下面是用于将 CBD 格式化的消息字符串的信息传递到程序的变量:
strGlobalInstanceId
是事件的全局实例 ID,(例如, "A1001001A10B19B12751I284680000000000000000225000"
,就是相同的消息 ID)。 strReturnMsg
包含了来自于 Content Manager 内容知识库的事件数据。strReturnTime
是 GMT 表示的事件创建时间(例如, "2010-03-19T01:03:11.256Z"
)。 strApplication
是生成事件的应用名称(例如,"Content Manager Event Monitor"
). strComponent
是生成事件的组件名称(例如,"Content Manager 8.4.02.000"
)。 strExecutionEnvironment
表示执行环境的操作系统和架构(例如,"Windows XP[x86]"
)。 strLocation
是事件监视器的主机名和 IP 地址(例如,"myhost/1.11.22.33"
)。 strSubComponent
是子组件的名称(例如,"Event Monitor"
)。 // cast the message to the TextMessage object msg = (TextMessage) message; // retrieve the raw string from a JMS message rawString = msg.getText(); System.out.println("Reading message: " + rawString); // retrieve the message properties from a JMS message msgDatabase = msg.getStringProperty("DATABASE"); msgType = msg.getStringProperty("TYPE"); msgLaunch = msg.getStringProperty("LAUNCH"); msgID = msg.getStringProperty("ID"); msgApplication = msg.getStringProperty("APPLICATION"); msgCount = msg.getStringProperty("COUNT"); // create an input source from the raw string ByteArrayInputStream bais = new ByteArrayInputStream (rawString.getBytes("UTF-8")); InputSource is = new InputSource(bais); bais.close(); // parse the string try { _parser.parse(is); } catch (SAXParseException se) { System.out.println("Encountered a SAX parser error" + " - " + se.getMessage()); se.printStackTrace(); throw se; } // retrieve the information from a CBE-formatted string strGlobalInstanceId = ((myContentHandler)_dh).getGlobalInstanceId(); strReturnMsg = ((myContentHandler)_dh).getReturnMsg(); strReturnTime = ((myContentHandler)_dh).getReturnTime(); strApplication = ((myContentHandler)_dh).getApplication(); strComponent = ((myContentHandler)_dh).getComponent(); strExecutionEnvironment = ((myContentHandler)_dh).getExecutionEnvironment(); strLocation = ((myContentHandler)_dh).getLocation(); strSubComponent = ((myContentHandler)_dh).getSubComponent(); |
清单 4 显示了 myEventHandler 程序中解析从消息字符串查询的事件数据的一部分程序。这些代码能从事件数据获取 PID
字符串和 ITEMTYPE
名称。PID
字符串和 ITEMTYPE
名称在后面会用于查询内容数据和创建电子邮件通知。
StringTokenizer
对象是使用事件数据和分隔符 ";"
实例化的。其中,一个 while
循环会遍历所有标识符,如果遇到 "ICMEMEND"
或遍历完所有标识符时,循环结束。每一个标识符都是用一个 3 元组元素 <tag>
、=
和 <value>
表示的。带有 ITEMTYPE
标签的标识符包含了事件数据所引用的文档的持久化 ID 字符串。
// Use the StringTokenizer to parse the event message StringTokenizer tokenizer = new StringTokenizer(strReturnMsg, ";"); // variable for PID String pid = ""; // variable for itemtype String itemtype = ""; String strPart = ""; int pos = 0; String tagPart = ""; // retrieve pid and itemtype from the event message while (true) { strPart = tokenizer.nextToken(); if (strPart.equalsIgnoreCase("ICMEMEND") || strPart == null || strPart.equals("")) break; pos = strPart.indexOf('='); tagPart = ""; if (pos > 0) { tagPart = strPart.substring(0, pos); } else continue; if (tagPart.equalsIgnoreCase("ITEMTYPE")) { pos = strPart.indexOf('='); if (pos > 0) { itemtype = strPart.substring(pos + 1); } } else { if (tagPart.equalsIgnoreCase("PID")) { pos = strPart.indexOf('='); if (pos > 0) { pid = strPart.substring(pos + 1); } } } } // end while |
通过指定从事件数据查询到的 PID 字符串,我们就能从 Content Manager 知识库中查询到文档元数据库。清单 5 显示了 myEventHandler 示例程序中从一个 Content Manager 服务器查询一个动态数据对象(DDO 对象)及其属性的一部分代码。一个查询调用能够为 DDO 对象填充它的属性值。
然后,下面这些属性会被查询到:
InterestRate
是贷款利率(例如,"0.05"
)。 FirstName
是贷款人的名字。LastName
是贷款人的姓。LoanAmount
是贷款数额(例如,"500000"
)。Duration
是以月为单位的贷款期限。CreditScore
是申请人的信用评分(例如,"310"
)。YearlyIncome
是申请人的年收入。Notification
是包含一组电子邮件地址的子组件,它有一个记录接收者电子邮件的属性 EMailAddress
(例如,"[email protected]"
)。DDO 对象的属性值在后面将用于创建一个电子邮件通知。
// retrieve the DDO object with the pid string DKDDO ddo = (DKDDO)dsICM.createDDO(pid); ddo.retrieve(); // retrieve the LoanNumber attribute short dataId = (short)ddo.dataId("LoanNumber"); String loanId = (String)ddo.getData(dataId); // retrieve the InterestRate attribute dataId = (short)ddo.dataId("InterestRate"); float interestRate = ((java.math.BigDecimal) (ddo.getData(dataId))).floatValue(); // retrieve the FirstName attribute dataId = (short)ddo.dataId("FirstName"); String firstName = (String)ddo.getData(dataId); // retrieve the LastName attribute dataId = (short)ddo.dataId("LastName"); String lastName = (String)ddo.getData(dataId); // retrieve the LoanAmount attribute dataId = (short)ddo.dataId("LoanAmount"); int loanAmount = ((Integer)(ddo.getData(dataId))).intValue(); // retrieve the Duration attribute dataId = (short)ddo.dataId("Duration"); short duration = ((Short)(ddo.getData(dataId))).shortValue(); // retrieve the CreditScore attribute dataId = (short)ddo.dataId("CreditScore"); short creditScore = ((Short)(ddo.getData(dataId))).shortValue(); // retrieve the YearlyIncome attribute dataId = (short)ddo.dataId("YearlyIncome"); int yearlyIncome = ((Integer)(ddo.getData(dataId))).intValue(); // retrieve the Notification component DKChildCollection notification = (DKChildCollection) ddo.getData( (short)ddo.dataId(DKConstant.DK_CM_NAMESPACE_CHILD, "Notification")); dkIterator iterNotification = notification.createIterator(); int count = notification.cardinality(); // variable for Notification String[] notificationList = new String[count]; int index = -1; // construct the array of e-mail addresses while (iterNotification.more()) { DKDDO ddoEmail = (DKDDO) iterNotification.next(); ddoEmail.retrieve(); dataId = (short) ddoEmail.dataId("EMailAddress"); String email = (String) ddoEmail.getData(dataId); if (email == null || email.trim().equals("")) continue; else { index++; notificationList[index] = email.trim(); } } |
因为整合体系结构将决策交由一个 ILOG JRules 规则引擎执行,这个定制的事件处理器将用于创建一个 ILOG JRules 连接会话。接着,贷款信息会被传递到规则引擎进行评估。然后评估响应会返回给定制的事件处理器以便执行更进一步处理。
清单 6 显示了 myEventHandler 示例程序中包含执行规则的详细步骤的一部分代码。总而言之,这部分代码执行了以下操作:
"/{RuleApp name}[/{version}]/{ruleset name}[/{version}]"
。borrower
和 loan
输入参数。 // create a J2SE session IlrSessionFactory factory = new IlrJ2SESessionFactory(); IlrStatelessSession session = factory.createStatelessSession(); // create a session request IlrSessionRequest sessionRequest = factory.createRequest(); // The rule path is composed of: // /{RuleApp name}[/{version}]/{ruleset name}[/{version}] // // Note that the rule archive is deployed in the file system // under the res_data subdirectory. String rulesetpath = "/miniloanruleapp/1.0/miniloanrules/1.0"; sessionRequest.setRulesetPath(IlrPath.parsePath(rulesetpath)); // ensure correct version of the ruleset is taken in account sessionRequest.setForceUptodate(true); sessionRequest.setTraceEnabled(true); sessionRequest.getTraceFilter().setInfoAllFilters(true); // set the input parameters for the execution of the rules Map inputParameters = new HashMap (); // miniloan.Borrower borrower = new miniloan.Borrower("Tom", 500, 50000); // This expression sets the input parameter to a borrower named Tom // with a credit score of 500 and yearly income of 50000. miniloan.Borrower borrower = new miniloan.Borrower(lastName+", "+firstName, creditScore, yearlyIncome); // miniloan.Loan loan = new miniloan.Loan(500000, 240, 0.05); // This expression creates a new loan with an amount of 500000, // a duration of 240 months, and an interest rate of 5%. miniloan.Loan loan = new miniloan.Loan(loanAmount, duration, interestRate); inputParameters.put("borrower", borrower); inputParameters.put("loan", loan); sessionRequest.setInputParameters(inputParameters); // execute the rules IlrSessionResponse sessionResponse = session.execute(sessionRequest); return sessionResponse; |
清单 7 显示了 myEventHandler 示例程序中选择贷款过程中将贷款申请从 SubmitLoan 操作区向前移动的正确路径的一部分代码。如果贷款被批准,它会从 SubmitLoan 操作区移动到 Approved 操作区。如果贷款被拒绝了,它会从 SubmitLoan 操作区移动到 Rejected 操作区。
// Locate the workpackage referenced by the pid string String[] wpList = drICM.listWorkPackagePidStringsWithItem(pid); for (int i = 0; i < wpList.length; i++) { if ((drICM.retrieveWorkPackage(wpList[i], true)) .getWorkNodeName().equalsIgnoreCase("SubmitLoan")) { if (approved) { // Advance the workpackage to the "Approved" work basket, // if the workpackage is located at the "SubmitLoan" work basket // and approved = true. drICM.continueProcess(wpList[i], "Approve", "ICMADMIN"); } else { // Advance the workpackage to the "Rejected" work basket, // if the workpackage is located at the "SubmitLoan" work basket // and approved = false. drICM.continueProcess(wpList[i], "Reject", "ICMADMIN"); } ... } ... } |
清单 8 显示了 myEventHandler 示例程序中使用 JavaMail API 通过简单邮件传输协议(SMTP)发送电子邮件的一部分代码,并显示了程序 sendMail
函数。首先,要指定一个 SMTP 服务器名,并实例化一个会话对象。其次,设置发件人地址和收件人地址数组。这个程序还设置了电子邮件标题、邮件程序和发送日期。最后,程序调用函数 Transport.send
将电子邮件发送到指定的 SMTP 服务器,由服务器将电子邮件发送给接收者。
Properties props = System.getProperties(); // use SMTP if (mailhost != null) props.put("mail.smtp.host", mailhost); // get a Session object javax.mail.Session session = javax.mail.Session.getInstance(props, null); if (debug) session.setDebug(true); // construct the message javax.mail.Message msg = new MimeMessage(session); // set From address if (from != null) msg.setFrom(new InternetAddress(from)); else msg.setFrom(); InternetAddress[] toAddresses = new InternetAddress[to.length]; for (int i = 0; i < to.length; i++) { toAddresses[i] = new InternetAddress(to[i]); } // set To address msg.setRecipients(javax.mail.Message.RecipientType.TO, toAddresses); // optional if (cc != null) msg.setRecipients(javax.mail.Message.RecipientType.CC, InternetAddress.parse(cc, false)); if (bcc != null) msg.setRecipients(javax.mail.Message.RecipientType.BCC, InternetAddress.parse(bcc, false)); // set Subject msg.setSubject(subject); // set e-mail text msg.setText(text); msg.setHeader("X-Mailer", mailer); msg.setSentDate(new Date()); // send out the e-mail Transport.send(msg); |
本节将通过循序渐进的方式介绍一个特定贷款申请例子来演示示例程序的功能,以及 Content Manager 和 ILOG 之间的整合。
这个例子是从一位贷款代理人创建一个贷款申请文档开始的。文档的创建触发了一个项目创建事件,它通过一个 JMS 队列从事件监听器流到定制的事件处理器。如图 11 所示,这个定制的事件处理器会通过 ILOG JRules 规则引擎决定是否要批准或拒绝这个贷款申请,然后这个事件处理器会根据它被批准或拒绝来继续在贷款过程中流转这个贷款申请,并且发送恰当的电子邮件通知给接收者。
当贷款代理人为他的客户提交了一个贷款申请后,这个提交操作会自动创建一个事件,这个事件会触发定制的事件处理器来处理这个申请。图 12 描述一个完整的输入界面,其中贷款代理人可以输入以下信息:
在这个特殊的案例中,根据 ILOG JRules 规则引擎的评估响应,这个贷款申请被拒绝了,因为:
结果,定制的事件处理器会将贷款申请从 SubmitLoan 操作区移到 Rejected 操作区。图 13 显示 RejectedWL 工作列表现在包含了这个贷款的贷款申请信息。
图 14 是一个事件通知例子,在这里它是由定制的事件处理器发送的电子邮件。这个事件通知包含了下面的信息:
IBM Content Manager Enterprise Edition 支持能整合外部应用的事件基础架构。本文描述了一个场景和一个定制的事件处理器的设计,这个定制的事件处理器整合了 IBM WebSphere ILOG JRules 和 Content Manager。在 下载 小节中提供的示例代码演示了 Content Manager 和 ILOG JRules 之间通过定制的事件处理器实现的交互。通过在快速变化环境中管理业务规则的功能,解决方案开发人员能够在企业内容管理领域开发更高效的业务应用。
本文样例程序 | myEventHandler.zip | 10KB | HTTP |
学习
原文:http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-1005ilogjrulescontentmanager/index.html?ca=drs-