dev2dev 首页 > 资源中心 > 技术文章
采用Weblogic Integration 8.1支撑97业务流程的解决方案
编者按:该作品为2004年原创技术文章大奖赛特等奖作品,点击此处查看所有参赛作品和活动详情。 摘要:
本文是在验证系统基础上完成的技术方案总结。该验证系统研究的是利用weblogic Integration 8.1作为业务流程管理平台支撑97业务的可行性,及相关技术细节。验证系统重点解决了三个问题:(1)面向业务用户的流程建模(2)复杂业务流程的表达(3)Integration与业务系统的集成。 注:文中的97系统特指作者公司的97产品。
1. 背景 2. 系统面对的主要问题
2.1 面向业务用户的流程建模
2.2 复杂业务流程的表达
2.3 Integration与业务系统的集成
3. 建设方案
3.1 总体架构
3.2 节点控件的封装
3.2.1 基本架构
3.2.2 流程与tuxedo应用的通信
3.2.3 任务管理
3.3 轻量级的建模工具BMStudio
3.3.1 的体系结构
3.3.2 BMStudio的用户界面
3.3.3 业务节点与控件的映射
3.3.4 转换jpd
3.4 使用消息渠道方式启动流程
3.5 实现异常流程
3.5.1 通过异常路径控制流程的回退。
3.5.2 在封装的业务控件中控制流程跳转和触发异常
3.5.3 一个异常流程的实现的例子
Integration 7中的流程建模工具是作为独立的客户端应用推出的,而Integration 8.1 把这块的功能集成到了workshop中。这一变化其实是值得商榷的。在BEA的设计人员看来,流程建模是应用开发的一部分,其目标用户是IT人员。当企业推出新业务流程时,先由业务专家画出草图,再交开发人员(集成商)建模实现。
我们认为,业务流程建模应该划分为2个层次。底层是IT人员对业务流程实现的建模,他们看到的是细粒度的节点,比如各种同步/异步调用、消息发布/订阅,java代码、应用视图等;上层是业务人员对业务流程的设计,他们看到的是粗粒度的节点,也就是诸如受理、收费、配线这样的业务环节。IT人员通过对细粒度节点的封装、业务接口设计等工作可以实现与粗粒度的业务节点的映射。通过这种映射关系,业务人员设计的流程模型不再是草图,而是自动被转换成底层的实现模型,部署到流程引擎上,支持生产系统。其优点很明显:新产品或新业务可以迅速推向市场,创造效益,提高企业的竞争力。
将workshop作为上层建模工具提供给业务用户并不合适(尽管它是免费的)。虽然我们也尝试使用workshop的扩展包对workshop做一些客户化的工作,但效果不理想。业务用户都比较挑剔,他们需要一个更为简单、易用、有效的建模工具和解决方案。
97的业务流程包括正常流程、异常环节和异常流程(这里的异常指的是业务方面的异常,不是程序级的异常)。其中异常环节和异常流程是比较复杂的。它要求实现任意跳转的功能,包括向前跳转和想后跳转,类似于程序设计中的GOTO。在Integration 7的版本中,这种任意跳转是被支持的,但在8.1中被去掉了,用设计者的话说“it’s very bad”。理论上讲,可以通过复杂的条件、循环等流程组合来实现任意复杂的流程,但这种方式的可操作性比较差。试想一下,一个原本只有十几个业务节点的流程为了支持异常处理,将被设计成为几十个分支,上百个节点的流程。那是多么让人郁闷的事情。
相信每一个程序开发人员都清楚GOTO对于结构化设计的危害。但是,我们可否找到一种方案,既无需GOTO,又能绕开对每一个流程都去做繁琐而复杂的异常流程建模呢?
这里的“集成”指的是基于业务流程的集成(BPI),而不仅仅是应用集成(EAI)。97业务系统构建于BEA中间件tuxedo之上,这使得Integration和97系统之间的集成似乎不该成其为难点,毕竟Weblogic Integration生来为就是解决业务集成问题的,更何况还是自家的产品。然而实际上,Integration的流程在与tuxedo应用的交互方面存在诸多的限制,使得我们在解决流程启动、任务管理甚至底层通信方式等问题上都遇到了不小的困难(参见解决方案中相关章节)。
如图所示,方案包括前后端两部分内容:后端使用workshop预定义97的业务控件。定义97业务控件的实质是对业务环节的实现机制进行封装。其中包括实现与tuxedo应用的通信、对业务系统的任务管理,以及对复杂流程的支持;前端则实现一个轻量级的流程建模工具(暂时称之为BMStudio),主要功能是辅助用户简便、快速地构建企业业务流程。两部分之间通过JPD文件作为数据交换的接口。 
在workshop中封装节点控件其实就是创建一个流程(jpd),然后将流程生成控件。如图所示,流程包括一个条件节点(decision)和三个执行节点(perform)。他们完成如下逻辑:
- Perform1调用97应用中的getEntryRule服务;
- 如果返回“Y”,则进入任务处理分支;
- 如果返回“N”,则走另一分支,什么也不做,流程结束
- 在任务处理分支中,Perform2调用97应用中assignTask服务,派发带有任务标识的工作项。
- 97相关业务系统完成任务后,调用completeTask服务,通过tuxedo Queue向JMS队列转发任务完成消息。
- perform3节点,调用JMS API访问JMS队列,流程被阻塞,直到带有任务标识的消息被捕获。
- 流程向下流转,流程结束。

3.2.2.1 从流程访问tuxedo服务
从流程访问tuxedo服务,相对比较简单,例如,对于weblogic
8.1.1,步骤如下:
- 配置tuxedo服务器端Domain。
*DM_RESOURCES
VERSION=U23
*DM_LOCAL_DOMAINS
TDOM1 GWGRP=DMGRP
TYPE=TDOMAIN
DOMAINID="TDOM1"
DMTLOGDEV="/tuxedo/bms/beatest/TLOG"
AUDITLOG="/tuxedo/bms/beatest/aud"
DMTLOGNAME="DMTLOG_TDOM1"
*DM_REMOTE_DOMAINS
TDOM2 TYPE=TDOMAIN
DOMAINID="TDOM2"
*DM_TDOMAIN
TDOM1 NWADDR="//192.168.100.58:16000"
TDOM2 NWADDR="//192.168.90.80:16000"
*DM_LOCAL_SERVICES
getEntryRule
assignTask
*DM_REMOTE_SERVICES
- weblogicserver中配置WTC
<WTCServer Name="WTCqsample" Targets="cgServer">
<WTCLocalTuxDom AccessPoint="MyLclAccessPt"
AccessPointId="TDOM2" ConnectionPolicy="ON_STARTUP"
Interoperate="Yes"
NWAddr="//192.168.90.80:16000"
Name="WTCLocalTuxDom-1077068834296"/>
<WTCRemoteTuxDom AccessPoint="MyRemoteAccessPt"
AccessPointId="TDOM1" ConnectionPolicy="ON_STARTUP"
LocalAccessPoint="MyLclAccessPt"
NWAddr="//192.168.100.58:16000"
Name="WTCRemoteTuxDom-1077068919812"/>
<WTCImport LocalAccessPoint="MyLclAccessPt"
Name="WTCImport-1077069864359"
RemoteAccessPointList="MyRemoteAccessPt"
RemoteName="FindAsgnFlg" ResourceName="getEntryRule "/>
<WTCImport LocalAccessPoint="MyLclAccessPt"
Name="WTCImport-1077069900000"
RemoteAccessPointList="MyRemoteAccessPt"
RemoteName="AsgnWkItem" ResourceName=" assignTask "/>
</WTCServer>
需要注意的是如果tuxedo是8.0以前的版本,LocalDomain必须配置选项Interoperate="Yes"
- 在节点中通过jatmi API访问tuxedo服务,关于这部分内容,可以参考weblogic
server的sample中的wtc的例子。
- weblogic 8.1.2提供了tuxedo control这一新特性,封装了对tuxedo服务的访问,使我们可以省掉了步骤2和步骤3的工作,只需要点击菜单,进入wizard,创建tuxedo control,然后在节点中调用control的方法就可以了。
3.2.2.2 tuxedo服务访问流程
流程访问tuxedo服务如此容易,让人不禁期待tuxedo服务也可以轻松实现与流程通信。大家都知道,tuxedo服务通过WTC可以调用EJB,而Integration的流程在编译部署后实质上也是以EJB的状态运行。那么,是否tuxedo可以直接访问Integration流程呢?
试验的结果给我们泼了一桶冷水。Integration的流程不是一种普通的EJB,tuxedo或者其它的EJB都无法实现对它的访问(原理尚不清楚,不知道是否处于安全性考虑,希望可以和大家一起探讨)。相关的试验还表明,基于HTTP协议的技术可以访问流程,例如Servlet/ Jsp或者Web Service。不过如果采用tuxedo-web service-integration这种方案的话,先不论它的可行性和效率,本身技术上就比较复杂,代价太高。
最后我们还是选择了JMS作为信息传递的技术通道。WTC提供的tBridge可以把tuxedo Queue中的消息直接转发到weblogic的JMS队列中。在Integration流程中我们可以通过不断访问JMS队列的来获取目标信息。这种方案的好处在于技术难度小,风险低;另一好处在于它正好提供了一种流程阻塞的机制。
下面简要介绍一下实现步骤:
- tuxedo ubb配置中需要增加与queue相关的内容
*RESOURCES
IPCKEY 234567
DOMAINID qsample
MASTER SITE1
MODEL SHM
*MACHINES
ibm44p
LMID = SITE1
TUXDIR ="/tuxedo"
TUXCONFIG = "/tuxedo/bms/beatest/tuxconfig"
TLOGDEVICE ="/tuxedo/bms/beatest/TLOG"
TLOGSIZE=80
APPDIR = "/tuxedo/bms/beatest"
ULOGPFX = "/tuxedo/bms/beatest/ULOG"
MAXWSCLIENTS = 10
*GROUPS
GROUP1 LMID = SITE1 GRPNO = 1
DMGRP LMID=SITE1 GRPNO=10
QUE1 LMID = SITE1 GRPNO = 2
TMSNAME = TMS_QM TMSCOUNT = 2
OPENINFO = "TUXEDO/QM:/tuxedo/bms/beatest/QUE:QSPACE"
QUE2 LMID = SITE1 GRPNO = 20
TMSNAME = TMS_QM TMSCOUNT = 2
OPENINFO = "TUXEDO/QM:/tuxedo/bms/beatest/QUE:QSPACE"
WSLGRP LMID=SITE1 GRPNO = 4
*SERVERS
DEFAULT: CLOPT="-A"
server SRVGRP=GROUP1 SRVID=1
simpserv SRVGRP=GROUP1 SRVID=10
ShTestServ SRVGRP=GROUP1 SRVID=100
DMADM SRVGRP=DMGRP SRVID=10
GWADM SRVGRP=DMGRP SRVID=20
GWTDOMAIN SRVGRP=DMGRP SRVID=30
WSL SRVGRP=WSLGRP SRVID = 1
CLOPT ="-A -- -n //192.168.100.58:12345 -m 5 -M 10 -x 10"
TMQUEUE SRVGRP = QUE1 SRVID = 1 MIN=3
GRACE = 0 RESTART = Y CONV = N MAXGEN=10
CLOPT = "-s QSPACE:TMQUEUE -- "
TMQUEUE SRVGRP = QUE2 SRVID = 1
GRACE = 0 RESTART = Y CONV = N MAXGEN=10
CLOPT = "-s QSPACE:TMQUEUE -- "
*SERVICES
QSPACE AUTOTRAN=N
- 创建tuxedo queue
QSPACE Name QSPACE
Queue Name SENDQ
Queue Name RPLYQ
ERROR Queue ERRQ
这里创建了两个QUEUE,其中RPLYQ是向JMS队列转发任务结束的消息,SENDQ用来向另外的JMS队列转发启动流程的消息(参见对“启动流程”方案的介绍)。 - 在Weblogic Server中配置JMS服务
<JMSServer Name="demoServer" Targets="cgServer">
<JMSQueue JNDIName="demoQueue" Name="demoQueue"/>
<JMSQueue JNDIName="weblogic.jms.Tux2JmsQueue" Name="Tux2JmsQueue"/>
<JMSQueue JNDIName="weblogic.jms.tBerrorQueue" Name="tBerrorQueue"/>
<JMSTopic JNDIName="startProcessTopic" Name="startProcessTopic"/>
</JMSServer>
<JMSConnectionFactory JNDIName="demoFactory" Name="demoFactory"
Targets="cgServer" XAConnectionFactoryEnabled="true"/>
说明:demoQueue:用于接收tuxedo服务向weblogic发送的工作项完成的消息。
Tux2JmsQueue:用于接收启动流程的消息(参见对“启动流程”方案的介绍)。
- 配置WTC tBridge
<WTCImport LocalAccessPoint="MyLclAccessPt"
Name="WTCImport-1077069063640"
RemoteAccessPointList="MyRemoteAccessPt"
RemoteName="myImportedResources" ResourceName="QSPACE"/>
<WTCtBridgeGlobal JmsFactory="weblogic.jms.ConnectionFactory"
JndiFactory="weblogic.jndi.WLInitialContextFactory"
Name="WTCtBridgeGlobal-1077069282421" TuxErrorQueue="ERRQ"
TuxFactory="tuxedo.services.TuxedoConnection" WlsErrorDestination="weblogic.jms.tBerrorQueue"/>
<WTCtBridgeRedirect Direction="TuxQ2JmsQ" Name="TuxQ2JmsQ"
SourceAccessPoint="MyLclAccessPt" SourceName="SENDQ"
SourceQspace="QSPACE"
TargetAccessPoint=""
TargetName="weblogic.jms.Tux2JmsQueue"/>
<WTCtBridgeRedirect Direction="TuxQ2JmsQ" Name="replyQ"
SourceAccessPoint="MyLclAccessPt" SourceName="RPLYQ"
SourceQspace="QSPACE" TargetName="demoQueue"/>
3.2.3.1 派发任务
97流程的任务节点中基本上都是人机交互节点(人工节点),也就使说,完成一个业务节点需要两个步骤,一是向应用系统派发任务;二是派发任务后,阻塞流程,并等待业务系统返回任务结束信息(业务术语称为“回单”)。
在J2EE架构的应用中,可以采用Integration
TASK控件来实现任务派发和结束。业务系统的客户端(WEB应用)通过访问worklist来提取任务和技术任务。然而正如前面提到的困难一样,基于TUXEDO的97系统无法访问worklist,对任务的管理只能采取一种替代方式。
原有的97工作流管理系统中,有一张WORKITEM表,记录了诸如流程实例编号、工作任务编号、当前所在(派发到)的业务环节,完成状态等信息。实现的功能与worklist类似。各业务子系统通过访问该表提取工单,通过的状态信息来回单。在验证系统中,我们沿用了这一设计。把任务列表仍然放在业务系统。
当流程节点派发任务时,根据某种规则生成一个taskid,需要保证这个taskid在所流程派发的任务中都是唯一,同时,我们以它作为一个参数,去调用assignTask服务,assignTask在WORKITEM中插入一条记录。同时关联taskid,作为结束流程时,业务系统与对应流程任务匹配的依据。 3.2.3.2 结束任务
前面已经说过,任务结束的实现机制是通过阻塞访问JMS队列,主动获取消息来实现。那么随之而来的问题是,队列里有很多消息,如何取得我所需要的那条?
可能大家会迅速想到qsession.createReceiver的selector参数,通过这个参数可以选择性地接收消息。但是selector只能对消息头的属性进行过滤,而不能过滤消息体本身。如果使用selector,必须要知道类似于JMSMessageID这样的关键信息。这时候,灵光一闪,我们想到,既然JMS消息是由TUXEDO Queue转发而来,那么,TUXEDO Queue的Message ID会不会就是JMSMessageID呢,如果是,那么我们可以在tuxedo服务调用enqueue方法时,通过约定方式设置Message ID,而在流程中通过这个ID获取消息,不就OK了吗?
试验结果证明,我们这次又是想当然了。TUXEDO
Queue的Message ID和JMSMessageID没有任何关系(其它参数也一样)。这个方案行不通。
最后,我们还是用了比较笨的办法:QBrowser。先对JMS队列中的所有消息做一个遍历,查找是否有内容符合的消息(消息体的内容等于任务编号),找到之后,取得它的JMSMessageID,再用带selector参数createReceiver去接收该该消息。
下面是实现程序的片断:
InitialContext ic = new
InitialContext();
qconFactory = (QueueConnectionFactory)
ic.lookup(JMS_FACTORY);
qcon = qconFactory.createQueueConnection();
qsession = qcon.createQueueSession(false,
QueueSession.AUTO_ACKNOWLEDGE);
queue = (Queue) ic.lookup(queueName);
do{
qBrowser =qsession.createBrowser(queue);
Enumeration enum = qBrowser.getEnumeration();
while(enum.hasMoreElements()){
msgText = (TextMessage)enum.nextElement();
ss = msgText.getText();
if (ss.equals(taskId){
msgId = msgText.getJMSMessageID();
quit = true;
break;
}
}
qBrowser.close();
java.lang.Thread.sleep(100);
i ++;
}while(!quit);
if (quit){
String sel = "JMSMessageID = " + msgId + "";
qreceiver = qsession.createReceiver(queue,sel);
qcon.start();
msgText = (TextMessage)qreceiver.receive();
qcon.stop();
qreceiver.close();
}
下图表达了BMStudio的实现架构
- UI用户界面。程序的主框架。负责创建主窗体、菜单、工具栏、状态栏,动态创建可视化子控件。响应用户操作),完成业务流程设计。
- 数据结构。业务流程(包括相关数据)在内存中的存在模式。
- 持久化对象。采用XML规范的流程定义。以文件形式保存业务流程。同时也是与其它系统流程格式进行转换的中间格式。
- 接口控制。针对具体的外部接口,实现数据转换(如Integration jpd)。

下图是BMStudio的界面。对于业务人员而言,他需要做只是从右下角的业务节点列表中选择一个节点,拖放到中间的设计区域。就这么简单。
可能你已经注意到了,BMStudio非常象workshop。不错,在这个验证系统中,我们在BMStudio的界面和操作方式的实现上主要参照了workshop,这样可以从一定程度上减少与jpd转换的难度。但是需要指出的时,BMStudio除了使用了workshop的一些图标外,并没有从workshop获得其它任何资源。 
在交给业务用户之前,IT人员需要对BMStudio进行一些配置,比如创建业务节点。这个工作的实质是和后台封装的业务控件进行映射。如下图所示,在指定业务节点对应的控件、方法和相关参数后,存盘,一个新的业务节点就出现在界面业务节点列表中。

jpd是integration
8.1采用的流程定义,是一种脚本和JAVA代码的混合格式文件。一般包括如下4部分
- package 指明代码所在的包。
与JAVA中包的概念一致。一般是该文件所在的目录。
- import 引入代码需要用到的外部JAVA包。
与JAVA中的概念一致。一个最简单的JPD一般会包含如下三个包
com.bea.jpd.JpdContext
com.bea.data.RawData
com.bea.xml.XmlObject
- process language
* @jpd:process process::
XML格式的过程定义脚本。其中包括大量的JPD标签,用于定义各种流程节点的类型、名称和方法。
@jpd:xquery prologue::
封装了XQUERY表达式方法。
- JAVA类定义。
流程中的变量和方法的定义。如果引入了控件,则需要做相关的申明和标记。
相比WFMC的XPDL和BPMI的BPML两种流程定义规范,jpd还是过于复杂了。但是还好,它毕竟是一种开放的文本格式,这为我们通过程序方式进行处理提供了可能性。在BMStudio中我们设计了一个转换模块,实现了XML格式的流程定义向jpd的转换。从结果来看,达到了预期的效果。
当然这种转换存在一定的风险和缺陷。首先,无法保证BMStudio构建的流程模型的有效性。当它部署到Integration时,可能会发生错误;其次,这种转换不是双向的,因为BMStudio简化了workshop的功能,BMStudio创建的流程在workshop可以打开,而workshop创建的流程在BMStudio中就可能打不开了。
在前面两部分工作完成后,验证系统还无法运转起来,因为我们还没有考虑如何来启动流程。这里有两个个问题(1)流程一般是由97系统发起(在营业受理完成后),业务系统必须知道在Integration流程引擎之上部署了哪些业务流程;(2)业务系统事先并不知道需要启动哪个流程,只有在营业受理完成后,根据具体的业务参数来决定。
一种简单的方案,是在业务系统中设计一张接口表,用于保存流程与业务的关联信息。在BMStudio中提供相应的访问该表的功能,当流程进行部署的同时,BMStudio向该接口写入相关的信息。对于第二个问题,在尝试了Integration流程的多种启动方式之后,我们发现,采用Message Broker Channel可以实现我们的需求。先建立一个消息代理渠道,让所有流程都在这个渠道上监听消息,由于流程订阅消息的同时可以指定过滤条件,那么只要从业务系统传递过来的消息中带有事先约定的信息,就可以启动我们期望启动的流程了。
似乎可以轻松一下了,但是实际情况是我们又碰到了新的困难。其一,为了使用Message Broker Channel,消息必须是XML格式,而tuxedo queue并不支持这种消息类型;其二,tuxedo queue不能通过WTC向Message Broker
Channel直接转发消息。
最后,迫于无奈,我们采用了一个监听流程作为信息中转,实现过程过程如下图所示:
业务系统调用tuxedo服务,通过TUXEDO QUEUE向JMS QUEUE转发流程启动消息。消息体采用String类型,形式上符合XML格式。
在Integration中,创建一个监听流程(startProcess.jpd),循环访问JMS QUEUE,接收消息。
一旦接收到启动消息,监听流程将消息内同解析为XML对象,通过mb-publish control的publish方法发送给Message Broker Channel。 
下面是相关的实现细节
- 消息代理渠道配置文件demo.channel
<channels xmlns="http://www.bea.com/wli/broker/channelfile"
channelPrefix="/SamplePrefix"
xmlns:eg="http://www.bea.com/wli/eventGenerator"
xmlns:dp="http://www.bea.com/wli/control/dynamicProperties"
xmlns:demo="demo"
xmlns:oagpo="http://www.openapplications.org/003_process_po_007">
<channel name ="Samples" messageType="none">
<channel name ="demoXMLChannel" messageType="xml"
qualifiedMessageType="demo:StartProcess"/>
</channel>
</channels>
- 流程启动消息的XML Schema
<?xml version="1.0" encoding="GBK"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="demo" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="StartProcess">
<xs:annotation>
<xs:documentation>Comment describing your root element</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="id" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
- Message Broker
Control
名称MbXMLPublishCtrl
消息通道channel-name="/SamplePrefix/Samples/demoXMLChannel"
方法:void publish(demo.StartProcessDocument value);
理论上,可以通过循环、条件等控制实现97各种异常业务流程,但这种方式对业务用户而言过于复杂,实际应用中缺乏可操作性。因此我们考虑另一种方案,即把对异常流程的处理封装起来,流程和业务规则分离,异常流程(异常环节)都放在业务系统一端,由开发人员实现,业务分析人员只需要关注正常流程就可以了。
实现异常流程的关键在于流程的回退和跳转。对于回退,我们的基本思路是将业务节点组合到一个节点组中,对这一个节点组加上异常路径(exception
path),当需要回退时,在这个组的级别抛出异常,异常处理节点可以设置异常处理完成以后重试这一段流程逻辑,从而使流程回退。对于跳转,也就使说根据业务规则跳过某些业务节点的执行,其实现已经封装业务控件的流程逻辑中了。
下图是一个简化的异常路径的例子。我们把所有业务节点放到节点组中。对该组建立一个异常路径。异常路径中包含异常处理动作(exception handle)。异常路径的after execute属性设为resume,retry count设为一个比较大的数值(例如32767)。这样。在节点组中的任何一个流程节点都可以通过抛出异常的方法(throw exception)跳出当前正常的流程顺序,进入异常路径,在异常处理完成后,流程又回到节点组的起点再次执行。 
上图是在workshop中所看到的最终流程的设计视图。在BMStudio中,由于解决模式是固定的,异常流程的处理方式也是固定的。因此完全可以把这部分工作对用户透明。也就是说,用户建模时,只关注正常流程,无需考虑异常。BMStudio在把流程定义转换为JPD时,自动地给所有业务节点建组,并加上异常路径,
在前面的方案中已经介绍了,我们把业务节点都封装成为子流程控件,每个子流程都有一个入口节点,它调用业务系统的接口服务getEntryRule,通过业务规则来决定是否向该业务节点派发任务。
在业务控件等待任务返回时,如果从JMS队列中接收到的是业务流程异常的信息,那么它将抛出相应的代码级异常,告诉主流程进入异常处理。
97中的异常流程包括:撤单追单处理、改单追单处理、失败工单处理、局内追单处理、割接追单处理5类。撤单处理比较简单,只需在补偿超作后中止流程即可,其它几类异常处理相对复杂,需要做流程的回退或跳转,但实现方式基本类似,只是补偿处理的内容不同,跳转的环节不同。这里以失败工单处理为例,说明其实现方式:
施工环节触发失败工单处理(工单子系统客户端发起)后,97业务系统后台向工作流程实例发出一个包含失败工单处理的JMS消息。
流程实例的封装节捕获到该消息后,抛出一个失败工单的异常。
流程实例捕获到异常,进入异常路径,开始异常处理动作(调用97系统方法,进行追退单处理,追退单回笼后处理等补偿操作)。
补偿操作完成后,流程回到节点组的第一个环节(一般是营业)重新执行。
流程进入营业节点,在访问97接口方法取得营业节点的入口规则时发现,当前流程处于失败工单处理状态,而且要求定单回到配线而不是营业,于是getEntryRule()返回false,流程跳出营业节点。
同理,流程跳过配线之前的其它环节,最后进入配线。再次派发配线任务。
......
总结:
本文主要探讨了利用weblogic Integration 8.1作为业务流程管理平台支撑97业务的实现方案,重点解决了三个问题:(1)面向业务用户的流程建模(2)复杂业务流程的表达(3)Integration与业务系统的集成。方案中既有用户需求的层次的设计,也有技术细节的实现。内容比较多。虽然可以分为几个主题分别阐述,但为了大家对验证系统有个整体认识,我还是把它们汇总在一篇文章中。
原文出处:http://dev2dev.bea.com.cn/bbs/yuanch/ArticleShow.jsp?Id=52
| 作者简介 |
|
曹云:(dev2dev ID:cxx2003 ) BEA系统中国有限公司售后服务工程师。曾任大唐软件技术有限责任公司高级软件工程师,研发项目经理。 |
作者其它文章
|