This second article in this series dedicated to Web services comes as a sequel to the first one in which I started to tell you how you could build different kind of clients and services using MS SOAP Toolkit, Apache SOAP for Java and .NET Framework.
In the last article I mentioned something about the incompatibility between a MS SOAP client and an Apache SOAP server (the infamous xsi:type). As far as I know the version 2.2 didn't solve this problem, which is Apache SOAP Server is still expecting all parameters to have a type specified. But, the good news is that there is a work around to this problem. Many of you sent me e-mails asking how to do this. Well it is fairly simply.
Apache SOAP Server and clients
Do you remember the Apache SOAP server we wrote last time? Well another good news is that you don't have to change anything inside the server. You only need to change the deployment descriptor.
Let me tell you more about the workaround before writing anything. The major difference between MS implementation of SOAP and Apache for Java's is that the former relies on WSDL files to fully describe the service when the latter doesn't. This is why in the initial implementation of the Apache SOAP for Java the type is required to be specified for each parameter. The server has no other mean to know the type of the parameters unless is specified in the call. In the MS implementation the WSDL file has enough information and the server can figure out even if the call tells nothing about this.
Now, the solution to our problem is: when you deploy your service you can specify the type mapping of each parameter in your methods. The Java service uses this whenever there isn't enough information in the method call.
So you must add a mappings section to your deployment script. I modified the deployment descriptor for our service.
<isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment" id="urn:MyService ">
...
<isd:mappings>
<isd:map encodingStyle=http://schemas.xmlsoap.org/soap/encoding/
xmlns:x="" qname="x:num1"
xml2JavaClassName="org.apache.soap.encoding.soapenc.DoubleDeserializer"/>
<isd:map encodingStyle=http://schemas.xmlsoap.org/soap/encoding/
xmlns:x="" qname="x:num2"
xml2JavaClassName="org.apache.soap.encoding.soapenc.DoubleDeserializer"/>
</isd:mappings>
...
</isd:service>
That's all. Believe it or not that's all you have to change. The MS STK client doesn't need any change either. The same mention for the .NET client, don't change anything.
This will complete our incursion to building clients and services (simple ones) using the three major frameworks available. I must mention here that there are other frameworks for building SOAP servers and clients so don't be shy and publish source code and information so we can all learn about them. I remember seeing among people on SOAP Builders discussion group another name: Glue. They were at beta version last time a checked their web site but I'm sure they will quickly be releasing their product.
Generic client for Web Services
Ok so now we know hot to build a web service when we have enough information about the service itself: we are either the developers of the service or good friends with the developer, so we can get the "signature" of the service at the time we write the client.
Now, suppose you want to build a client that is able to call a service knowing only the name of the methods or something similar. My example will try to add two numbers searching a Math service and calling the methods. A more practical example could be a stock checker or something similar.
The steps I follow are:
- search the UDDI and find businesses which can help me solve my problem. The way we find the business is not standardized since there isn't a set of categories with businesses. For example we'll make the convention that Math businesses will be stored under Math category. Next we'll query for the URL where the web service stores the WSDL file.
- This is the first step to finalize our solution. I'll skip the code for this section since UDDI and related APIs are the subject of a future article.
- Once we have the WSDL file we'll parse this file and find out information about the web service. Based on this information we'll build a SOAP request. To build a soap request I used the low level API in STK since we don't know from the beginning how many parameters the service will call.
And here is the code:
Option Explicit On
Function BuildOperation( ByVal WSDLFileName As String, ByVal WSMLFileName As String, ByVal sOperation As String) As CWSDLOperation
Dim Reader As WSDLReader
Dim EnumService As EnumWSDLService
Dim Service As WSDLService
Dim EnumPort As EnumWSDLPorts
Dim Port As WSDLPort
Dim EnumOperation As EnumWSDLOperations
Dim Operation As WSDLOperation
Dim EnumMapper As EnumSoapMappers
Dim Mapper As SoapMapper
Dim Fetched As Long
Dim objWSDLOperation As CWSDLOperation
Dim objOperationPart As COperationPart
Dim bAddParts As Boolean
objWSDLOperation = New CWSDLOperation
Reader = New WSDLReader
Reader.Load(WSDLFileName, WSMLFileName)
Reader.GetSoapServices(EnumService)
EnumService.Next(1, Service, Fetched)
Do While Fetched = 1
Service.GetSoapPorts(EnumPort)
EnumPort.Next(1, Port, Fetched)
Do While Fetched = 1
Port.GetSoapOperations(EnumOperation)
EnumOperation.Next(1, Operation, Fetched)
Do While Fetched = 1
' check to see if the operation is here
bAddParts = False
If InStr(1, Operation.soapAction, "." + sOperation) > 0 Then
With objWSDLOperation
.m_Parts = New Collection
.m_PortAddress = Port.address
.m_SoapAction = Operation.soapAction
End With
bAddParts = True
Operation.GetOperationParts(EnumMapper)
EnumMapper.Next(1, Mapper, Fetched)
Do While Fetched = 1
If bAddParts Then
objOperationPart = New COperationPart
objOperationPart.m_Name = Mapper.partName
Call objWSDLOperation.m_Parts.Add(objOperationPart)
End If
EnumMapper.Next(1, Mapper, Fetched)
Loop
End If
EnumOperation.Next(1, Operation, Fetched)
Loop
EnumPort.Next(1, Port, Fetched)
Loop
EnumService.Next(1, Service, Fetched)
Loop
BuildOperation = objWSDLOperation
End Function
Comments
Join the conversation! Your thoughts help the community grow.