深入了解WPS中的业务对象Business Object

来源:百度文库 编辑:神马文学网 时间:2024/04/30 11:32:10

文档选项

将此页作为电子邮件发送

样例代码
拓展 Tomcat 应用

下载 IBM 开源 J2EE 应用服务器 WAS CE 新版本 V1.1
南俊杰 , IBM中国研发中心
张彰 , IBM中国研发中心
2006 年 1 月 20 日
通过本文读者将了解业务对象与服务数据对象(SDO)的概念,二者之间的区别,以及运行原理和实现方法,并通过一个实际的例子来掌握其具体应用。
IBM刚刚推出的WPS (WebSphere Process Server)产品, 主要用于企业业务整合,业务整合又包括服务整合和数据整合。WPS中的SCA(Service Component Architecture)组件用于服务整合(本系列安排有专门章节介绍),而BOF(Business Object Framework)组件就是用于业务数据整合(本章介绍)。在WPS中,业务数据在服务之间的流动,WPS用BPEL(Business Process Execution Language)的BPC(Business Process Choreographer)组件来管理和执行(有专门章节介绍)各种服务并串连其成为一个整体。本章所介绍的BO(Business Object)组件描述了业务数据的结构并提供了一系列的服务使业务数据可以在服务之间传输、转换和映射。SOA(Service Orient Architecture)的号角很早就已经吹起了,如果说EMF(Eclipse Model Framework)是对SOA一个响应,那WPS则是对SOA的全面的拥抱,现在我们可以部署一个在SOA标准基础上的整合应用程序到WPS上。很多人相信SOA就是替代面向对象编程的下一代编程模型。让我们从了解BOF开始,通过本文读者将了解业务对象与服务数据对象(SDO)的概念,二者之间的区别,以及运行原理和实现方法,并通过一个实际的例子来掌握其具体应用。





回页首
WPS(WebSphere Process Server)是一个从企业业务整合概念,应用服务器技术以及最新的开放标准中发展出来的下一代企业应用整合服务器。WPS支持SOA的架构,是一个需要整合使用不同技术的企业应用程序的理想平台。使用WebsphereIntegration Developer 工具可以轻而易举地使用很简单的整合机制创建出企业整合解决方案。
如上所述,WPS是用于企业的业务整合,而业务整合的关键是数据整合。BOF就是设计用来做数据整合的。
分布在不同的应用程序中的数据结构差异巨大。这些差异各自有各自的存在的理由,应用程序构建在上面,已经运行很久,很难改变。把他们整合起来,绝非易事。而且,面向服务的架构又要求数据通用,能被每个服务所理解,可靠性要强。我们把一些要求罗列一下:
灵活,强大,能表达任意的数据结构 自解释,数据能告诉服务自身的结构 自恢复,数据能记忆自己被更改的状况 容易传输,数据需要在各个服务之间流动
IBM和Bea一起制定的SDO(Service Data Object)规范可以满足以上要求。目前SDO作为WebSphere Application Server的一部分已经集成在WPS中,它提供了一个简化了的J2EE数据应用开发的模型,SDO的实现包含在EMF中。EMF是构建数据模型的工具。可以把SDO理解为EMF所建的一个模型。EMF在WPS产品中作用巨大。比如SCA的数据模型就是使用EMF建立。数据模型一旦建立,运行时和可视化工具使用同一套数据模型,有效的保证了数据的一致性。这一点在BO的设计工具和运行时里也有所体现。
SDO作为一个规范,界定了SDO的数据模型,并没有提供相关的服务来创建SDO。 从SDO的规范里我们可以看到DataObject把自身的创建交给了DataGraph,DataGraph把创建交给了Mediator(比如JDBCMediator或XMLMediator等)。交给Mediator后,就得期待各数据厂商的实现了。
Business Object Framework在WPS中,作为SDO的一种增强是建立在SDO的EMF实现之上的,并且由于它是SOA的一部分而成为了WPS的核心组建之一。BOF的数据模型直接使用SDO。此外BOF还提供一些服务来创建、操纵Business Object以及Business Graph。
一个Business Object(BO)是一组属性的集合,用来表达一个业务实体、一个对数据的操作和处理数据的流程。整合应用程序的组件则使用BO来交换数据和触发事件。




回页首
SDO规范的最高版本是2.0。之前的版本是1.0。SDO 1.0在EMF中有完整的实现。SDO 2.0 在EMF中的实现还不完整。因此有必要两者都了解一下。
了解更多细节解请参阅SDO 1.0 和2.0规范 。
这两个模型都列在下面。读者先看一下。


SDO里主要有三个概念:DataMediatorService(SDO 1.0)或DataAccessService,DataGraph和DataObject。
在SDO 1.0中的DataMediatorService,到SDO 2.0变成了DataAccessService。
DataMediatorService在SDO 1.0中定义为一个java class。这个java class提供API去从数据源加载DataGraph,并可以把DataGraph存储到数据源里去。这里"数据源"是一个宽泛的定义,比如,如果数据源是一个XML文件,那DataMediatorService就需要把数据从XML文件读出,生成一个DataGraph返还用户,在用户修改过提交后,DataMediatorService能把DataGraph存入一个XML文件;如果数据源是一个JDBC数据源,那DataMediatorService就需要在数据库中把数据读出,生成DataGraph返回给用户,在用户做了一番修改提交给DataMediatorService后,能把用户修改过的DataGraph存到数据库中。在存储过程中,由于ChangeSummary里包含了用户修改的情况,DataMediatorService有能力根据ChangeSummary进行存储。如果用户根本没改,DataMediatorService可以什么都不做。DataMediatorService以无连接的方式操作数据源。
DataAccessService在SDO 2.0中定义为一个组件。这个组件的功能和SDO 1.0中DataMediatorService一致,但范围广了些。比如SessionBean,WebService尽管不是一个java class,也可以作为DataAccessService出现。
DataGraph里包含两个东西,一个是DataObject,一个是ChangeSummary。DataObject里是具体的数据,DataObject提供各种操纵数据的API。ChangeSummary记录数据的改动并提供API让调用者知道都有哪些改动。
在SDO 1.0中,DataGraph由DataMediatorService创建。而在SDO 2.0中,DataAccessService创建的是DataObject。读者可以思考一下这个改变的利弊。这里不打算做更深入的探讨。
另外较之于SDO 1.0,SDO 2.0还提供了一些接口和帮助类:
DataFactory - 创建DataObject。 TypeHelper - 查找,定义新的DataObject类型。 CopyHelper - DataObject的拷贝,分深拷贝和浅拷贝。 EqualityHelper - DataObject的比较,分深比较和浅比较。 XMLHelper - DataObject的序列化 XMLDocument -DataObject的序列化 XSDHelper - 创建额外信息如果DataObject类型是XSD类型。 DataHelper - 提供DataObject使用的一些数据。 HelperProvider - 提供上面的帮助类。帮助帮助类的帮助类。
这些接口或帮助类在EMF的SDO实现中还没完全实现。但在BOF中会看到一些几乎同名的服务,这些服务实质上这些接口和帮助类的实现。因此这里不做深入探讨。
下面是一个简单的例子。在这个例子里,方法createDataGraph担当DataAccessService的角色(没实现save),负责创建一个DataGraph。之后我们利用创建出的DataGraph,探讨SDO的以下性质:
DataGraph, DataObject和ChangeSummary的关系。 ChangeSummary的使用。 DataObject操作数据的API。
这个DataGraph有一个根DataObject,类型为Employee。下图是Employee的数据结构。

Employee的数据结构比较简单,因为这里不打算讨论SDO对XPath的支持。希望读者能修改这个例子,去学习SDO更多的特性。具体的代码见资源列表。
01 DataGraph dataGraph = createDataGraph(); // beginLogging tell ChangeSummary to record changes. 02 dataGraph.getChangeSummary().beginLogging(); 03 DataObject employee = dataGraph.createRootObject( "http://bof.sample.sdo/Employee", "Employee"); // Set some values 04 employee.setString("name", "mike"); 05 employee.setInt("sn", 1000000); 06 employee.setString("manager", "Jone"); 07 for (int i = 0; i < 3; i++) { 08 Object obj = employee.get(i); 09 System.out.println(obj); 10 } // Another method to get ChangeSummary. 11 ChangeSummary changeSummary = employee.getDataGraph() .getChangeSummary(); // endLogging tell ChangeSummary to stop record changes 12 changeSummary.endLogging(); 13 List changedList = changeSummary.getChangedDataObjects(); // Check change summary. 14 Iterator iterator = changedList.iterator(); 15 while (iterator.hasNext()) { 16 DataObject changedObject = (DataObject) iterator.next(); 17 String typeName = changedObject.getType().getName(); 18 if (changeSummary.isCreated(changedObject)) { 19 System.out.println(typeName + " is created."); 20 } else if (changeSummary.isDeleted(changedObject)) { 21 System.out.println(typeName + " is deleted."); 22 } else {// Do something else 22 } 23 }
第1行用DataAccessService创建了一个DataGraph。这里的DataAccessService就是方法createDataGraph了。方法createDataGraph使用了EMF的一些API。不感兴趣的读者可以跳过。但是鉴于SDO实现和EMF的密切关系,以及EMF技术本身的魅力,建议读者也认真学习一下EMF。
第2行打开ChangeSummary的logging开关。ChangeSummary记录改变需要占用一定的资源。因此默认情况下logging是关闭的。
第3-6行创建rootDataObject,并加了些数据进去。
第7-10行展示了取从DataObject数据的方法。无论什么类型的数据,都可以用get方法去。写数据的时候也都可以用set方法。
第11行展示了从DataObject取ChangeSummary的一个方法。先得到DataGraph,然后从DataGraph得到ChangeSummary。
第12行告诉ChangeSummary结束记录。
第13-23行展示了ChangeSummary的使用。其中,第17行表明,DataObject可以通过getType知道自己的类型。
本例的输出:
mike 1000000 Jone Employee is created.
SDO是一个规范。规范可以暂时没有实现。比如SDO 2.0就没有完全实现。但BOF不同,BOF是个产品。没有实现的产品是不现实的。
但BOF基于SDO的EMF实现而做。BOF提供一组服务,和SDO 2.0中定义的一系列帮助类相呼应;同时BOF使用EMF SDO 1.0实现的数据模型;成功解决了这个问题。
我们从两个面探讨BOF。一个是BOF数据模型,一个是BOF服务。
BOF数据模型
BOF里的数据模型的建立综合考虑了SDO的数据模型和ICS里BO的数据模型。分三部分讲述:Business Object,Business Graph和Business Object Type Metedata。
Business Objects
就是SDO里的DataObject。但考虑了和之前产品ICS里BO业务数据部分的兼容问题。 Business Graphs
就是SDO里的DataGraph。 但考虑了和之前产品ICS的兼容问题。因此Business Graph里除了有ChangeSummary外,还添加了ICS BO中的Verb等信息。 Business Object Type Metadata
是可以添加在business object定义文件中增强其在WPS中价值的原数据。这些原数据片断用xs:annotation和xs:appinfo添在在business object的XML定义文件中。
BOF服务
BO Framework为我们提供了许多服务:
BOChangeSummary
提供SDO 1.0 ChangeSummary的增强接口,用于管理Business Graphs中的ChangeSummary头。 BOCopy
方便用户拷贝一个Business Object或者包含Business Objects的Business Graph的服务。 BODataObject
增强了SDO 1.0 Data Object接口。 BOEquality
提供一个比较两个Business Graph或者Business Object是否相等的接口。 BOEventSummary (described above)
提供一个管理Business Graph中Event Summary头的接口。 BOFactory
提供接口创建一个Business Graph或者Business Object。 BOType
提供一个获取Business Graph的SDO Type或者Business Object影射的Java类名称。 BOTypeMetadata (described above)
提供一个读取依照BO Type 原数据模型的注视块的接口,并且把它转换/反转换为一个DataObject。 BOXMLDocument/BOXMLSerializer
提供创建表达一个内存中的Business Object的XML文档的接口,支持序列化与反序列化。




回页首
这一节中,将用一个实例说明BO的应用,这里假设有一业务需求:订单和物品,订单中可以有很多物品,每一个物品都有自己的ID,名称,单价和数量,而订单有自己的ID,编码,总价。
订单在传输过程中经历了如下操作,先创建一个订单实例,在这个订单实例中添加了两个物品,并且计算了订单的总价,但是在传送走后发现订单的代码被改动过了,需要重新找回原来的订单代码,最后这个订单实例被序列化并存储。
WID(WebSphere Integration Develpor)是WPS开发的工具,我们可以在WID中非常方便地开发BO的定义。
首先,在WID中的Business Integration视图中建立一个Module,名称是:Purchase。
其次,在新建的Module上单击右键,选择New->Business Object,新建一个名叫Purchase的Business Object,按照此步骤,分别创建Purchase BO和Item BO,如图所示:

在创建过程中需要注意的是如何创建树组,例如Purchase中的items元素就是一个树组,我们需要在属性中将Array的复选框钩上,这样items就成为了一个数组,如图所示:

那么如何创建BG呢?
在左侧的Business Integration视图中,右建点击PurchaseBO,在菜单中选择Create a Business Graph,WID会自动为我们创建一个标准的Business Graph,并且使用和BO相同的命名空间:

WID是一个集成的开发环境,为我们提供了良好的对WPS6.0的支持,BO可以在WPS6.0下运行,但是同时也提供了一个轻量级的J2SE的调试环境,我们可以使用J2SE来测试我们的BO。
在WID中,我们可以任意创建一个可以运行的Java类来运行BO,下面是一些BOF服务的使用方法,我们将具体介绍每一个服务的调用方法和功能,读者可以比较一下SDO相应接口的调用方式。
private BOChangeSummary getBOChangeSummary(DataObject purchaseBG) { BOChangeSummary change = (BOChangeSummary) ServiceManager.INSTANCE .locateService("com/ibm/websphere/bo/BOChangeSummary"); return change; }
获取BOChangeSummary服务,用于管理BG中ChangeSummary的内容,利用ChangeSummary,我们可以保存一组BO的初始值。
private DataObject createBO(String string, String string2) { BOFactory bof = (BOFactory) ServiceManager.INSTANCE .locateService("com/ibm/websphere/bo/BOFactory"); return bof.create(string, string2); } private DataObject createByType(String string, String string2) { BOType botype = (BOType) ServiceManager.INSTANCE .locateService("com/ibm/websphere/bo/BOType"); Type type = botype.getType(string, string2); BOFactory bof = (BOFactory) ServiceManager.INSTANCE .locateService("com/ibm/websphere/bo/BOFactory"); return bof.createByType(type); }
BOF服务提供了许多创建BO的方式,我们可以通过BO定义中的TargetNameSpace和TypeName创建BO,可以通过SDO的Type定义来创建BO,并且BOF还支持从WSDL的Message中创建BO。
private DataObject retrieve(DataObject purchase) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); BOXMLSerializer serializer = (BOXMLSerializer) ServiceManager.INSTANCE .locateService("com/ibm/websphere/bo/BOXMLSerializer"); BOXMLDocument doc = serializer.createXMLDocument(purchase, "abc.com/PurchaseRetrieve", "Retrieved"); try { serializer.writeXMLDocument(doc, bos); } catch (IOException e) { e.printStackTrace(); } ByteArrayInputStream in = new ByteArrayInputStream(bos.toByteArray()); try { doc = serializer.readXMLDocument(in); } catch (IOException e1) { e1.printStackTrace(); } return doc.getDataObject(); }
BO支持序列化和反序列化,可以轻易地将BO的Java实例转换为一个XML文件或者一个流保存起来,并且在需要的时候,将这个BO从XML或者流中转换回一个Java实例。
private BOEventSummary getBOEventSummary(DataObject purchaseBG) { BODataObject boe = (BODataObject) ServiceManager.INSTANCE .locateService("com/ibm/websphere/bo/BODataObject"); return boe.getEventSummary(purchaseBG); }
BOF服务提供了对BG中EventSummary进行操作的服务,BOEventSummary,我们可以对某一BO设置其Event和ObjectEventID。
private void endLogging(DataObject purchaseBG) { ChangeSummary chs = (ChangeSummary) purchaseBG.get("changeSummary"); chs.endLogging(); } private void beginLogging(DataObject purchaseBG) { BOChangeSummary changes = (BOChangeSummary) ServiceManager.INSTANCE .locateService("com/ibm/websphere/bo/BOChangeSummary"); changes.beginLogging(purchaseBG); } BeginLogging和EndLogging是一对操作,BOF会将在beginLogging之前BO的值保存在ChangeSummary中。 private boolean isEqual(DataObject copyofpurchase, DataObject purchase) { BOEquality boe = (BOEquality) ServiceManager.INSTANCE .locateService("com/ibm/websphere/bo/BOEquality"); return boe.isEqual(copyofpurchase, purchase); }
使用BOF提供的BOEquality服务可以很容易地比较两个复杂的BO是否相同,这里需要区分isEqual方法和isEqualShallow方法的区别,前者会整个比较BO中所有的内容,包括子BO中的内容,isEqualShallow则直比较BO中简单类型是否相等。
private DataObject copy(DataObject purchase) { BOCopy bocopy = (BOCopy) ServiceManager.INSTANCE .locateService("com/ibm/websphere/bo/BOCopy"); return bocopy.copy(purchase); }
BOCopy服务可以帮助用户将一个BO的实例拷贝成为另一个BO的实例,两个实例完全一致,这里同样有两个方法copy和copyShallow,copyShallow将只会拷贝BO中的简单类型,这里还有一对方法copyInto和copyPropertyInto,前者将BO拷贝到另外的一个BO中作为子BO,后者可以拷贝BO中的某个属性。
以上完整的代码请参看附件中的源文件。




回页首
本文介绍了服务数据对象(SDO)的概念,并给出一个使用SDO的精简例子;介绍了业务对象(BO)与服务数据对象(SDO)的区别和联系,并通过一个实际的例子来掌握其具体应用。




回页首
名字 大小 下载方法
bof.sample.sdo.zip 2KBHTTP
Purchase.zip 7KBHTTP

关于下载方法的信息Get Adobe® Reader®




回页首
http://www-128.ibm.com/developerworks/java/library/j-sdo/
http://www-128.ibm.com/developerworks/library/specification/j-commonj-sdowmt/index.html




回页首


南俊杰, 2001年毕业于北京师范大学。2003年加入IBM中国研发中心。一直从事WPS及WBI产品开发及测试工作。

 

张彰,2002年毕业于北京工业大学。2004年加入IBM中国研发中心,一直从事WPS产品的FVT测试工作,现在主要负责WPS中BO组件自动化测试的设计和开发工作。