WBSF(WebSphere Business Services Fabric)让我们在 SOA 开发中能够根据服务策略动态调用业务服务。本文通过一个具体的例子,介绍如何通过 WBSF V6.02 的 SCA 编程模型动态调用业务服务。
组装服务流程
创建 AccountQueryProcess 业务流程:
将 WID 切换至”Business Integration” perspective,在 AccountQueryModule 项目中新建 AccountQueryProc 接口 , 该接口包含 query 方法,如图 1 所示:
图 1 创建 AccountQueryProc 接口
在 AccountQueryModule 项目中新建 Business Process “AccountQueryProcess”,为该 bpel 选择接口为 AccountQueryProc。该 bpel 首先调用 AuthorizationService,然后调用 AccountQueryService,如图 2 所示:
图 2 AccountQueryProcess 流程实现
在”Business Integration”视图下,将 AccountQueryProcess 从 Business Logic 中拖入 Assembly Diagram,WID 将生成以该 BPEL 为实现的 SCA 组件。
通过 Dynamic Assembly 组件组装业务服务:
在 Assembly Diagram 中添加一个 Dynamic Assembler 组件,命名为” AuthorServiceDA”,为其添加 AuthorizationService 接口。双击该组件,生成 DA 实现,如图 3 所示。为 AccountQueryProcess 组件添加到 AuthorServiceDA 的引用。
图 3 AuthorServiceDA 实现
按照同样的步骤,添加 AccountQueryDA Dynamic Assembler 组件,为其选择 AccountQueryService 接口,同样将其添加为 AccountQueryProcess 的引用。如图 4 所示。右键单击 AccountQueryProcess 组件,选择”Synchronize interfaces and references”=>”to implementation”。在 bpel 中将生成两个对应的 Reference Partner。
图 4 为 AccountQueryProcess 添加到 DA 的引用
用流程编辑器打开 AccountQueryProcess,为 AuthorizationService 的调用设置 Partner 为生成的 AuthorizationServicePartner,如图 5 所示:
图 5 设置 AuthorizationService Partner
同样为 AccountQueryService 的调用设置 Partner,如图 6 所示:
图 6 为 AccountQueryService 设置 Partner
通过 Context Propagator 进行 Context 传播
在 Assembly Diagram 中添加 java 组件 ContextEnjectComp_WS 选择实现 AccountQueryProc 接口,并为其添加到 AccountQueryProcess 的引用。ContextEnjectComp_WS 组件的主要实现代码如示例 1 所示:
public class ContextEnjectComp_WSImpl {
static final String SUBSCRIPTOIN_URI=
”http://www.webifysolutions.com/context/subscription“;
static final String subscriptionId=
“fc://fabric/enrollment/subscription-inst#ed4ba997-039a-4351-a05c- 0e318586ed0f”;
private final DaServerLink link = DaServerLink.getInstance();
public Integer query(String userId, String accountId) {
Integer amount;
Map map=new HashMap();
map.put(SUBSCRIPTOIN_URI, subscriptionId);
Serializable contextId = this.createContext(null,map,null);
// 创建 Context 对象,并设置 Context 属性
ContextPropagator propagator = ContextPropagator.getInstance();
propagator.pushContext(contextId);
try{
amount=this.locateService_AccountQueryProcPartner().query (userId,accountId);
}// 在此调用事务中使用创建的 Context
finally{
propagator.popContext();
DynamicAssembler da = link.getServer();
try {
da.completeContext(contextId);
} catch (ContextException e) {
e.printStackTrace();
}
}
return amount;
}
private Serializable createContext(Serializable parentCtxId, Map selectionProperties,
Map otherProperties) {
Serializable contextId;
try {
DynamicAssembler da = link.getServer();
if (parentCtxId == null) {
contextId = da.createContext(parentCtxId);
}
else {
contextId = parentCtxId;
}
ContextImpl ctx = new ContextImpl(contextId, link);
if (selectionProperties != null) {
ctx.mergeCustomProperties(selectionProperties);
}
if (otherProperties != null) {
ctx.mergeCustomProperties(otherProperties);
}
da.setContextProperties(contextId, ctx.getCustomProperties());
}
catch (ContextException ex) {
throw new ServiceRuntimeException(ex);
}
return contextId;
}
}
示例 1 ContextEjectComp 组件实现
按照同样的方式添加 ContextEnjectComp_Portal 组件,其实现与 ContextEnjectComp_WS 几乎完全一样,仅需将 subscriptionId 字段的值改为使用 Portal Channel 的预订 Id 值。
将上面创建的两 java 组件生成 Web service 导出,如图 7 所示:
图 7 为 ContextEnject 组件生成 Web Service 导出
在 ResponseListener 中动态创建 Context 属性:
将 Fabric 的 DA 相关 lib 添加到 AccoutQueryModule 项目中,如图 8 所示:
图 8 配置 AccountQueryModule 项目 Build Path
在 Assembly Diagram 中添加 AuthorResponseListener 组件,其接口为
com.ibm.websphere.fabric.da.plugin.ResponseListener java 接口,为组件生成 java 实现,主要实现代码如示例 2 所示:
public class ResponseListenerImpl implements ResponseListener {
static final String UNITS_OF_WORK_URI=
”http://www.webifysolutions.com/2005/10/catalog/assertion#unitsOfWork“;
static final String high_processCapability=”300″;
static final String basic_processCapability=”150″;
public OutboundResponse handleResponse(
InboundResponse inboundResponse, OutboundResponse outbountResponse) {
// TODO Auto-generated method stub
System.out.println(“inside reponse listener…”);
DataObject resp=
(DataObject) inboundResponse.getResponseMessage().getSequence (0).getValue(0);
DataObject svcLevelDO=(DataObject) resp.getSequence (0).getValue(0);
String serviceLevel=(String) svcLevelDO.getSequence (0).getValue(0);
// 以上获取 Authorization Service 调用的返回值
System.out.println(“serviceLevel=”+serviceLevel);
if(“GOLDEN”.equals(serviceLevel)){
outbountResponse.getParentContext().setSelectionProperty (UNITS_OF_WORK_URI,
new TypedValue(advanced_processCapability));
}
else if(“SILVER”.equals(serviceLevel)){
outbountResponse.getParentContext().setSelectionProperty (UNITS_OF_WORK_URI,
new TypedValue(basic_ processCapability));
}
// 根据不同的服务级别设置不同的服务查询处理能力要求
return outbountResponse;
}
示例 2 ResponseListener 扩展的实现
为 AuthorServiceDA 组建添加到 AuthorResponseListener 组件的引用,如图 9 所示:
图 9 为 DA 添加 ResponseListener 扩展的引用
通过 ContextExtractor 查看运行时 Context 信息:
在 Assembly Diagram 中添加 AccQueryContextExtractor 组件,为其添加
com.ibm.websphere.fabric.da.plugin.ContextExtractor java 接口,并生成 java 实现,其主要实现代码见示例 3:
public class ContextExtractorImpl implements ContextExtractor {
public Context extractContext(PendingRequest req) throws UnexpectedContentException {
Context context=req.getContext();
Set set = context.getSelectionPropertyNames();
for(Iterator it=set.iterator();it.hasNext();){
String key=(String) it.next();
String value=context.getSelectionProperty(key).getValue();
System.out.println(key+”=”+value);
}
// 打印 Context 对象中所有的属性
return context;
}
}
示例 3 ContextExtractor 的实习那
为 AccountQueryDA 组件添加到 AccQueryContextExtractor 组件的引用,如图 10 所示:
图 10 为 DA 添加 ContextExtractor 扩展的引用
部署服务组件:
在 WID 中构建 AccoutQueryModule 项目,将其导出为 ear 文件,并且部署至 WBSF Server 所在的 WPS 上。
测试与分析
测试:
将 WID 切换至 Java 视图,右键单击 ContextEnjectComp_WS 组件导出的 wsdl 文件,选择”Web Services”=>”test with Web Services Explore”, 进入 Web service 测试界面,填写用户名和帐号,提交表单之后,可以观察到示例 4 所示结果。根据 Policy,从 Web Service 通道访问服务,选择采用 HTTPS 客户机认证的授权服务,因而得到服务级别为 GOLDEN;在 ResponseListener 中,根据服务级别设置帐户查询的处理能力大于 300 工作单元,因此只有 Advance 查询服务被选择,返回结果 5000。
服务返回值: 5000
ResponseListener Log 输出: serviceLevel=GOLDEN
ContextExtractor Log 输出:
http://www.webifysolutions.com/context/interface=
http://AccountQueryModule/AccountQueryService#AccountQueryService
http://www.webifysolutions.com/2005/10/catalog/assertion#unitsOfWork=300
http://www.webifysolutions.com/context/subscription=
fc://fabric/enrollment/subscription-inst#ed4ba997-039a-4351-a05c-0e318586ed0f
http://www.webifysolutions.com/context/component=sca://AccountQueryModule/AccountQueryDA
示例 4 通过 Web Service 通道调用业务服务的结果
同样用 Web Service Explore 测试 ContextEnjectComp_Portal 组件到处的 Web Service,可以观察到示例 5 所示结果。通过 Portal 通道进行的请求,选择了采用 HTTP 基本认证方式的服务,得到服务级别为 SILVER,从而在 ResponseListener 中设置对查询服务处理能力要求最小为 150 个工作单元,Advanced 查询服务和 Basic 查询服务都满足要求,WBSF 随机选择查询服务调用。
示例 5 通过 Portal 通道调用业务服务的结果 :
服务返回值:返回值可能为 2000,也可能为 5000
ResponseListene Log 输出: serviceLevel=SILVER
ContextExtractor Log 输出:
http://www.webifysolutions.com/context/interface=
http://AccountQueryModule/AccountQueryService#AccountQueryService
http://www.webifysolutions.com/2005/10/catalog/assertion#unitsOfWork=120
http://www.webifysolutions.com/context/subscription=
fc://fabric/enrollment/subscription-inst#182e3f32-8d92-4d93-8636-74d97d784a2d
http://www.webifysolutions.com/context/component=sca://AccountQueryModule/AccountQueryDA
分析
整个服务调用流程的 Context 更新过程如图 11 所示:在 Context Eject 组件中,我们创建了根 Context,并在 Context 中设置了 Subscription Id 属性,该 Id 关联了包括通道在内的一组上下文信息。在 BPEL 的执行中,调用到 Authorization Service DA 组件时,该组件会创建子 Context,并且继承根 Context 的所有属性。Authorization Service DA 在子 Context 中设置和 Authorization Service 相关的一组属性,例如服务接口。DA 调用服务结束后,子 Context 被去除。后面 AccountQuery DA 创建本次服务调用的子 Context,仍然继承了根 Context 的所有属性。
在 Authorization DA 调用结束之前,我们在 ResponseListener 中根据调用结果修改了其父 Context,也就是根 Context。根 Context 为后面的 Account Query DA 创建的子 Context 所继承,从而在 ResponseListener 中对父 Context 的更新能够影响后续服务的调用。
图 11 Context 传播结构图
结束语
以上我们了展示了通过 WBSF 开发业务服务的完整流程,本文的场景和实现虽然很大程度上是模拟现实场景,我们不难将其对应于实际应用开发。我们通过 WBSF V6.02 的 SCA 编程模型进行业务服务的动态调用,使用了基于上下文的服务策略和基于内容的断言两种方式进行运行时服务选取。
作者简介
周志远,工作在 IBM 中国软件开发实验室 – 中国新技术中心(China Emerging Technology Institute),从事 Incubator 及 SOA 相关项目的工作。他的邮件是zzyuan@cn.ibm.com。
郭迎春,IBM 中国软件实验室(CSDL BJ)的成员,有多年 Java 开发经验,目前主要研究方向为 SOA、CBS(Composite Business Service)。你可以通过 guoyingc@cn.ibm.com 联系她。
王强IBM软件工程师,工作在IBM中国软件开发实验室 – SOA Design Center,从事Incubator及 SOA ,Grid项目的工作,对J2EE架构、 SOA 架构、MDA/MDD以及网格计算等技术有较深入的研究。联系方式:wangq@cn.ibm.com。
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号
TechTarget
官方微博
TechTarget中国
相关推荐
-
工具和实践促进意义SOA ALM流程的创建
SOA ALM时代已经到来,它必须反映这样的事实:现代应用程序逐渐由重用组件和重新编排工作流而组成。
-
如何透过业务和技术看SOA的发展
随着SOA发展的深入,各种SOA相关技术标准也随之发展和完善。面对庞大而复杂的SOA相关技术标准,我们如何来有选择的使用它们呢?
-
SOA架构下补偿模型驱动的安全苛求软件开发
随着我国高速铁路的快速发展,传统的计算机联锁软件开发方法在灵活性、可维护性、安全性以及开发效率上都显露出不足,怎样才能弥补这一不足呢?
-
浅谈基于SOA架构的服务集成技术研究
在近几年软件行业的发展中,面向服务架构(SOA)成为了当下的热门话题。那么对于SOA架构的服务集成你又了解多少?