如何实现 SCA 的异常处理机制

日期: 2008-02-13 作者:赵杰 来源:TechTarget中国

  引言

  当前 Service Component Architecture(SCA)和 Service Data Object(SDO)是构建 Service Oriented Architecture(SOA)系统的两大结构支柱,同时基于 SCA 的服务调用是实现企业业务流程的重要保证。但是,这种服务调用不可能总会成功完成并返回需要的结果,它的分布式和异构的天性使得它特别容易失败。这种失败可以是由服务本身引起的,如输入参数验证失败,或只是服务实现的一个 bug,或通信问题等等。那么如何在 SCA 下有效地、合理地构建异常处理机制对提高系统的稳定性和可靠性是至关重要的。

  SCA 1.0 规范在 SCA 编程模型下定义了两种异常,分别是 ServiceRuntimeException(SRE)用来封装 SCA 组件之间和组件内部发生的系统异常,ServiceBusinessException(SBE)用来封装业务逻辑异常。其中 SBE 可以承载数据对象,这样就能给开发者的异常处理方案提供可决策的异常数据。

  SCA1.0 的介绍

  SCA 是一个可执行的模型,用于将不同的服务集成到一个业务解决方案。它简化了实现业务服务的组件编程模型,这些组件可以使用不同编程语言实现,比如 Java、C++、BPEL 等等。SCA 带来的一些益处主要为:

  松耦合

  组件间的集成不需要知道彼此是基于何种编程语言实现的。在同步、异步情况下,组件都可以被方便的调用。

  可扩展性

  组件可被简单的被替换。既有的服务可被用来创建新的解决方案(自下而上),也可业务建模和开发(自上而下)。

  生产率

  SCA 可让你专心于分析业务逻辑,而不需要过多的去担心系统架构。SCA 简化了所有开发者的使用体验(包括 J2EE 和集成开发者)。

  SCA 1.0 规范中定义了 SCA Domain(SCA 域)、Composite(服务组件复合体)、Component(服务组件)、Binding(绑定)、Reference(引用)、Service(服务)、Property(属性)等概念如图 1 所示

  图 1. SCA 属性的定义
 
  Component 是 SCA 中的基本组成元素和基本构建单位,也是我们具体实现业务逻辑的地方。我们可以把它看成是构建我们应用的积木。我们可以非常容易地把传统的 POJO,无状态会话 BEAN 等包装成 SCA 中的 Component。多个 Component 组合在一起就构成了 Composite,我们可以看成是各个服务组件构成的应用系统或是应用系统的子系统。而多个 Composite 组合在一起就构成了 SCA Domain。 SCA Composite 的主要接口规范是基于 WSDL(Web Service Description Language)的,另外为了给 Java 编程人员提供一个比较直接的接口,SCA 部分组件也提供了 Java 接口。因此,使用 Composite 的客户端可以选择使用 WSDL 接口或 Java 接口。

  SCA 通过 Binding 的概念可以为 Web Service、SCA、JCA、JMS 等服务调用提供的入口,这个入口叫 Service(服务),而 Composite 本身可能也需要调用别的服务,这个调用出口叫 Reference(引用)。无论是接口还是引用,其调用规范都是 WSDL 或 Java 接口。

  绑定(Binding)的介绍

  Binding 是 SCA 中非常重要的概念,它使整合 SCA 封装的异构服务组件成为可能。到目前为止,Web Service Binding、JCA Binding 和 JMS Binding 1.0 规范已经发布,详细文档信息可以从 OSOA 网站获得。下面我们简单介绍一下这三个绑定:

  Web Service Binding 是把一个 SCA 服务组件暴露成为一个 web service 供外部调用,同时也可以调用一个外部以存在的 web service。
  JCA Binding 可以使得 SCA 服务组件与外部企业信息系统(EIS)进行集成,具体是通过与 JCA 资源适配器(JCA Resource Adapter)交互来实现的。
  JMS Binding 可以使得 SCA 服务组件与外部的消息引擎(Messaging System)进行交互,具体来说可以支持队列(Queue)和主题(Topic),其实现基于 JMS 协议。

  SCA1.0 的异常处理机制

  一般开发者对程序都会有异常的捕捉机制,但在捕捉到异常后如何有效的处理确是不容易做到的。实际上我们捕获到的异常,通过 getMessage()、getClass() 等方法只能知道是哪个类发生的异常,还有 JDK 底层抛出的一些异常信息,这些信息对于我们准确的判断异常和分析异常非常困难。所以,如果可以把更多更有效的信息提供给调用者,那么调用者进行异常处理就会更有效更灵活。

  如图 2 所示,SCA 1.0 规范定义了两类异常,分别是 ServiceRuntimeException(SRE)用来封装服务组件运行和远程服务交互发生的系统异常,ServiceBusinessException(SBE)用来封装业务逻辑异常。ServiceUnavailableException 继承了 ServiceRuntimeException(SRE),属于 SRE 的子类,主要用来封装远程调用出现的异常信息。ServiceBusinessException(SBE)不仅可以封装业务逻辑异常,它更重要的特点是可以承载数据对象,开发者不但可以把业务逻辑发生的异常捕获并传回给调用者,而且还可以把更详细的异常信息或者是可预见的异常提示封装成数据对象传回给调用者。这样就可以为调用者进行异常处理决策分析提供更有效的异常数据。

  图 2. SCA 的异常分类
 
  SCA 中,数据对象的载体是 Service Data Object(SDO)。SDO 是一个开放标准数据模型编程 API,允许开发人员在较高的级别方便地操作数据。我们可以把有效的异常信息封装成一个 SDO 或者是嵌套的 SDO,这样调用者通过 SDO 的描述就可以准确的取出需要的异常信息。(SDO 的详细使用方式和 API 的调用请参阅 SDO2.1 规范。)

  下面我们通过一个例子来了解一下 SCA 的异常处理是如何实现的。

  实现 SCA 异常处理的例子-TestErrorHandling

  我们在构建和测试 TestErrorHandling 这个应用程序时候,会用到 Websphere Integration Developer(WID)和 Websphere Process Server(WPS)。

  WID 是基于 RAD(Rational Application Developer)的开发环境,不仅提供了一个使可视的组件与后端实现相分离的层次结构,而且对本地和远程 EIS(企业信息系统)上作为组件的业务流程的开发、调试、装配、部署等各种功能提供了可视化编辑器,这使得各个组件和它们的实现相分离。开发人员无需深入了解各个组件的实现便能使用 WID 开发各种集成应用程序。

  WPS 是由具体的业务整合概念、应用服务器技术以及最新的公开标准而发展而来的下一代业务流程整合服务器。基于现有的公开标准,它实现了简单的编程模型服务组件模型 SCA(Service Component Architecture),调用模型,以及部署模型。

  在 TestErrorHandling 应用程序中,如图 3 所示,我们会构建两个用 Java 实现的 SCA 服务组件。一个是 Caller,其接口为 CallerInterface.wsdl,实现为 CallerImpl。另一个是 Callee,其接口为 CalleeInterface.wsdl,实现为 CalleeImpl。同时让 Caller 组件引用 Callee 组件的 CalleeInterface 接口。当 Caller 组件调用 Callee 组件的时候,Callee 组件会抛出 SBE,其中 SBE 会携带一个 DataObject,Caller 组件会捕捉到 SBE 并且得到其携带的 DataObject。

  图 3. TestErrorHandling 模型
  
  构建步骤

  1.创建模块

  打开 WID,切换到 Business Integration 透视图,新建一个模块,名称为 TestErrorHandling。

  2.创建数据类型。

  通过点击 TestErrorHandling 模块左边的 "+" 号展开,选择 "Data Type",然后通过右键创建一个 Business Object(BO),名称为 FaultBO。如图 4 所示:

  图 4. 创建 BO
 
  3.FaultBO 包含两个元素分别是 ErrorCode 和 ErrorMSG。我们可以通过点击 Business Object 编辑器上方的  按钮来添加一个元素。如图 5 所示:

  图 5. 定义 FaultBO
 
  4.创建接口

  通过点击 TestErrorHandling 模块左边的 "+" 号展开,选择 "Interface",然后通过右键创建两个接口,名称为 CallerInterface 和 CalleeInterface。

  5.CallerInterface 接口包含 send 操作,输入参数是名为 message 的字符串,输出参数是名为 status 的字符串。CalleeInterface 接口包含 receive 操作,输入参数是名为 message 的字符串,输出参数是名为 status 的字符串,Fault 参数是名为 FaultData 的 FaultBO。可以通过点击接口编辑器上方的  按钮来添加一个操作, 按钮来添加一个 Fault。通过  和  分别来添加输入和输出参数。如图 6、图 7 所示:

  图 6. 定义 Caller 接口

 
  图 7. 定义 Callee 接口
 
  创建服务组件。双击打开 TestErrorHandling 模块的图形化编辑器,然后把 Java 组件图标  拖拽到编辑器中即生成一个 Java 服务组件,并把名称改为 Caller,同样再创建另一个 Java 服务组件,命名为 Callee。如图 8 所示:

  图 8. 创建 Caller 和 Callee 服务组件
 
  7.为组件添加接口。单击 Caller 组件,组件上方会出现  按钮,点击并为 Caller 组件选择一个 WSDL 接口,即我们前面定义的 CallerInterface。同样我们为 Callee 组件选择 CalleeInterface。

  8.为 Caller 组件添加引用接口。单击 Caller 组件,组件上方会出现  按钮,点击并为 Caller 组件选择一个 WSDL 接口,即我们前面定义的 CalleeInterface。

  9.添加 Wire

  右击 reference,选择 Wire to Existing 并保存。如图 9 所示:

  图 9. 添加 Reference
 
  10.通过双击上图中的 Callee 组件,WID 会自动生成 Callee 组件实现类的基本框架 CalleeImpl.java。如图 10 所示:

  图 10. Callee 组件的实现类框架
 
  上图中高亮处显示的代码行就是我们可以给 receive 方法添加业务代码的地方。我们让 Callee 的 receive 方法抛出一个 ServiceBusinessException,同时携带我们构造的 FaultBO。

  代码清单 1. CalleeImpl.java

  public String receive(String message) {
  System.out.println("Enter CalleeImpl.receive(String) Method");
  ServiceManager serviceManager = new ServiceManager();
  BOFactory boFactory =
  (BOFactory) serviceManager.locateService("com/ibm/websphere/bo/BOFactory");
  System.out.println("************ BOFactory created ************");
  DataObject faultBO = boFactory.create("http://TestErrorHandling",
  "FaultBO");
  System.out.println("************ FaultBO created ************");
  faultBO.setString("ErrorCode", "1001");
  faultBO.setString("ErrorMSG", "Message Incorrect");
  try {
  @SuppressWarnings("unused")
  int i = 1 / 0;
  } catch (Exception e) {
  ServiceBusinessException sbe = new ServiceBusinessException(faultBO);
  throw sbe;
  }
  System.out.println("Enter CalleeImpl.receive(String) Method");
  return "Success";
  }
 
  11.双击 Caller 组件,生成 Caller 组件实现类的基本框架 CallerImpl.java。我们让 Caller 的 send 方法捕获 ServiceBusinessException,同时得到 FaultBO。

  代码清单 2. CallerImpl.java

  public String send(String message) {
  System.out.println("Enter CallerImpl.send(String) Method");
  String status = null;
  Service service = this.locateService_CalleeInterfacePartner();
  try {
  service.invoke("receive", message);
  status = "Success";
  } catch (ServiceBusinessException sbe) {
  status = "Failed";
  DataObject faultBO = (DataObject) sbe.getData();
  System.out.println("ErrorCode of FaultBO is : "
     + faultBO.getString("ErrorCode"));
  System.out.println("ErrorMSG of FaultBO is : "
     + faultBO.getString("ErrorMSG"));
  } catch (Exception e) {
  e.printStackTrace();
  }
  System.out.println("Exit CallerImpl.send(String) Method");
  return status;
  }
 
  测试步骤

  1.加载 TestErrorHandlingApp 到 Server。如图 11 所示:

  图 11. 加载应用程序
 
  2.右击 TestErrorHandling 模块,选择 Test-〉Test Module。在 Test Module 编辑视图中为 message 参数赋值。如图 12 所示:

  图 12. 启动 Test Module
 
  3.点击  按钮,返回参数 status 的值为 Failed。查看 SystemOut.log 文件,Caller 组件得到了 FaultBO。如图 13 所示:

  图 13. 运行应用程序
 
  通过这个简单例子的构建和测试我们可以感觉到,对于 SCA 异常处理机制的实现还是比较简单。开发人员只需要把有效的异常信息构建成 SDO,然后把 SDO 放到 SBE 中抛出就可以了。当然什么样的信息是有效异常信息,如何安排 SDO 承载异常信息的结构还是需要开发人员花费一定时间来考虑的。这样必然会增加架构设计人员和开发人员的工作量。但是这样的工作量的增加对于增加客户友好度,提高产品容错能力还是有积极作用的。

  JCA Binding 和 Websphere Adapter 对 SCA 异常处理机制的实现

  基于 SCA 1.0 规范对 SCA 异常处理机制的定义,JCA Binding 和 Websphere Adapter 6.1 版本对其进行了支持。

  Websphere Adapter 的简介

  在面向服务的体系结构中,每个事物都是服务,并且服务是使用组件来实现的。如果将此黄金规则应用到企业信息系统 (EIS),则会认识到我们也需要将 EIS 视为黑盒。换句话说,我们需要按调用任何其他组件的方式调用我们的信息系统;这样我们不必处理详细的 EIS 逻辑。那么 Websphere Adapter 产品就是实现这个规则的纽带。

  Websphere Adapter 产品允许服务组件与特定的 EIS 通信。一些与数据库通信,一些与文件系统中的平面文件通信,一些与事务处理系统通信,还有一些与 EIS 中的功能通信等等。它为我们提供了简单而又直接的操作 EIS 的方式。如图 14 所示:

  图 14. Websphere Adapter 的基本结构
 
  对异常处理的支持

  Websphere Adapter 6.1 版本对 SCA 异常处理机制的实现思路与前面阐述的例子是类似的。我们通过图 15 来给大家进行详细的解释。

  图 15. Websphere Adapter 对 SCA 异常处理的实现
 
  我们知道 SCA 服务组件通过 JCA Binding 可以调用 Websphere Adapter 来操作 EIS。当 Websphere Adapter 操作 EIS 时发上了系统异常,比如连接失败等等,Websphere Adapter 会根据这些异常封装成 ResourceException。当 Websphere Adapter 操作 EIS 时发生了业务逻辑异常,比如插入 EIS 的数据重复,EIS 中没有符合查询条件的数据等等,Websphere Adapter 会根据这些异常构造出承载不同 Fault Data 的 SDO,然后把异常信息封装成 FaultException,并且加载构造出的 SDO,其中 FE 是 RE 的子类。无论是 ResourceException 还是 FaultException 最后都会抛出给 JCA Binding。如果 JCA Binding 捕获到的是 ResourceException,那么它就会把 ResourceException 携带的异常信息取出,重新封装成 ServiceRuntimeException 抛给 SCA 服务组件。如果捕获到的是 FaultException,那么它就会把 FaultException 携带的异常信息和数据对象取出,重新封装成 ServiceBusinessException 抛给 SCA 服务组件。

  Websphere Adapter 定义了五种公共的 FaultException,每种 Exception 都有对应的 Fault Business Object。每个 Adapter 又进行了扩展,定义一些符合自身需要的 FaultException 和 Fault Business Object。这些丰富的 Fault Business Object 为开发者提供了详细的异常数据,同时也为决策异常处理流程提供了更好的依据。

  具体的实现示例,本文在此不再阐述。

  总结

  本文首先对 SCA 1.0 规范和绑定规范行了简要介绍,然后介绍了 SCA1.0 对异常处理机制的定义并通过一个简单的 SCA 服务组件调用之间的异常处理例子来详细阐述对 SCA 异常处理机制的实现,最后介绍了一下 Websphere Adapter 6.1 版本对 SCA 异常处理机制的支持。从本文中我们可以了解到,通过 ServiceBusinessException 概念的引入到自定义携带的数据对象,SCA 异常处理机制为开发者在应用异常信息改善异常处理流程发面提供了更大的发挥空间,而 Websphere Adapter 6.1 版本对 SCA 异常处理机制进行的支持,使其应用到企业级应用系统成为可能。

 

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

作者

赵杰
赵杰

相关推荐