随着SOA (面向服务架构) 的推广,Web Service技术作为SOA最基础最简单的一种实现方式,在各种各样的项目中得到了广泛的应用。Web Service使用SOAP作为消息格式,基于这种通用的技术,各种异构的系统可以很容易地进行整合和交互。这些Web Service接口,也为企业将来的SOA平台提供了良好的基础。
Web Service不仅仅只有SOAP消息,还有它所使用的transport。HTTP作为Web Service标准的第一个官方transport,已经得到了广泛的应用,但是http本身有许多局限性。比如:它只支持点对点同步方式;不能保证消息的可靠传输;http受主机端口的限制,扩展性不强;虽然有很多的机制对SOAP/HTTP进行了扩充,但这些机制复杂,难于掌握。
幸运的是,我们还有其他的选择,除了HTTP,JMS也是Web Service常用的transport。相对于http,JMS有这样一些优点:JMS有更多的通讯方式,包括同步/异步的点对点和发布/订阅;JMS通过其自身的存储转发机制支持可靠的传输;JMS不受端口限制,有很强的扩展性;因为JMS本身有了上述特性,所以SOAP/JMS比SOAP/HTTP要更加简单。当然了,要使用JMS Transport,你需要一个JMS Server。
目前广泛使用的Web Service引擎——XFire和Axis2都对JMS transport提供了支持。(Axis2的最新版本1.5.1还不支持JMS,据说还没有release。)
在这两种Web Service引擎上部署SOAP/JMS的所使用的JAVA代码与SOAP/HTTP完全一样,只是在配置文件上稍有不同。本文中我们使用TIBCO EMS作为JMS服务器。
1. XFire
l 将TIBCO EMS的jar文件拷贝到WEB-INF/lib目录下(本文使用XFire 1.2.6);
l 如下修改XFire应用目录下的WEB-INF/classes/META-INF/xfire/services.xml
<!-- START SNIPPET: services -->
<beansxmlns="http://xfire.codehaus.org/config/1.0">
<xfire>
<transports>
<bean id="jmsTransport"
class="org.codehaus.xfire.transport.jms.JMSTransport"
xmlns="http://xbean.org/schemas/spring/1.0">
<constructor-argref="xfire"/>
<constructor-argref="connectionFactory"/>
</bean>
</transports>
</xfire>
<service>
<name>TestService</name>
<namespace>http://xfire.codehaus.org/TestService</namespace>
<serviceClass>test.TestService</serviceClass>
<implementationClass>test.TestServiceImpl</implementationClass>
<bindings>
<soap11Bindingname="e:TestServiceJMSBinding"transport="urn:xfire:transport:jms">
<endpoints>
<endpointname="e:TestServiceJMSEndpoint" url="jms://TestService"/>
</endpoints>
</soap11Binding>
</bindings>
</service>
<bean id="connectionFactory"
class="com.tibco.tibjms.TibjmsQueueConnectionFactory"
singleton="true"
xmlns="http://xbean.org/schemas/spring/1.0/">
<constructor-arg value="tcp://localhost:7222"type="java.lang.String"/>
</bean>
</beans>
<!-- ENDSNIPPET: services -->
l 红色字体为配置SOAP/JMS与SOAP/HTTP不同的地方,部署SOAP/HTTP不需要这些配置;
l 其中<endpoint name="e:TestServiceJMSEndpoint"url="jms://TestService" />中jms://后为当前服务使用的Queue或者Topic的,它的名称必须与<name>TestService</name>中的名称相同。
l 启动部署XFire应用的Application Server,访问该服务的WSDL,会发现相比单纯的SOAP/HTTP,多出了如下信息:
<wsdl:bindingname="TestServiceJMSBinding"type="tns:TestServicePortType">
<wsdlsoap:bindingstyle="document" transport="urn:xfire:transport:jms"/>
<wsdl:operationname="getTests">
<wsdlsoap:operationsoapAction=""/>
<wsdl:inputname="getTestsRequest">
<wsdlsoap:bodyuse="literal"/>
</wsdl:input>
<wsdl:outputname="getTestsResponse">
<wsdlsoap:bodyuse="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operationname="getResult">
<wsdlsoap:operationsoapAction=""/>
<wsdl:inputname="getResultRequest">
<wsdlsoap:bodyuse="literal"/>
</wsdl:input>
<wsdl:outputname="getResultResponse">
<wsdlsoap:bodyuse="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:servicename="TestService">
<wsdl:portname="TestServiceJMSPort"binding="TestServiceJMSBinding">
<wsdlsoap:addresslocation="jms://TestService"/>
</wsdl:port>
<wsdl:portname="TestServiceHttpPort" binding="tns:TestServiceHttpBinding">
<wsdlsoap:addresslocation="http://localhost:8080/xfire/services/TestService"/>
</wsdl:port>
<wsdl:portname="TestServiceJMSEndpoint"binding="TestServiceJMSBinding">
<wsdlsoap:addresslocation="jms://TestService"/>
</wsdl:port>
</wsdl:service>
l 部署在App Server中的XFire应用同时支持SOAP/HTTP和SOAP/JMS两种模式。
2. Axis2
l 将TIBCO EMS的jar文件拷贝到AXIS2_HOME/lib目录下;
l 修改AXIS2_HOME/conf/axis2.xml,修改与JMS相关的设置,如下:
<transportReceivername="jms"class="org.apache.axis2.transport.jms.JMSListener">
<parametername="tibTopicConnectionFactory">
<parametername="java.naming.factory.initial">com.tibco.tibjms.naming.TibjmsInitialContextFactory</parameter>
<parametername="java.naming.provider.url">tibjmsnaming://localhost:7222</parameter>
<parametername="transport.jms.ConnectionFactoryJNDIName">TopicConnectionFactory</parameter>
</parameter>
<parameter name="tibQueueConnectionFactory">
<parametername="java.naming.factory.initial">com.tibco.tibjms.naming.TibjmsInitialContextFactory</parameter>
<parametername="java.naming.provider.url">tibjmsnaming://localhost:7222</parameter>
<parametername="transport.jms.ConnectionFactoryJNDIName">QueueConnectionFactory</parameter>
</parameter>
<parameter name="default">
<parametername="java.naming.factory.initial">com.tibco.tibjms.naming.TibjmsInitialContextFactory</parameter>
<parametername="java.naming.provider.url">tibjmsnaming://localhost:7222</parameter>
<parametername="transport.jms.ConnectionFactoryJNDIName">QueueConnectionFactory</parameter>
</parameter>
</transportReceiver>
<transportSendername="jms" class="org.apache.axis2.transport.jms.JMSSender"/>
l AXIS2引擎可以不用部署到App Server就能启动,启动引擎。应用启动后,可在EMS中查到引擎创建的与服务名相同的Queue或Topic;
l 查询服务的WSDL可以发现新增如下信息:
<wsdl:portname="TestServiceJmsSoap11Endpoint"binding="ns:TestServiceSoap11Binding">
<soap:addresslocation="jms:/TestService?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.provider.url=tibjmsnaming://localhost:7222&java.naming.factory.initial=com.tibco.tibjms.naming.TibjmsInitialContextFactory"/>
</wsdl:port>
<wsdl:portname="TestServiceJmsSoap12Endpoint"binding="ns:TestServiceSoap12Binding">
<soap12:addresslocation="jms:/TestService?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.provider.url=tibjmsnaming://localhost:7222&java.naming.factory.initial=com.tibco.tibjms.naming.TibjmsInitialContextFactory"/>
</wsdl:port>
l 在我这几天做的测试中,发现AXIS2 1.3和AXIS2 1.4.1上部署的服务都有问题;同样的aar包部署在AXIS2 1.5.1可以正常运行,但是它还不支持JMS transport,需要等待更新的版本,所以在后面的测试中,我也没有再使用BW去调用AXIS2的SOAP/JMS服务。
3. 使用BW SOAP RequestReply调用SOAP/JMS服务
TIBCO BusinessWorks (简称BW) 是一款非常优秀的集成平台产品,它通过图形化方式创建集成应用,并且能够与市面上几乎所有的技术接口进行交互,这里面当然不会少了Web Service。BW本身也可以进行SOAP应用的封装和调用,在本节中,我们将要介绍如何用BW调用使用XFire封装的SOAP/JMS服务。(因为AXIS2本身的缺陷和不完善,暂不做讨论)
使用BW调用SOAP/JMS服务有两种方式,可以使用topic或者queue的requestor调用同步服务,或者用Topic Publisher或者Queue Sender来调用One Way的异步服务,因为SOAP/JMS本质上就是使用JMS发送SOAP格式的报文。另一种方式就是更加正规的,使用SOAP RequestReply来进行调用。
l 将XFire服务的WSDL导入BW工程,与SOAP RequestReply关联,我们会发现Transport Detail是空的;
l 如下修改XFire服务的WSDL:
n 在wsdl:definitions中增加如下两个Name Space
xmlns:jms ="http://www.tibco.com/namespaces/ws/2004/soap/binding/JMS"
xmlns:jndi = http://www.tibco.com/namespaces/ws/2004/soap/apis/jndi
n 在wsdl:service中增加如下的红色字体
<wsdl:service name ="TestService">
<wsdl:portbinding = "TestServiceJMSBinding" name = "TestServiceJMSPort">
<wsdlsoap:addresslocation = "jms://TestService"/>
<jms:connectionFactory>QueueConnectionFactory</jms:connectionFactory>
<jms:targetAddress destination ="queue">TestService</jms:targetAddress>
</wsdl:port>
<wsdl:portbinding = "tns:TestServiceHttpBinding" name ="TestServiceHttpPort">
<wsdlsoap:addresslocation = "http://localhost:8080/xfire/services/TestService"/>
</wsdl:port>
<wsdl:portbinding = "TestServiceJMSBinding" name ="TestServiceJMSEndpoint">
<wsdlsoap:address location= "jms://sample"/>
<jms:connectionFactory>QueueConnectionFactory</jms:connectionFactory>
<jms:targetAddress destination ="queue">TestService</jms:targetAddress>
</wsdl:port>
</wsdl:service>
增加的内容为使用的jndi connection factory和destination的类型和名称。
n 如上修改后,用户就可以在Transport Detail中进行Transport的设置
l 启动Process 进行测试,SOAP RequestReply会抛出异常:SoapMessage::initRequestMessage。看样子是SOAP RequestReply在组装SOAP Message的时候就有问题,没法把消息发送到EMS服务器上;通过检查WSDL,发现问题在于:
<wsdlsoap:binding style="document"transport="urn:xfire:transport:jms"/>
SOAP RequestReply不能识别这个transport,如下进行修改:
<wsdlsoap:binding style = "document" transport = "http://www.tibco.com/namespaces/ws/2004/soap/binding/JMS"/>
l 重新启动Process,调用成功。

本文介绍了在SOA环境中,如何使用TIBCO ESB(BusinessWorks)通过SOAP RequestReply调用使用XFire封装的SOAP/JMS服务。文章详细阐述了SOAP和JMS的优缺点,以及XFire和Axis2支持JMS的情况。通过修改配置文件,实现了在TIBCO BW中调用SOAP/JMS服务,并解决了SOAP RequestReply在组装SOAP Message时遇到的问题。

553

被折叠的 条评论
为什么被折叠?



