级别: 中级 李 传峰 (lichuanf@cn.ibm.com), IBM中国软件研发实验室SOA设计中心工程师 刘 昕鹏 (xinpengl@cn.ibm.com), 工作在IBM中国软件开发实验室软件工程师
2006 年 2 月 20 日 本文介绍了WID支持的两种预定义的 JMS 绑定方式,并通过一个实例介绍了如何创建一种客户化的JMS 绑定方式来使服务组件与不同类型的 JMS 交互。
概述
IBM WID(WebSphere Integration Developer)支持服务组件架构SCA(Service Component Architecture),作为实现SOA统一的、基于标准的编程模型;其中,服务组件(Service Component)代表了底层IT基础设施的关键业务抽象。服务组件并不是孤立存在的,需要与其它非SCA系统交互,WID支持基于JMS和Web Service的交互方式。
本文着重阐述WID服务组件的JMS交互方式,对于SCA的基本概念,如Export、Import、SDO(Service Data Object)等,不再具体介绍,读者可以参见本文的参考资料。
服务组件可以作为JMS Service,接收外部JMS Client发送的消息;也可以作为JMS Client,向外部JMS Service发送消息。服务组件接收JMS消息通过JMS绑定的Export(Export with JMS Binding)机制实现,发送JMS消息通过JMS绑定的Import(Import with JMS Binding)机制实现。Export/Import与外部的JMS Client/Service通过JMS Destination交互。
WID预定义的JMS绑定方式支持用XML文本封装SDO,通过文本类型的JMS消息(TextMessage)传送;也支持用Java对象(Object)封装SDO,通过对象类型的JMS消息(ObjectMessage)传送。使用WID客户化可定制的JMS绑定方式,可以支持其它类型的JMS消息。
本文结合一个实际的例子,阐述这两种预定义的JMS绑定方式,同时创建一种客户化的JMS绑定方式,并将它们应用于Export或Import,与外部JMS Client或Service通信。
本文的开发工具采用WID V6.0.1,部署环境采用WID内嵌的WESB Server。对于WID和WESB的基本使用方法,文中不再具体介绍,读者可以参见本文的参考资料。
示例的交互流程
图1 示例的消息交互流程图
如上图所示,这个例子包含一个外部JMS Client,一个SCA Module,一个外部JMS Service。
- SCA Module中包含一个服务组件(Service Component),同时包含一个JMS绑定的Export和一个JMS绑定的Import。
- JMS Client采用Web形式,可以向特定JMS队列目标发送或从中接收消息。
- 一个MDB作为JMS Service,在特定JMS队列目标上监听消息,并实时返回应答消息。
JMS Client和Export之间通过Q1、Q2队列目标交互,Import和JMS Service通过Q3、Q4队列目标交互。JMS资源,如Q1、Q2、Q3、Q4及队列连接工厂等,既可以在部署时自动生成,也可以使用已经存在的资源。
消息交互过程如下:
1. JMS Client发送消息到Q1;
2. Export从Q1接收JMS消息,转换为特定格式的SDO;
3. 服务组件接收SDO消息,调用Import;
4. Import接收SDO调用,将SDO转换为JMS消息,发送到Q3;
5. MDB监听并消费Q3上到达的JMS消息,生成返回消息,发送到Q4;
6. Import从Q4接收JMS消息,转换为特定格式的SDO;
7. 经过Import转换后的SDO,作为调用结果返回到服务组件;
8. 服务组件将调用结果SDO发送到Export;
9. Export接收返回的SDO,转换为JMS消息,发送到Q2;
10. JMS 消费Q2上到达的JMS消息。
下文将详细介绍示例的构建过程,读者将附录中的"JMSBindingSample.zip"文件引入到WID中,就得到构建完成后的SCA Module和JMS Client。MDB打包到另外一个文件"JMSTestMDB.ear"中。
创建SCA Interface
在单独的JMSBindingLibrary项目(Library项目)中创建JMSStringType业务对象类型和JMSBindingInterface接口。
JMSBindingInterface接口创建了三个Request-Response方法,输入输出参数的类型都是JMSStringType。服务组件、Export和Import都使用JMSBindingInterface接口。
图2 接口定义
创建客户化JMS绑定
JMS绑定为了实现JMS消息和SDO间的转换,需要选择调用的函数名称(实现commonj.connector.runtime.FunctionSelector接口),以及转换消息格式(实现com.ibm.websphere.sca.jms.data.JMSDataBinding接口)。对于FunctionSelector,本文使用WESB的缺省实现com.ibm.websphere.sca.jms.selector.impl.JMSFunctionSelectorImpl;对于JMSDataBinding,使用WESB的缺省实现,并自定义一个客户化实现。
在单独的JMSBindingClassess项目(Java项目)中创建JMSDataBinding的客户化实现JMSTextDataBinding。JMSTextDataBinding实现单纯文本格式(Plain Text)的JMS 消息与SDO之间的格式转换。JMSTextDataBinding中的几个重要方法如下。
- void read(Message message)
读取接收的JMS消息内容,将其存入SDO私有属性中。
- DataObject getDataObject()
返回SDO私有属性。
- void setDataObject(DataObject jmsTextData)
将接收的SDO存入私有属性中。
- void write(Message message)
读取SDO私有属性内容,并将其存入JMS消息中。
从JMS消息到SDO的转换,需要依次调用read()和getDataObject()方法;从SDO到JMS消息的转换,需要依次调用setDataObject()和write()方法。
创建服务组件、Export和Import
在JMSBindingModule项目(Module项目)中创建服务组件、Export和Import。
在Business Integration视图,JMSBindingModule项目的上下文菜单中,选择"Open Dependency Editor",设置JMSBindingModule项目对JMSBindingLibrary项目和JMSBindingClassess项目的依赖,如下图所示。
图3 建立项目间的关联
在Assembly Diagram中,创建服务组件、Export和Import,都使用JMSBindingInterface接口,并连线,如下图所示。
图4 组件装配图
其中,Component1服务组件实现的关键代码如下。
Service JMSService = locateService_JMSBindingInterfacePartner();
DataObject output = (DataObject) JMSService.invoke(FuncName, request);
OperationType opType = JMSService.getReference().getOperationType(FuncName);
if (opType.isWrapperType(opType.getOutputType())) {
response = output.getDataObject("response");
}
else {
response = output;
}
String payload = response.getString("StringValue");
response.setString("StringValue", "SCA-" + payload);
|
需要判断返回类型是否为封装类型,如果是封装类型,需要获取进一步的引用。
为Export1生成JMS绑定。在Assembly Diagram,Export1的上下文菜单中,选择"Generate Binding ... -> JMS Binding"。在接下来的弹出窗口"JMS Export Binding attributes selection"中,使用缺省选项(JMS message domain为"Point-to-Point"),直接点击"OK"。
图5 生成JMS绑定
进入Export1的Properties视图,进入"Binding"页,将Managed Connection Factory的属性改为"com.ibm.ws.sib.api.jmsra.impl.JmsJcaManagedQueueConnectionFactoryImpl"。
图6 修改可管理连接工厂的类型
JMSBindingInterface接口中有三个方法,每个方法使用不同的JMSDataBinding实现。同样在Properties视图的"Binding"页,为每个方法设置"In Data Type"和"Out Data Type"。
- ObjectBindingFunction方法的对应配置为WID预定义的JMSDataBinding实现:com.ibm.websphere.sca.jms.data.impl.JMSDataBindingImplJava,即用Java对象(Object)封装SDO,通过对象类型的JMS消息(ObjectMessage)传送。
- XMLTextBindingFunction方法的对应配置为WID预定义的JMSDataBinding实现:com.ibm.websphere.sca.jms.data.impl.JMSDataBindingImplXML,即用XML文本封装SDO,通过文本类型的JMS消息(TextMessage)传送。
- PlainTextBindingFunction方法的对应配置为客户化的JMSDataBinding实现:com.ibm.sca.jms.binding.sample.JMSTextDataBinding,它实现为单纯文本格式(Plain Text)的JMS 消息与SDO之间的格式转换。
图7 修改Export的输入和输出消息格式绑定类型
类似的,为Import1生成JMS绑定。将JMSBindingInterface接口三个方法的"In Data Type"和"Out Data Type"全部设置为com.ibm.sca.jms.binding.sample.JMSTextDataBinding。
图8 修改Import的输入和输出消息格式绑定类型
创建JMS Client
创建JMSBindingLibrary、JMSBindingClassess和JMSBindingModule项目完成后,点击主菜单"Project"上的"Build"命令,WID将自动生成JMSBindingModuleApp、JMSBindingModuleEJB、JMSBindingModuleEJBClient和JMSBindingModuleWeb项目。
基于JMSBindingModuleWeb项目,创建JMS Client。为了方便,构建完成后的JMSBindingModuleWeb项目也可以从"JMSBindingSample.zip"文件中引入。
JMS Client包含若干JSP及HTML文件,关键逻辑在Servlet中实现,其中,WriteQueue实现向特定队列发送特定类型的JMS消息,ReadQueue从特定队列读取并消费JMS消息。
WriteQueue的关键代码如下:
if (msg_type.equals("PlainTextMessage")) {
TextMessage message = session.createTextMessage(msg_text);
message.setStringProperty("TargetFunctionName","PlainTextBindingFunction");
producer.send(message);
}
else if (msg_type.equals("XMLTextMessage")) {
TextMessage message = session.createTextMessage(msg_text);
message.setStringProperty("TargetFunctionName","XMLTextBindingFunction");
producer.send(message);
}
else if (msg_type.equals("ObjectMessage")) {
String field2 = request.getParameter("PureText");
DataObject jmsData = DataFactory.INSTANCE.create("http://JMSBindingLibrary","JMSStringType");
jmsData.setString("StringValue",field2);
ObjectMessage message = session.createObjectMessage();
message.setObject(jmsData);
message.setStringProperty("TargetFunctionName","ObjectBindingFunction");
producer.send(message);
}
|
发送JMS消息之前,需要设置TargetFunctionName属性,WID缺省的FunctionSelector实现com.ibm.websphere.sca.jms.selector.impl.JMSFunctionSelectorImpl将依靠这个属性值选择调用的函数名称。对于ObjectMessage,创建符合"JMSStringType"的Schema要求的SDO,然后将其设置到ObjectMessage中。
本文示例中,不使用已经存在的JMS资源,部署时自动生成,使用缺省JNDI名称。如下图所示,需要在JMSBindingModuleWeb项目的部署描述符中建立资源引用。
图9 为JMS Client设置资源引用的JNDI名称
- jms/qcf引用JNDI name为"JMSBindingModule/Export1_CF"
- jms/queue_sender引用JNDI name为"JMSBindingModule/Export1_RECEIVE_D"
- jms/queue_receiver引用JNDI name为"JMSBindingModule/Export1_SEND_D"
创建MDB
可以从"JMSTestMDB.ear"文件直接引入构建完成的MDB。
MDB的关键代码如下:
String payload = ((TextMessage) msg).getText();
String MessageID = msg.getJMSMessageID();
System.out.println("MDB: TextMessage Payload is:\n" + payload);
TextMessage sendMsg = session.createTextMessage("MDB-" + payload);
sendMsg.setJMSCorrelationID(MessageID);
sender.send(sendMsg);
|
由于Import1的接口方法都采用JMSTextDataBinding转换消息格式,无论JMS Client发送的消息类型,MDB接收的消息都是单纯文本类型(Plain TextMessage)。为了关联申请消息和返回消息,需要设置返回消息的CorrelationID为申请消息的MessageID。这一点尤为重要,如果不设置CorrelationID,在服务组件的Import上发出的对该MDB的JMS服务请求将无法正确接收MDB的服务回应JMS消息。Import上的JMS绑定会过滤掉本应该被认做服务响应的JMS消息。
与JMS Client类似,MDB也需要在部署描述符中建立资源引用。
图10 为MDB设置资源引用的JNDI名称
- test/sender引用JNDI name为"JMSBindingModule/Import1_RECEIVE_D"
- test/QCF引用JNDI name为"JMSBindingModule/Import1_CF"
另外,还需要在WESB管理控制台(Admin Console)为MDB创建"activation specification",对应配置为:
Name:test_mdb_as
JNDI name:test/mdb/as
Destination JNDI name:JMSBindingModule/Import1_SEND_D
Bus name:SCA.APPLICATION.esbCell.Bus
创建"activation specification"后,在MDB的部署描述符中设置Bean的JCA Adaptor属性。
部署和测试
完成以上创建后,将JMSBindingModuleApp(包含JMS Client)和JMSTestMDB部署到WESB上。
JMS Client的缺省访问URL为"http://localhost:9083/JMSBindingModuleWeb/index.html"。进入不同的链接,可以发送不同类型的JMS消息。
发送"XML TextMessage"时,需要输入符合"JMSStringType"的Schema要求的XML文本,格式如下所示。
<?xml version="1.0" encoding="UTF-8"?>
<jms:JMSStringType xmlns:jms="http://JMSBindingLibrary">
<StringValue>asdfasdf</StringValue>
</jms:JMSStringType>
|
发送"ObjectMessage"时,由于有效值其实为"String"类型,只需要输入有效值,如下图。
图 11 JMS Client发送ObjectMessage消息
也可以显示返回队列上的返回消息,如下图。
图12 显示返回的JMS消息
总结
SCA带来了一种新的支持SOA的编程模型。这种编程模型与现存的技术并不是矛盾的,可以通过在服务组件Export/Import上实现的多种类型的绑定来进行兼容。WID支持SCA,也可以有效的支持SCA服务组件与JMS系统的交互,既支持预定义的JMS绑定,也支持客户化的JMS绑定,可以比较灵活的满足用户的需求。
代码下载
SCA Module及JMS Client:JMSBindingSample.zip,选择"Project Interchange"导入WID。
MDB:JMSTestMDB.ear,选择"EAR file"导入WID。
参考资料
作者简介  | 
|  | 李传峰:IBM中国软件研发实验室SOA设计中心工程师,多年IT企业工作经验,对软件开发及应用有浓厚兴趣。目前正在从事ESB和SCA的实现工作。联系方式:lichuanf@cn.ibm.com |
 | 
|  | 刘昕鹏:IBM软件工程师,工作在IBM中国软件开发实验室 - SOA Design Center,从事Incubator及SOA方面的工作,对J2EE、SOA、MDA/MDD、AOP、语义网等相关技术有浓厚兴趣。目前主要负责基于WID的SCA和WESB实现扩展的相关开发。
联系方式:xinpengl@cn.ibm.com |
对本文的评价
|