Skip to main content

Preserving EJB State with SOAP headers

Handling state from VB.6 and VB.NET SOAP clients

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

Summary:  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.

Date:  01 Nov 2003
Level:  Intermediate
Activity:  1807 views

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.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and Web services
ArticleID=10893
ArticleTitle=Preserving EJB State with SOAP headers
publish-date=11012003
author1-email=
author1-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers