Saturday, January 5, 2008

Using GroovyWS with the TerraService (Part 1)

I got recently a post on the difficulty of retrieving complex elements by some webservices, I will try to clarify some issues on this in this post using the Microsoft Terra webservice.
The TerraService is an WebService API which allows you to query the Microsoft TerraServer database of high resolution aerial imagery. Among other things, you can:
  • Find Geographic and Image Coordinates by Place Name
  • Convert coordinates from one projection system to another
  • Fetch tile meta-data and image-data
Today, I will just concentrate on using the search API to show how to deal with arrays with GroovyWS.

If you look at the TerraService WSDL you will notice that some functions return arrays. This is clear from the following part of the WSDL:


<s:element name="GetPlaceList">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="placeName" type="s:string"/>
<s:element minOccurs="1" maxOccurs="1" name="MaxItems" type="s:int"/>
<s:element minOccurs="1" maxOccurs="1" name="imagePresence" type="s:boolean"/>
</s:sequence>
</s:complexType>
</s:element>

<s:element name="GetPlaceListResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="GetPlaceListResult" type="tns:ArrayOfPlaceFacts"/>
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name="ArrayOfPlaceFacts">
<s:sequence>
<s:element minOccurs="0" maxOccurs="unbounded" name="PlaceFacts" type="tns:PlaceFacts"/>
</s:sequence>
</s:complexType>

<wsdl:message name="GetPlaceListSoapIn">
<wsdl:part name="parameters" element="tns:GetPlaceList"/>
</wsdl:message>
<wsdl:message name="GetPlaceListSoapOut">
<wsdl:part name="parameters" element="tns:GetPlaceListResponse"/>
</wsdl:message>

<wsdl:operation name="GetPlaceList">
<wsdl:input message="tns:GetPlaceListSoapIn"/>
<wsdl:output message="tns:GetPlaceListSoapOut">
</wsdl:operation>

Therefore, the following call to GetPlaceList will return an object embedding an array of PlaceFacts.

def proxy = new WSClient("http://terraservice.net/TerraService.asmx?WSDL", this.class.classLoader)
def plist = proxy.GetPlaceList("mountain view", 5, true)

From this object, one can call getPlaceFacts to get the array. Here we asked for its size:

println plist.placeFacts.size()

Then one call go through all the places returned by the call to the TerraService:

for (pfact in plist.placeFacts) {
println pfact.place.city
println pfact.place.state
}

All this might look a bit cryptic, and it is probably. The fact is that there is no magic. When you want to call a remote service, you have to know its signature. If you don't have any manual then you have to read and understand the WSDL which represents the contract you are offered.

If you have any idea on how thing could be improved by GroovyWS for helping you in writing your scripts then do not hesitate to give your feedback.

1 comment:

Rick Cromer said...

Chez, have you had any luck on tracing down what's causing the Nullpointer exception when running against some web services?

Ref:
http://www.nabble.com/HELP-PLEASE!-GroovyWS-Null-pointer-exception-whilst-running-stock-quote-example-td14759513.html