IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  SOA and Web services | WebSphere  >

在 SOA 开发中使用 WBSF 动态调用业务服务,第 2 部分(下)

WBSF V6.02 开发实例

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


周 志远 (zzyuan@cn.ibm.com), 软件工程师, IBM 中国开发试验室
郭 迎春 (guoyingc@cn.ibm.com), 软件工程师, IBM中国软件实验室
王 强 (wangq@cn.ibm.com), IBM 中国软件开发实验室 软件工程师

2008 年 2 月 21 日

WBSF(WebSphere Business Services Fabric)让我们在 SOA 开发中能够根据服务策略动态调用业务服务。本文通过一个具体的例子,介绍如何通过 WBSF V6.02 的 SCA 编程模型动态调用业务服务。

组装服务流程

  1. 创建 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 组件。

  1. 通过 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

  1. 通过 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 导出

  1. 在 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 扩展的引用

  1. 通过 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 扩展的引用

  1. 部署服务组件:

在 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 试用软件 开发您的下一个项目,可下载或索取 DVD 光盘。


讨论


作者简介

周志远,工作在 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




对本文的评价










回页首


IBM、IBM 徽标和 WebSphere 是 IBM 在美国和 / 或其他国家 / 地区的注册商标。 Java 和所有基于 Java 的商标都是 Sun Microsystems, Inc. 在美国和 / 或其他国家 / 地区的商标。 其他公司、产品或服务的名称可能是其他公司的商标或服务标志。

IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款