Now we can write an application that binds to the service and
calls both its methods:
package javasoap.book.ch5;
import electric.registry.RegistryException;
import electric.registry.Registry;
public class BasicTradingClient {
public static void main(String[] args) throws Exception
{
try {
IBasicTradingService srv =
(IBasicTradingService)Registry.bind(
"http://georgetown:8004/glue/urn:BasicTradingService.wsdl",
IBasicTradingService.class);
String[] stocks = { "MINDSTRM", "MSFT", "SUN" };
int total = srv.getTotalVolume(stocks);
System.out.println("Total Volume is " + total);
Object[] multiParams = { "MINDSTRM", new Integer(100),
new Boolean(true) };
String desc = srv.executeTrade(multiParams);
System.out.println("Trade Description: " + desc);
}
catch (RegistryException e)
{
System.out.println(e);
}
}
}
As we've seen before, GLUE allows us to use familiar Java
programming syntax without having to think about the underlying SOAP
constructs. This holds true for the passing of array parameters as well.
Everything is pretty much handled for us after the interface is bound to the
service.
There are some interesting things to see in the SOAP request
envelopes generated by this example. Here is the SOAP envelope for the getTotalVolume( ) method invocation:
<soap:Envelope
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'
xmlns:soapenc='http://schemas.xmlsoap.org/soap/encoding/'
soap:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
<soap:Body>
<n:getTotalVolume xmlns:n='urn:BasicTradingService'>
<arg0 href='#id0'/>
</n:getTotalVolume>
<id0 id='id0' soapenc:root='0'
xmlns:ns2='http://www.themindelectric.com/package/java.lang/'
xsi:type='soapenc:Array' soapenc:arrayType='xsd:string[3]'>
<i xsi:type='xsd:string'>MINDSTRM</i>
<i xsi:type='xsd:string'>MSFT</i>
<i xsi:type='xsd:string'>SUN</i>
</id0>
</soap:Body>
</soap:Envelope>
The Body element starts off like
we've seen before; the envelope is qualified by a namespace identifier, soap, which represents the namespace of the SOAP
envelope. The first child element of the SOAP body is getTotalVolume, which of course is the name of the
service method being invoked. getTotalVolume is
namespace-qualified using the name of the service. The only child element of
getTotalVolume is arg0,
which represents the parameter passed to the method. But this isn't the array
we passed; it's a reference to the array. This is a significant difference
between the ways that GLUE and the Apache SOAP API generate this call. Apache
SOAP puts the array in the envelope as a child element of getTotalVolume, and GLUE uses a reference and serializes
the array after the getTotalVolume element
terminates. So the parameter is serialized as arg0,
and includes an href attribute with the value #id0. No data is included, as the array resides
elsewhere.
The array that we passed as a parameter follows the getTotalVolume element. It's named id0, although the element name itself, which is generated
by GLUE, is not important. The id attribute is
assigned a value of id0, which coincides with the
href value used in the getTotalVolume element. GLUE generates the soapenc:root attribute with a value of 0, meaning that
this element is not considered the root of an object graph. (GLUE seems to
include that attribute automatically.) Next we see
a declaration of a namespace identifier called ns2
that seems to identify the internal GLUE package for java.lang; however, the ns2
namespace identifier is never used. The xsi:type
and soapenc:arrayType attributes are set up in the
same way as in the Apache SOAP examples. Finally, the elements of the array
are serialized. The only difference between this example and the one generated
by Apache SOAP is in the name of the array elements themselves. Apache SOAP
named these elements item, and GLUE named them
i. The names don't matter; the result is the
same.
This example gives us a good opportunity to see two equally
valid ways to serialize arrays. It's important that SOAP implementations
understand these different styles if they are to interoperate. This is one of
the reasons we keep showing the SOAP envelopes generated by the examples.
Becoming familiar with the various styles of serialization will help you down
the road if you run into problems getting applications based on different
implementations to communicate correctly. (Did I say if
?)
Let's take a look at the SOAP envelope for the call to the executeTrade service method. This method takes a
heterogeneous array as a parameter. It too uses a reference to a separately
serialized array, this time encoded as xsd:anyType:
<soap:Envelope
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'
xmlns:soapenc='http://schemas.xmlsoap.org/soap/encoding/'
soap:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
<soap:Body>
<n:executeTrade xmlns:n='urn:BasicTradingService'>
<arg0 href='#id0'/>
</n:executeTrade>
<id0 id='id0' soapenc:root='0'
xmlns:ns2='http://www.themindelectric.com/package/java.lang/'
xsi:type='soapenc:Array' soapenc:arrayType='xsd:anyType[3]'>
<i xsi:type='xsd:string'>MINDSTRM</i>
<i xsi:type='xsd:int'>100</i>
<i xsi:type='xsd:boolean'>true</i>
</id0>
</soap:Body>
</soap:Envelope>
New on the Java Boutique:
New Review:
Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling
API boasts simplicity, ease-of-integration, a well-rounded feature
set, and it's free!
New Applet:
Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA
sequences into three useful formats.
Elsewhere on internet.com:
WebDeveloper Java
Lots of Java information on webdeveloper.com
WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.
ScriptSearch Java
Hundreds of free Java code files to download.
jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.