SOAP Implementations
As you have probably gathered by the cautions in
this chapter, there are two leading SOAP implementations available today:
Microsoft’s SOAP Toolkit (currently at version 2.0 SP2) and Apache SOAP (now at
version 2.2), which was originally created by IBM, who donated it to the Apache
Foundation. The Microsoft Toolkit supports all COM-compliant languages—in
particular, Visual Basic, and C#. The Apache implementation uses Java.
However, several other SOAP implementations are
available, as well. Table 15.3 lists several of the most popular
implementations.
TABLE 15.3 Some Popular SOAP
Implementations
At this point in time, there are two main issues
with the available SOAP implementa-tions: First, how well do they support an
overall Web Services implementation? Second, how interoperable they are? The
discussion of how well each of the leading SOAP implementations supports Web
Services appears in Chapter 16, in the discussion of WSDL and UDDI. The
question of interoperability among SOAP implementations is also a critical
issue for this nascent technology.
Microsoft SOAP Toolkit
The Microsoft SOAP Toolkit can be found at http://msdn.Microsoft.com/soap. You
must have the Visual Basic runtime files and the Windows Installer installed on
your sys-tem before you install the toolkit. The toolkit also requires Internet
Explorer 5.0, or higher, and will install MSXML 3.0 SP1 (if it isn’t already
present). You will also need Visual Basic or another development tool that can
compile DLL files, if you will be cre-ating your own.
The SOAP Toolkit contains the following elements:
A client-side component that
enables an application to invoke Web Services opera-tions that are described by
a WSDL document.
A server-side component that maps
those operations to COM object method calls. These calls are described by the
WSDL and Web Services Meta Language (WSML) files.
Marshaling and unmarshaling
components.
A WSDL/WSML document-generator
tool.
In order to exchange SOAP messages, you must set up
the SOAP server and the SOAP client. The server requires a system running
Internet Information Services (IIS). To set up the server, you can either
choose an Internet Server API (ISAPI) server or an Active Server Pages (ASP)
server as the listener. You then create an ActiveX DLL within Microsoft Visual
Basic that contains the actual server code (sample code comes with the
toolkit). Listing 15.1 shows a sample DLL that calculates a base rate or a
replacement cost, which you will need to compile with Visual Basic.
LISTING 15.1 CalcRateBase.vbs—DLL File
Public Function CalcBaseRate(ByVal RawBaseRate
As Double,
➥ ByVal RelativeFactor As Double,
ByVal TerritoryFactor As Double) As Double CalcBaseRate = RawBaseRate *
RelativeFactor * TerritoryFactor
End Function
Public Function CalcReplacementCost(ByVal BaseRate
As Double,
➥ ByVal ReplacementCostFactor As
Double) As Double
CalcReplacementCost
= BaseRate *
ReplacementCostFactor
End Function
Public Function DisplayVersion() As
String
DisplayVersion
= “Version 1.0”
End Function
Run the SOAP Toolkit Wizard and name your service
with the toolkit. Then select the COM DLL file to analyze, as shown in Figure
15.2.
Then select the services you would like to expose, as shown in Figure
15.3.
Next, create a virtual root using IIS and then
create the WSDL file and the WSML files that describe the Web Service. (More
about WSDL and WSML in Chapter 16.)
LISTING 15.2 RateCalcSvc.wsdl—Generated WSDL File
<?xml version=’1.0’ encoding=’UTF-16’ ?>
<!— Generated 09/24/01 by
Microsoft SOAP Toolkit WSDL File Generator, Version 1.02.813.0 —>
<definitions name
=’RateCalcSvc’ targetNamespace = ‘http://tempuri.org/wsdl/’
xmlns:wsdlns=’http://tempuri.org/wsdl/’ xmlns:typens=’http://tempuri.org/type’
xmlns:soap=’http://schemas.xmlsoap.org/wsdl/soap/’ xmlns:xsd=’http://www.w3.org/2001/XMLSchema’
xmlns:stk=’http://schemas.microsoft.com/soap-toolkit/wsdl-extension’
xmlns=’http://schemas.xmlsoap.org/wsdl/’>
<types>
<schema
targetNamespace=’http://tempuri.org/type’
xmlns=’http://www.w3.org/2001/XMLSchema’ xmlns:SOAP-ENC=’http://schemas.xmlsoap.org/soap/encoding/’
xmlns:wsdl=’http://schemas.xmlsoap.org/wsdl/’
elementFormDefault=’qualified’>
</schema>
</types>
<message
name=’Class1.CalcBaseRate’>
<part name=’RawBaseRate’ type=’xsd:float’/>
<part name=’RelativeFactor’ type=’xsd:float’/> <part
name=’TerritoryFactor’ type=’xsd:float’/>
</message>
<message
name=’Class1.CalcBaseRateResponse’> <part name=’Result’
type=’xsd:float’/>
</message>
<message
name=’Class1.CalcReplacementCost’> <part name=’BaseRate’
type=’xsd:float’/>
<part
name=’ReplacementCostFactor’
type=’xsd:float’/>
</message>
<message
name=’Class1.CalcReplacementCostResponse’> <part name=’Result’
type=’xsd:float’/>
</message>
<message name=’Class1.DisplayVersion’>
</message>
<message
name=’Class1.DisplayVersionResponse’> <part name=’Result’
type=’xsd:string’/>
</message>
<portType
name=’Class1SoapPort’> <operation name=’CalcBaseRate’
parameterOrder=’RawBaseRate
RelativeFactor TerritoryFactor’> <input
message=’wsdlns:Class1.CalcBaseRate’ />
<output message=’wsdlns:Class1.CalcBaseRateResponse’
/> </operation>
<operation
name=’CalcReplacementCost’ parameterOrder=’BaseRate ReplacementCostFactor’>
<input
message=’wsdlns:Class1.CalcReplacementCost’ />
<output
message=’wsdlns:Class1.CalcReplacementCostResponse’ /> </operation>
<operation
name=’DisplayVersion’ parameterOrder=’’> <input
message=’wsdlns:Class1.DisplayVersion’ />
<output
message=’wsdlns:Class1.DisplayVersionResponse’ /> </operation>
</portType>
<binding
name=’Class1SoapBinding’ type=’wsdlns:Class1SoapPort’ > <stk:binding
preferredEncoding=’UTF-16’/>
<soap:binding
style=’rpc’
transport=’http://schemas.xmlsoap.org/soap/http’ /> <operation
name=’CalcBaseRate’ >
<soap:operation
soapAction=’http://tempuri.org/action/Class1.CalcBaseRate’ />
<input>
<soap:body use=’encoded’
namespace=’http://tempuri.org/message/’
encodingStyle=’http://schemas.xmlsoap.org/soap/encoding/’ />
</input>
<output>
<soap:body use=’encoded’
namespace=’http://tempuri.org/message/’ encodingStyle=’http://schemas.xmlsoap.org/soap/encoding/’
/>
</output>
</operation>
<operation
name=’CalcReplacementCost’ > <soap:operation
soapAction=’http://tempuri.org/action/Class1.CalcReplacementCost’
/> <input>
<soap:body use=’encoded’
namespace=’http://tempuri.org/message/’ encodingStyle=’http://schemas.xmlsoap.org/soap/encoding/’
/>
</input>
<output>
<soap:body use=’encoded’
namespace=’http://tempuri.org/message/’
encodingStyle=’http://schemas.xmlsoap.org/soap/encoding/’ />
</output>
</operation>
<operation name=’DisplayVersion’
> <soap:operation
soapAction=’http://tempuri.org/action/Class1.DisplayVersion’ />
<input>
<soap:body use=’encoded’
namespace=’http://tempuri.org/message/’
encodingStyle=’http://schemas.xmlsoap.org/soap/encoding/’ />
</input>
<output>
<soap:body use=’encoded’
namespace=’http://tempuri.org/message/’
encodingStyle=’http://schemas.xmlsoap.org/soap/encoding/’ />
</output>
</operation>
</binding>
<service
name=’RateCalcSvc’ >
<port name=’Class1SoapPort’
binding=’wsdlns:Class1SoapBinding’ > <soap: address
location=’http://10.68.1.7/rates/RateCalcSvc.WSDL’ />
</port>
</service>
</definitions>
And Listing 15.3 shows the corresponding WSML.
LISTING 15.3 RateCalcSvc.wsml—Generated WSML File
<?xml version=’1.0’ encoding=’UTF-16’ ?>
<!— Generated 09/24/01 by
Microsoft SOAP Toolkit WSDL File Generator, Version 1.02.813.0 —>
<servicemapping
name=’RateCalcSvc’> <service name=’RateCalcSvc’>
<using PROGID=’Project1.Class1’ cachable=’0’
ID=’Class1Object’ /> <port name=’Class1SoapPort’>
<operation
name=’CalcBaseRate’>
<execute uses=’Class1Object’
method=’CalcBaseRate’ dispID=’1610809344’>
<parameter callIndex=’1’
name=’RawBaseRate’ elementName=’RawBaseRate’ />
<parameter callIndex=’2’
name=’RelativeFactor’ elementName=’RelativeFactor’ />
<parameter callIndex=’3’
name=’TerritoryFactor’ elementName=’TerritoryFactor’ />
<parameter callIndex=’-1’
name=’retval’ elementName=’Result’ /> </execute>
</operation>
<operation
name=’CalcReplacementCost’>
<execute uses=’Class1Object’
method=’CalcReplacementCost’ dispID=’1610809345’>
<parameter callIndex=’1’ name=’BaseRate’
elementName=’BaseRate’ /> <parameter callIndex=’2’
name=’ReplacementCostFactor’
elementName=’ReplacementCostFactor’ />
<parameter callIndex=’-1’
name=’retval’ elementName=’Result’ /> </execute>
</operation>
<operation
name=’DisplayVersion’> <execute uses=’Class1Object’
method=’DisplayVersion’ dispID=’1610809346’>
<parameter callIndex=’-1’
name=’retval’ elementName=’Result’ /> </execute>
</operation>
</port>
</service>
</servicemapping>
Finally, create an ASP application to handle incoming SOAP requests.
To set up the client, write a Visual Basic Scripting Edition (VBScript)
application that calls the operations that your server provides. Listing 15.4
shows our sample client.
LISTING 15.4 SoapClient.vbs—Sample SOAP Client
Option Explicit
Dim soapClient,BaseRate, RelativityFactor, TerritoryFactor,
AdjustedBase, ➥ ReplaceCost, ReplaceCostFactor,
TotalCost
set soapclient = CreateObject(“MSSOAP.SoapClient”) On Error Resume Next
Call soapclient.mssoapinit(“http://mysite.com/rates/RateCalcSvc.wsdl”, ➥ “RateCalcSvc”, “Class1SoapPort”)
if err <>
0 then
wscript.echo “Initialization Failed “ +
err.description else
wscript.echo “Initialization Successful “ end if
wscript.echo “” wscript.echo “”
BaseRate = 303
RelativityFactor = .97
TerritoryFactor = 1.2
ReplaceCostFactor = .21
AdjustedBase = 0
Apache SOAP
You can find the open-source Apache SOAP 2.2 at http://xml.apache.org/soap. You
will need to have the following tools installed on your system before you
install Apache SOAP:
Java 1.1 or higher.
Apache Jakarta Tomcat 3.2.1 Web
server and servlet engine, available at
http://jakarta.apache.org/
Apache Xerxes XML Parser 1.2.3, found
at http://xml.apache.org/xerces-j/
JavaMail (mail.jar), found at http://java.sun.com/products/javamail/, and
the JavaBeans Activation Framework (activation.jar), found at
http://java.sun.com/products/beans/glasgow/jaf.html
Once all the tools (including Apache SOAP) are installed and your CLASSPATH is cor-rectly updated, you must
configure Tomcat so that it can detect Apache SOAP. Edit the file \jakarta-tomcat-3.2\conf\server.xml and put
the following entry near the end of the file:
<Context path=”/soap” docBase=”C:/soap-2_0/webapps/soap”
reloadable=”true”> </Context>
Next, launch Tomcat. You should see the output:
Starting tomcat. Check
logs/tomcat.log for error
messages
Now, point your browser to http://localhost/soap (including the port number, if you have chosen a port other than 80) to
launch the Apache SOAP system.
Next, we need to write a Web Service in Java. Listing 15.5 shows a
sample service that calculates a rate (in this case, returning the same value
every time).
LISTING 15.5 Exchange.java—Sample Web Service
public class Exchange
{
public
float getRate( String
BaseRate, String ReplacementCostFactor )
{
System.out.println( “getRate( “ +
BaseRate + “, “ + ReplacementCostFactor + “ )” );
return
1234.56F;
}
}
Put the directory that contains the Exchange class on your CLASSPATH and compile it. Restart Tomcat and run the admin client from your
browser. From the admin client, click Deploy, and you’ll see the screen shown
in Figure 15.5.
Enter the necessary information, as shown in Figure 15.5, and click the
Deploy button again. If you have successfully deployed your Web Service, you
should see the screen shown in Figure 15.6.
Next, we must run our client application. Listing 15.6 shows a simple
example of a Java client.
LISTING 15.6 Client.java—Sample
SOAP Client
import java.net.*; import java.util.*; import org.apache.soap.*;
import org.apache.soap.rpc.*; public class Client
{
public
static void main( String[] args
) throws Exception
{
URL url = new URL(
“http://localhost/soap/servlet/rpcrouter” ); String urn = “urn:demo1:exchange”;
Call call = new Call(); // prepare to invoke the
Service call.setTargetObjectURI( urn );
call.setMethodName(
“getRate” );
call.setEncodingStyleURI( Constants.NS_URI_SOAP_ENC
); // the default Vector v = new Vector();
v.addElement( new Parameter( “BaseRate”,
String.class, “12.34”, null ) ); v.addElement( new Parameter(
“ReplacementCostFactor”, String.class,
➥ ”56.78”, null ) );
call.setParams( v ); try
{
System.out.println( “Service
invoked:\n” + “ URL= “ + url + “\n URN= “ + urn );
Response response = call.invoke( url, “” ); //
invoke the Service
if( !response.generatedFault() )
{
Parameter r = response.getReturnValue(); //
response was OK
System.out.println( “Result= “ + r.getValue() );
}
else
{
Fault f = response.getFault(); // error
System.err.println( “Fault= “ + f.getFaultCode() +
“, “ +
f.getFaultString()
);
}
}
catch(
SOAPException e )
// error sending
call
{
System.err.println(
“SOAPException= “ + e.getFaultCode() + “, “ + e.getMessage() );
}
}
}
Compile and run the client, and you should see the following output:
Service invoked:
URL= http://localhost/soap/servlet/rpcrouter
URN= urn:demo1:exchange
Result= 1234.56
Finally, the output from the Tomcat server should include the following:
Processing SOAP request...
GetRate (12.34, 56.78
)
We have successfully invoked our Web Service!
Interoperability Issues
Interoperability among different SOAP implementations is especially
important, because, well, interoperability is what Web Services are all about.
What’s the point of having loosely coupled services if they can only talk to
systems that use the same implementa-tion? The fact that interoperability is an
issue at all is a symptom of the fact that Web Services are still on the
bleeding edge. This issue is currently a topic of much discussion, and there is
a good chance that the issue will be resolved in 2002.
The fundamental cause of most interoperability problems has to do with a
single word: may. When the SOAP
specification says that a particular feature
may be implemented, it opens up
the option that a particular vendor may choose not to implement the feature.
Another implementation, however, may use the feature, causing the two
implementations to be incompatible with each other.
Interoperability issues with SOAP implementations fall into three
general categories:
Transport problems, namely those
involving the HTTP SOAPAction header.
XML issues, typically involving
the Byte Order Mark.
SOAP problems, involving the mustUnderstand attribute or other unevenly
imple-mented features of the specification.
Let’s look at each of these issues in turn.
First, as discussed earlier, the SOAPAction header is mandatory in SOAP messages that go over HTTP. However, the
SOAP specification allows for a null SOAPAction, which appears like this:
SOAPAction:
However, Apache SOAP does not have any way of interpreting a null header
value, caus-ing messages that have null values to be incompatible with those
SOAP messages that have this header.
Second, there is the issue of the Byte Order Mark (BOM). A BOM is a
nonprintable character that indicates the order of the bytes in a two-byte
character encoding (like those for Japanese and Chinese). BOMs are required for
two-byte encodings such as UTF-16, but they serve little purpose (even though
they are not forbidden) for single-byte encod-ings such as UTF-8. Apache SOAP,
for example, cannot interpret UTF-8-encoded SOAP messages that have a BOM, even
though many text editors (such as Notepad) automati-cally place a BOM at the
beginning of UTF-8-encoded text.
Finally, the third category of incompatibility issues has to do with
inconsistent imple-mentations of SOAP. Table 15.4 contains a reasonably
comprehensive accounting of the current state of SOAP feature support in the
three leading SOAP implementations.
TABLE 15.4 SOAP Compatibility Matrix
Whenever a SOAP feature is not fully supported across different
implementations, there is always the possibility of a failure to exchange SOAP
messages correctly. The fact that relatively few rows in Table 15.4 contain
only “Yes” is a clear indication of the immatu-rity of the SOAP protocol.
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.