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

developerWorks 中国  >  SOA and Web services  >

利用 SOAP 头保持 EJB 状态

处理 VB.6 和 VB.NET SOAP 客户端中的状态

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


级别: 初级

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

一旦您创建了代理,就需要修改它们,以便将头信息包括进去。修改代理需要遵循两个步骤(同试参见清单 56):

  1. 添加类型 NetHeaderHandler.SoapHeaderHandler 的公共成员变量。
  2. 插入 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 联系。




对本文的评价










回页首


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