【IT168 技术文档】
前言
在任何一个商业系统运行环境中,异常处理无疑都是非常重要的。如何对异常进行处理以避免可能导致的业务数据丢失业务流程混乱是在对系统进行设计和开发时必须要考虑的一个重要问题。
在笔者从事WPS相关的售前工作过程中,发现几乎每位客户都会对WPS如何处理异常以及怎样将业务流程中的异常处理和其他相关业务系统里的异常处理结合起来格外关心。
本文首先将介绍WebSphere Process Server V6.0.2对异常进行捕捉的基本原理和工作机制,然后探讨在业务流程的开发过程中,如何进行合理的异常处理设计。
WPS异常处理机制原理介绍
要想设计出能够合理处理异常的业务流程,首先要了解WPS的异常处理机制。
WPS中的异常分为两类:业务异常(ServerBusinessException)和系统异常(ServiceRuntimeException)。业务异常指出于业务需要通过流程设计主动抛出的异常,系统异常则是在流程实时运行过程中发生的不可预知的异常。
WPS对于异常的处理方式取决与异常的类型以及模块之间的调用方式。
在同步调用(Synchronous invocation)中,调用方和被调用方是在同一个线程中执行,在这种情况下,不管被调用方返回的是业务异常还是系统异常,都能够被调用方捕获。同步调用的情况下产生系统异常,服务器不会产生失败事件(Failed Event)。
在异步调用(Asynchronous invocation)(包括单向调用(One-way operation)、延迟反馈(Deferred response)、回调(Callback)等几种情况),由于调用方和被调用方是在不同的线程中执行,每个线程会有自己的异常捕获机制,因此通常情况下被调用方所抛出的业务异常会被返回给客户端,而系统异常则会送交服务器中的Failed Event Manager处理,不会返回给调用方。但是这种情况也有例外。如果调用方是一个BPEL流程的话,那么被调用方产生的运行时异常也会被返回给调用方。
2. BPEL业务流程中的异常处理
首先,我们在定义流程所实现的接口操作的时候可以定义异常,使得异常可以抛出给流程的调用方。WPS接口中的操作分为两类:单向操作(One-Way Operation)和双向操作(Two-Way Operation)。单向操作只发出调用,不关心调用结果的返回,因此无法在接口上定义异常的抛出。双向操作发出调用之后会等待调用的完成和结果的返回,可以在接口上定义异常的抛出。如下图所示:

图 1. 接口操作上的错误定义
在业务流程(Business Process)中,可以使用错误处理器(Fault Handler)来对异常进行处理。错误处理器可以在Invoke,Scope和Receive三种结点上使用。在Invoke上定义的错误处理器处理此次调用返回的异常;在Scope上定义的错误处理器处理在这个scope里的结点运行期间抛出的错误,在Receive上定义的错误处理器则处理整个业务流程中抛出的错误。
错误处理器对异常的处理是按层次由内向外抛出的。例如如果一个Invoke结点是定义在一个Scope之内的,那么Invoke产生的异常首先由Invoke上定义的错误处理器处理,如果此错误处理器未能捕获或者再次抛出这个异常,那么异常由Scope上定义的错误处理器处理,如果再次抛出,那么由Receive结点上定义的全局错误处理器进行处理。如果异常未能在流程范围能得到处理,可以返回给接口操作的调用方。
业务流程中三种结点上的错误处理器情况分别如下列图形所示:

各种结点上的错误处理器的具体配置如下所示:
图 5.

此处可以选择错误的类型:Built-in和User-defined。Built-in包括一些系统预先定义的常见异常类型,如空指针错误类型等。User-defined指用户自己定义的业务异常类型,这些异常应当在定义接口的时候在方法里予以定义,如图1所示。
在一个错误处理器里,可以添加多个Catch结点去捕获多种不同类型的错误,也可以使用Catch All结点去捕获所有错误。
捕获了错误之后,常见的处理错误办法有:
1)将其再次抛出至外一层异常处理体(如果直至整个流程级都没有相应的异常捕获体,那么流程实例将进入失败状态);
2)启动一个人工任务,发起对于错误的人工干预;
3)启动补偿;
4)调用一个Reply结点,将错误返回(这种情况需要在流程接口上定义错误处理)。
此外,还有两处需要注意的地方:
关于“Continue On Error”
在大多数结点的属性栏的Server页面上,有一个选项叫做“Continue On Error”,如下图所示:

图6. Continue On Error选项
如果选中此选项的话,则一旦此结点出错,流程抛出一个错误并且继续;如果未选中的话,流程会暂停当前活动,为流程管理员创建一个工作项,允许他重新尝试这个结点,如果仍然失败,则流程实例失败。
在流程里可以通过Java Snippet来取得当前流程出错的详情
示例代码如下:
com.ibm.bpe.api.BpelException bpelexception = getCurrentFaultAsException();
QName faultName =
new QName("http://FaultHandlingSampleModule", "JavaSnippetException");
raiseFault(faultName);
3. 人工任务的异常处理
人工任务(Human Task)的异常处理和BPEL业务流程的异常处理有很大不同,这是由人工任务的驱动机制决定的。一个人工任务的生命周期由产生(Create)、启动(Start)、声明(Claim)和完成(Complete)几个动作组成。在一个业务流程中,当流程流转到某个人工结点,工作流引擎会自动产生(Create)和启动(Start)相应的人工任务实例。这种情况下,人工任务在创建和启动时产生的系统异常,会被返回给业务流程。
但是人工任务的声明(Claim)和完成(Complete)则不会由工作流引擎来自动完成,而是必须由客户端(Client)调用WPS提供的API来完成。这种情况下,在声明和完成时发生的异常会被返回给客户端(Client),在业务流程中无法捕获。
查看WPS的API文档,我们可以发现,声明(Claim)和完成(Complete)人工任务的方法允许抛出的异常有CannotCreateWorkItemException, UnexpectedFailureException, java.rmi.RemoteException, javax.ejb.EJBException等多种,每种异常都代表了不同的出错情形,客户端可以根据捕捉到的异常类型去做相应的业务处理。抛出异常后,此人工任务实例进入失败(Failed)状态。
结束语
本文向您介绍了WPS的异常处理机制和一些常见的处理手段。在使用WID来开发业务流程的过程中,可以结合实际业务需要进行详细的异常处理设计。
参考资料
WebSphere Process Server信息中心
http://publib.boulder.ibm.com/infocenter/dmndhelp/v6rxmx/index.jsp
作者介绍
杨娟,IBM软件部售前工程师,主要从事WebSphere Process Server和WebSphere Application Server的售前技术支持工作,联系方式:yangjuan@cn.ibm.com。