级别: 初级 Ioulia Doumkina, 软件开发人员, IBM Canada
2003 年 12 月 01 日 用于 J2EE 服务器应用程序最流行的模式之一是有状态会话门面(Stateful Session Facade)。但是,当 SOAP 不支持状态时,您如何利用有状态会话 Bean 呢?这个问题尤其关系到如今的软件开发,现在,将 Visual Basic(VB)6 和 .NET SOAP 连接到 J2EE 引擎已经变得越来越流行。在本文中讨论的解决方案就是利用 SOAP 头以序列化的形式传送控制器的。
Web
服务不仅在软件开发界非常流行,而且在用户中也是如此。在日益全球化的今天,共享信息已经变得越来越重要。大的公司需要把它们的 VB
或 .NET 应用程序与合作伙伴的 J2EE 引擎连接在一起。Web
服务为软件跨不同的平台和编程语言进行互操作提供了方法。但具有讽刺意味的是,由于不同厂商之间的 Web
服务实现存在着差异,互操作性还没有完全实现。另外,SOAP
并不保持状态,这使得完成互操作性的任务更加具有挑战性。状态的概念与 J2EE
服务器应用程序的关系尤其密切,J2EE
服务器应用程序常常把它们的业务流程作为有状态会话 Bean
公开。尽管如此,互操作性还是可以实现的,并且可以利用 SOAP
头并借助于序列化的魔力来保持状态。本文将重点介绍连接 VB
和 .NET 桌面客户端中的有状态会话 Bean。
用 VB 6.0 开发 SOAP 客户端
用
VB 开发 SOAP 客户端需要安装 Microsoft SOAP
类型库,这个库可以从 Microsoft 网站下载。在接下来的例子中,我使用了
Microsoft Soap Toolkit 3.0。Microsoft SOAP 类型库不包括 SOAP
头实现,而只是一个接口。
在
VB 6.0 中使用 Microsoft SOAP 类型库实现 SOAP 头
有一种方法可以创建单独的 DLL(仅包含
SOAP 头实现),并且将该实现装载到作为产品一部分的客户端中,如
清单1所示。在本例中,您可以调用 DLL VBHeaderHandler.dll。
清单1. 用 VB 实现的头示例
Implements IHeaderHandler
Option Explicit
Public HeaderValue As String
Private Function IHeaderHandler_readHeader(
ByVal par_Reader As MSSOAPLib30.ISoapReader,
ByVal par_HeaderNode As MSXML2.IXMLDOMNode,
ByVal par_Object As Object) As Boolean
IHeaderHandler_readHeader = False
End Function
Private Function IHeaderHandler_WillWriteHeaders() As Boolean
IHeaderHandler_WillWriteHeaders = True
End Function
Private Sub IHeaderHandler_writeHeaders( _
ByVal pSerializer As SoapSerializer30, _
ByVal pObject As Object)
pSerializer.StartHeaderElement "SoapHeaderHandler", "http://www.ibm.com"
pSerializer.StartElement "SoapHeaderHandler"
pSerializer.WriteString HeaderValue
pSerializer.EndElement
pSerializer.EndHeaderElement
End Sub
|
在 VB 6.0
中将序列化控制器作为头的一部分进行传送
在客户端中,您可以实例化 VBHeaderHandler
类,将 HeaderValue 设置为 base64
编码的序列化控制器,最后,将 SoapClient30 的 HeaderHandler
特性设置为 HeaderHandler 类的实例。同
清单2中的代码示例一样,您可以首先将序列化控制器存储在一个字符串变量中,然后将此变量赋给
HeaderValue 变量。
清单2. 在 VB 6.0
中使用头传送序列化控制器的示例
Dim objSoapClient As SoapClient30
Set objSoapClient = CreateObject("MSSOAP.SoapClient30")
objSoapClient.MSSoapInit "http://server1:9080/MyTest/TestControllerEJBService.wsdl",
"TestControllerEJBService"
Dim strSerializedTestController as String
strSerializedTestController =
objSoapClient.getSerializedTestController("John","password")
Dim objHeaderHandler as VBHeaderHandler.clsVBHeaderHandler
Set objHeaderHandler = CreateObject("VBHeaderHandler.clsVBHeaderHandler")
objHeaderHandler.HeaderValue = strSerializedTestController
'now let's try to invoke the same controller
Set objSoapClient.HeaderHandler = objHeaderHandler
Dim strUserName as String
strUserName = objSoapClient.getUserName()
MsgBox(strUserName)
|
服务器端的需求和互操作性技巧
在服务器端,您将需要创建 SOAP 提供者,SOAP 提供者将解释 SOAP
消息,从 SOAP
头提取序列化控制器,然后反序列化它。另外,您还将需要把数据信息添加到部署描述符(dds.xml)中,因为 SoapClient30
不包括 SOAP 消息中的数据类型信息。
用 VB.NET 开发 SOAP 客户端
.NET
的一个有用的特征是创建代理的能力。您可以一次创建它们,在 API
发生改变时更新,然后交给客户端。不再序列化 WSDL
文件,并且不需要重新收集 WSDL
文件中的签名调用。另外,不需要使用 dds.xml
文件,因为所有的数据类型信息现在都包括在 SOAP 消息中。
就个人而言,我更喜欢使用 WSDL.exe
工具生成代理,因为它可以自动添加特性“Url”,这是非常方便的(此特性允许您动态指定以公开的服务的位置)。如果您需要将您的代理作为产品的一部分进行装载,这将是非常方便的。
用 VB.NET
实现头
用 .NET Web
实现头是非常简单的。编写头简化到只需创建从 SoapHeader
继承的类,再将表示头条目的公共变量 HeaderValue
包括进去就可以了,如
清单3所示。
清单
3.
用 VB.NET 实现的头示例
Imports System.Web.Services
Imports System.Web.Services.Protocols
Public Class SoapHeaderHandler
Inherits SoapHeader
Public HeaderValue As String
Public Sub New()
MyBase.New()
End Sub
End Class
|
在本例中,您可以将它保存为
NetHeaderHandler.dll。
创建和修改 Web
服务代理
在创建了 NetHeaderHandler.dll
之后,您就可以更改您用 WSDL.exe
创建的代理。用于生成您的代理的命令如
清单4所示(这条命令应该位于一行上)。
清单4.
生成代理的命令
wsdl /language:VB /namespace:ibm.com
http://server1:9080/MyTest/TestControllerEJBService.wsdl
|
一旦您创建了代理,就需要修改它们,以便将头信息包括进去。修改代理需要遵循两个步骤(同试参见清单
5和
6):
- 添加类型 NetHeaderHandler.SoapHeaderHandler
的公共成员变量。
- 插入 SOAP 头属性。
清单
5.
用 VB.NET 声明头的示例
Public headerValue As NetHeaderHandler.SoapHeaderHandler
|
添加头属性
决定如何添加头属性并不容易,因为头属性不是由
Microsoft
良好文档化的,并且关于如何使用它们的可用示例很少。在大多数情况下,您将以看起来类似于
清单6的代码结束。
清单
6.
头属性的示例
System.Web.Services.Protocols.SoapHeaderAttribute("headerValue", _
Direction:=System.Web.Services.Protocols.SoapHeaderDirection.In, Required:=True), _
System.Web.Services.Protocols.SoapRpcMethodAttribute("",
RequestNamespace:=
"http://ibm.com/myarticle.myarticlecontrollers. TestControllerEJB",
ResponseNamespace:=
"http://ibm.com/myarticle.myarticlecontrollers. TestControllerEJB")
|
创建此代码并将其保存为
NetProxies.dll。
在 VB.NET
中将序列化器作为头的一部分进行传送
一件您已经做过的并且可以作为最后的步骤的事情是——通过 .NET
客户端应用程序调用 J2EE 应用程序服务器(参见
清单7)。
清单
7.
用 VB.NET 创建的客户端代码的示例
Dim strURL as string
strURL = "http://server1:9080/TestWebServices/servlet/rpcrouter"/"
Dim oNetProxy As New NetProxies.ibm.com.TestControllerEJBService()
oNetProxy.Url = gstrURL
'invoke my controller and return it in serialized form
Dim strSerializedTestController as string
strSerializedTestController =
oNetProxy.getSerializedTestController("John","password")
Dim oNetHeaderHandler as New NetHeaderHandler.SoapHeaderHandler
oNetHeaderHandler.HeaderValue = strSerializedTestController
oNetProxy.headerValue = oNetHeaderHandler
Dim strUserName as string
strUserName = oNetProxy.getUserName()
|
总结
本文介绍了如何连接到 J2EE
服务器应用程序(它使用有状态的会话 Bean
作为其体系结构的一部分)。为了调用这样的 Bean,您使用了
Visual Basic 6.0 Soap 客户端和 VB.NET Soap
客户端。此外,本文还列出了如何克服在使用 Microsoft Soap
客户端和 WebSphere Soap 服务器时出现的互操作性问题。
参考资料
关于作者  | |  | Ioulia Doumkina IBM 渥太华实验室 eRecordsManager
小组的软件开发人员。您可以通过
Ioulia_doumkina at ca.ibm.com
与 Ioulia 联系。
|
对本文的评价
|