Visual Basic .NET Client for Apache SOAP

The following instructions produce a Visual Basic .NET client application for the Apache SOAP stock quote sample. They use WSDL generated for the stock quote sample. However, the WSDL is simply used to generate a client proxy, which could also be written by hand in the case that no WSDL is available.

The instructions in this document assume that Apache SOAP is installed according to these instructions. It is also assumed that Visual Studio .NET is installed. My tests were run on Windows 2000 Server SP3 for both the client and server.

Install Web Services Toolkit
Generate WSDL for Stock Quote
Generate the VB.NET proxy from the WSDL
Run the Stock Quote client
Trace the Stock Quote client
Resources

Install Web Services Toolkit

  1. Download a version of the Web Services Toolkit from IBM alphaWorks. I used version 3.0.1 for these tests.
  2. Follow the instructions in the installer. I installed to i:\wstk-3.0.
  3. Note that an alternative is to download Axis, as the only part of the WSTK I used is the java2wsdl tool borrowed from Axis.
Return to top.

Generate WSDL for Stock Quote

Generate WSDL for the stock quote service and place a copy in the soap web application by running the following commands:

  • set WSTK_HOME=I:\wstk-3.0
  • I:\wstk-3.0\bin\java2wsdl -w all -n urn:xmltoday-delayed-quotes -l http://localhost:8080/soap/servlet/rpcrouter -o StockQuoteService.wsdl samples.stockquote.StockQuoteService
  • xcopy /y StockQuoteService.wsdl j:\jakarta-tomcat-4.0.1\webapps\soap

The WSDL generated by this is:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="urn:xmltoday-delayed-quotes"
                  xmlns="http://schemas.xmlsoap.org/wsdl/"
                  xmlns:impl="urn:xmltoday-delayed-quotes-impl"
                  xmlns:intf="urn:xmltoday-delayed-quotes"
                  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
                  xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
                  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <wsdl:message name="getQuoteResponse">
      <wsdl:part name="getQuoteResult" type="xsd:float"/>
   </wsdl:message>
   <wsdl:message name="getQuoteRequest">
      <wsdl:part name="arg0" type="xsd:string"/>
   </wsdl:message>
   <wsdl:portType name="StockQuoteServicePortType">
      <wsdl:operation name="getQuote">
         <wsdl:input message="intf:getQuoteRequest"/>
         <wsdl:output message="intf:getQuoteResponse"/>
      </wsdl:operation>
   </wsdl:portType>
   <wsdl:binding name="StockQuoteServiceSoapBinding"
                 type="intf:StockQuoteServicePortType">
      <soap:binding style="rpc"
                    transport="http://schemas.xmlsoap.org/soap/http"/>
      <wsdl:operation name="getQuote">
         <soap:operation soapAction="" style="rpc"/>
         <wsdl:input>
            <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
                       namespace="urn:xmltoday-delayed-quotes"
                       use="encoded"/>
         </wsdl:input>
         <wsdl:output>
            <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
                       namespace="urn:xmltoday-delayed-quotes"
                       use="encoded"/>
         </wsdl:output>
      </wsdl:operation>
   </wsdl:binding>
   <wsdl:service name="StockQuoteService">
      <wsdl:port binding="intf:StockQuoteServiceSoapBinding"
                 name="StockQuoteServicePort">
         <soap:address location="http://localhost:8080/soap/servlet/rpcrouter"/>
      </wsdl:port>
   </wsdl:service>
</wsdl:definitions>
Return to top.

Generate the VB.NET proxy from the WSDL

The wsdl.exe utility provided with Visual Studio .NET can generate a .NET proxy from a WSDL file. With the WSDL generated in the previous step that was copied to the Apache SOAP webapp in Tomcat, the following command will generate a proxy in a file named StockQuoteService.vb.

	wsdl /language:vb http://localhost:8080/soap/StockQuoteService.wsdl

The following code is generated. I have removed comment blocks for brevity.

Option Strict Off
Option Explicit On

Imports System
Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Xml.Serialization

<System.Diagnostics.DebuggerStepThroughAttribute(),  _
 System.ComponentModel.DesignerCategoryAttribute("code"),  _
 System.Web.Services.WebServiceBindingAttribute(Name:="StockQuoteServiceSoapBinding", _
                                        [Namespace]:="urn:xmltoday-delayed-quotes")>  _
Public Class StockQuoteService
    Inherits System.Web.Services.Protocols.SoapHttpClientProtocol
    
    Public Sub New()
        MyBase.New
        Me.Url = "http://fastdata:8080/soap/servlet/rpcrouter"
    End Sub
    
    <System.Web.Services.Protocols.SoapRpcMethodAttribute("", _
                         RequestNamespace:="urn:xmltoday-delayed-quotes", _
                         ResponseNamespace:="urn:xmltoday-delayed-quotes")>  _
    Public Function getQuote(ByVal arg0 As String) As Single
        Dim results() As Object = Me.Invoke("getQuote", New Object() {arg0})
        Return CType(results(0),Single)
    End Function
    
    Public Function BegingetQuote(ByVal arg0 As String, _
                                  ByVal callback As System.AsyncCallback, _
                                  ByVal asyncState As Object) As System.IAsyncResult
        Return Me.BeginInvoke("getQuote", New Object() {arg0}, callback, asyncState)
    End Function
    
    Public Function EndgetQuote(ByVal asyncResult As System.IAsyncResult) As Single
        Dim results() As Object = Me.EndInvoke(asyncResult)
        Return CType(results(0),Single)
    End Function
End Class

It is extremely important to realize that, although this code was generated by a tool, a person could create the same file in an editor, based on knowledge of the service, such as the relevant namespaces and data types of parameters and return values. While using the tool is typically easier and less error prone, in the absence of WSDL, it is possible to write client code for most web services by subclassing the appropriate class and using .NET attributes.

Return to top.

Run the Stock Quote client

  1. Download the Stock Quote client source.
  2. Unzip the downloaded file.
  3. Open the project named GetQuoteClient in Visual Studio .NET and run it.

The client is a simple form that allows entry of a stock symbol. Upon clicking the button, the Apache SOAP service is called using the proxy and the result displayed on the form. The code for the button follows.

Private Sub btnGetQuote_Click(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) Handles btnGetQuote.Click
    Try
        Dim objService As New StockQuoteService()
        txtQuote.Text = CStr(objService.getQuote(txtSymbol.Text))
    Catch ex As Exception
        MsgBox(ex.ToString(), MsgBoxStyle.OKOnly, _
               "An exception has occurred")
    End Try
End Sub
Return to top.

Trace the Stock Quote client

The TcpTunnelGui utility, included in Apache SOAP, is invaluable in seeing what characters are being sent and received by the client.

  1. Start TcpTunnelGui by running java org.apache.soap.util.net.TcpTunnelGui 81 localhost 8080
  2. In proxy file, StockQuoteService, change localhost:8080 to localhost:81 the constructor.
  3. Run the Stock Quote client again.

The client sends the following (formatting changed for readability):

POST /soap/servlet/rpcrouter HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 1.0.3705.288)
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Content-Length: 529
Expect: 100-continue
Connection: Keep-Alive
Host: fastdata

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
               xmlns:tns="urn:xmltoday-delayed-quotes"
               xmlns:types="urn:xmltoday-delayed-quotes/encodedTypes"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<tns:getQuote>
<arg0 xsi:type="xsd:string">
IBM
</arg0>
</tns:getQuote>
</soap:Body>
</soap:Envelope>

The (formatted) response from the server is:

HTTP/1.1 100 Continue
HTTP/1.1 200 OK
Content-Type: text/xml;charset=utf-8
Content-Length: 468
Date: Wed, 18 Jun 2003 21:08:26 GMT
Accept-Encoding: gzip
Server: Apache Tomcat/4.0.1 (HTTP/1.1 Connector)
Set-Cookie: JSESSIONID=87576400D5F64880C7F430E0C6C20541;Path=/soap

<?xml version='1.0' encoding='UTF-8'?>
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                   xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<ns1:getQuoteResponse xmlns:ns1="urn:xmltoday-delayed-quotes"
                      SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<return xsi:type="xsd:float">
84.7
</return>
</ns1:getQuoteResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Return to top.

Resources

Accessing a .NET Web Service using Apache/SOAP and Java, although I hope there is an easier way!

Return to top.

Copyright © 2002-2003 Scott Nichol.
18-Jun-2003