IBM Skip to main content
Search for:   within 
      Search help  
     IBM home  |  Products & services  |  Support & downloads   |  My account

developerWorks > Web services
developerWorks
Preserving EJB State with SOAP headers
62 KBe-mail it!
Contents:
Developing a SOAP client in VB 6.0
Developing a SOAP client in VB.NET
Summary
Resources
About the author
Rate this article
Subscriptions:
dW newsletters
dW Subscription
(CDs and downloads)
Handling state from VB.6 and VB.NET SOAP clients

Level: Intermediate

Ioulia Doumkina
Software Developer, IBM Canada
01 November 2003

One of the most popular patterns for use in J2EE server applications is the Stateful Session Facade. But how do you take advantage of stateful session beans when SOAP doesn't support state? This question is especially relevant to software development today where Web Services are becoming popular for connecting Visual Basic (VB) 6 and .NET SOAP clients to J2EE engines. The solution described in this article involves using SOAP headers for passing controllers in serialized form.

Web Services are becoming extremely popular not only in the software development world, but also among customers. In this age of globalization, sharing information has become extremely important. Large companies want to connect their VB or .NET applications with their partner’s J2EE engines. Web Services provide the means for software to interoperate across different platforms and programming languages. Ironically, interoperability has not yet become seamless due to the differences in Web Services implementations between different vendors. Furthermore, SOAP doesn't preserve state, which makes the task even more challenging. The concept of state is especially relevant for J2EE server applications, which frequently expose their business processes as stateful session beans. Nevertheless, interoperability is achievable and state can be preserved with the help of SOAP headers and the magic of serialization. This article will focus on interfacing stateful session beans from VB and. NET desktop clients.

Developing a SOAP client in VB 6.0
Developing a SOAP client in VB requires installation of the Microsoft SOAP Type Library, which can be downloaded from the Microsoft Web site. In the examples below, I have used the Microsoft Soap Toolkit v3.0. The Microsoft SOAP Type Library doesn't include the header implementation, but only an interface.

Implementing a SOAP Header with the Microsoft SOAP Type Library 3.0 in VB 6.0
One approach would be to create a separate DLL that would consist exclusively of the header implementation and ship this implementation to the client as part of the product, as shown in Listing 1. In this example, you could call the DLL VBHeaderHandler.dll.

Listing 1. Example of header implementation in VB 6.0

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

Passing serialized controller as part of the header in VB 6.0
On the client side you can instantiate the VBHeaderHandler class, set the HeaderValue to the base64 encoded serialized controller and, eventually, set the HeaderHandler property of the SoapClient30 to the instance of the HeaderHandler class. As in the code example in Listing 2, you can first store a serialized controller in a string variable, then assign this variable to the HeaderValue variable.

Listing 2. Example of using headers to pass serialized controllers in 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)

Requirements on the server side and interoperability tips
On the server side you will need to create a SOAP provider that will intercept the SOAP message, extract the serialized controller from the header, and deserialize it. Furthermore, you will need to add data type information to the deployment descriptor (dds.xml) , since SoapClient30 doesn't include data type information in the SOAP message

Developing a SOAP client in VB.NET
One useful .NET feature is the ability to create proxies. You create them once, refresh when the API changes, and deliver to the client. No more initializing WSDL files, and no need to recollect the signature calls from the WSDL files. Furthermore, no need to use the dds.xml files, since all data type information is now included in the SOAP message.

Personally, I prefer to generate proxies using the WSDL.exe tool, since it automatically adds the property "Url", that is very handy (this property allows you to dynamically specify the location of the exposed services). This can be convenient if you want to ship your proxies as part of your product.

Header implementation in VB.NET
Implementing headers with .NET Web Services is very straightforward. Writing headers is simplified to just creating a class that inherits from SoapHeader and including a public variable HeaderValue, which represent the header entry, as shown in Listing 3.

Listing 3. Example of header implementation in 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

In this example, you could save it as NetHeaderHandler.dll.

Creating and modifying Web Services proxies.
After creating NetHeaderHandler.dll, you are ready to change your proxies that you created using WSDL.exe. The command used to generate your proxies is shown in Listing 4 (this command should be all on one line).

Listing 4. Command for generating proxies

wsdl /language:VB /namespace:ibm.com  
http://server1:9080/MyTest/TestControllerEJBService.wsdl

Once you have created your proxies, you need to modify them to include header information. Modifying a proxy involves two steps (see also Listings 5 and 6):

  1. Adding a public member variable of type NetHeaderHandler.SoapHeaderHandler
  2. Inserting a SOAP header attribute.

Listing 5. Example of header declaration in VB.NET

Public headerValue As NetHeaderHandler.SoapHeaderHandler

Adding header attributes
Deciding how to add a header attribute is not easy, because header attributes are not well documented by Microsoft, and there are very few good examples available on how to use them. In most cases, you will end up with something that looks like Listing 6.

Listing 6. Example of a header attribute

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")

Build this and save it as NetProxies.dll.

Passing serialized controller as part of the header in VB.NET
One you are done with modifying your proxies, you are ready for the final step -- invoking a J2EE server application through a .NET client application (see Listing 7).

Listing 7. Example of client side code in 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()

Summary
This article has covered how to connect to a J2EE server application, which uses stateful session beans as part of its architecture. To invoke the same bean, you used headers for both a Visual Basic 6.0 Soap Client and a VB.NET Soap Client. Also listed were some tips on how to overcome interoperability issues which arise when using a Microsoft Soap Client and a WebSphere Soap Server.

Resources

About the author
Ioulia Doumkina is a Software Developer in the IBM Ottawa Lab, eRecordsManager Team. You can contact Ioulia at Ioulia_doumkina at ca.ibm.com.


62 KBe-mail it!

What do you think of this document?
Killer! (5) Good stuff (4) So-so; not bad (3) Needs work (2) Lame! (1)

Comments?



developerWorks > Web services
developerWorks
  About IBM  |  Privacy  |  Terms of use  |  Contact