标题：业务对象
简介
业务对象（Business Object）是由第三方开发的，在GeneXus 社区内可获得的知识对象。用其可以在一个应用中自动的加入一个特定的功能来获得增值效应。使知识重用变为可能。比如，如果你要开发一个包含多货币处理的应用，你可以选择使用一个已经开发完成的，包含所有多货币处理功能的业务对象来开始你的开发。使您的开发工作极大的减少。 Remote Data Service 提供默认的中间层业务对象 RDSServer.DataFactory，用于接收客户端请求并提供对指定数据源的读写访问，但不包含任何验证或业务规则逻辑。
用户可以创建能够提供与 RDSServer.DataFactory 功能相同的自定义业务对象，并且对应用程序的业务规则进行封装。
必要条件
⒈由状态和行为组成
⒉表达了来自业务域的一个人，地点，事物或概念
⒊可以重用
分类
1.实体业务对象：
表达了一个人，地点，事物或者概念.根据业务中的名词从业务域中提取的.如客户，订单，物品.在EJB应用程序中，一般为实体Bean.在传统的web应用程序中，可能是包含业务应用的状态和行为的普通javabean.
2.过程业务对象：
表达应用程序中业务处理过程或者工作流程任务.通常依赖于实体业务对象，是业务的动词.在EJB应用程序中，通常是模型的会话bean，或者消息驱动bean.在非EJB应用中，可能是javabean，包含特定的行为，作为应用程序的管理者或者控制者.
3.事件业务对象：
表达应用程序中由于系统的一些操作造成或产生的一些事件.
抽象与整合
业务对象的抽象和整合有何联系呢，或许有人会问我这样的一个问题（以前的我也老想着这个问题），就这个问题我个人觉得，如果脱离业务抽象而想象一个架构体系，那么是一个本末倒置的愚蠢的做法，因为只有做了一个业务的抽象才能根本上满足需求本质，这样才能更实际的充分的得到现实业务现象的抽象才能合理有效的模拟实现的IT系统（一个IT化的过程第一步骤）。
整合IT系统面临一个很大问题如何抽象IT系统的交互问题，这个方面IBM采取了消息通信的抽象；它这样做当然有他的道理（也是比较接近现实场景的），但是我在这里顺便提一下我个人的想法，消息其实只是通信和协调的一个实现而已，但是还没有到本质；本质就是通信的协议的定制。我自己采取的就是在底层使用一个会话协议抽象（工作的保密关系不能再细说了，但是我的实践告诉我这样做有很高的架构体系扩展上，大家有机会可以试一试）。
所以业务抽象十分重要，只有把握好这一点，你的架构系统将体现更高的架构体系高度。你会发现需求的现象的本质，已经没有太多的需求变动能破坏你的架构还没有把握业务的本质）。
BO的应用
业务需求这一节中，将用一个实例说明BO的应用，这里假设有一业务需求：订单和物品，订单中可以有很多物品，每一个物品都有自己的ID，名称，单价和数量，而订单有自己的ID，编码，总价。
订单在传输过程中经历了如下操作，先创建一个订单实例，在这个订单实例中添加了两个物品，并且计算了订单的总价，但是在传送走后发现订单的代码被改动过了，需要重新找回原来的订单代码，最后这个订单实例被序列化并存储。
用WID开发具体的BO及相关组件WID(WebSphere Integration Develpor）是WPS开发的工具，我们可以在WID中非常方便地开发BO的定义。
首先，在WID中的Business Integration视图中建立一个Module，名称是：Purchase。
其次，在新建的Module上单击右键，选择New->Business Object，新建一个名叫Purchase的Business Object，按照此步骤，分别创建Purchase BO和Item BO，如图所示：
  Purchase BO和Item BO
图表 1，Purchase和Item BO的定义
在创建过程中需要注意的是如何创建树组，例如Purchase中的items元素就是一个树组，我们需要在属性中将Array的复选框钩上，这样items就成为了一个数组，如图所示：
  数组
图表 2，items的数组定义
那么如何创建BG呢？
在左侧的Business Integration视图中，右建点击PurchaseBO，在菜单中选择Create a Business Graph，WID会自动为我们创建一个标准的Business Graph，并且使用和BO相同的命名空间：
  Purchase和PurchaseBG
图表 3，Purchase和PurchaseBG
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中的某个属性。