Poking at ESRI's Public ArcWeb Services

In the wake of Google's mapping API release, ESRI has opened up some of its SOAP-based web services for limited public use to see if they can lure in the map hackers. I played around with a trial subscription to ArcWeb services two years ago, and this seemed a good opportunity to dust off the old code and try again with the public services.

As before I'm using ZSI, the Zolera SOAP Infrastructure for Python. Happily, it's improved, and now features generation of service stubs and types from WSDL. Two years ago I was faced with implementing my own ArcWeb types. Now I can use ZSI's wsdl2py.py script to generate type and client stub modules from the ESRI authentication and map image WSDL URLs, which allows me to abandon my earlier code and start fresh:

$ wsdl2py.py -u https://arcweb.esri.com/services/v2/Authentication.wsdl
$ wsdl2py.py -u https://arcweb.esri.com/services/v2/MapImage.wsdl

resulting in the creation of three files:

$ ls *.py
Authentication_services.py  MapImage_services.py
MapImage_services_types.py

Following the example, I quickly coded up a request for an authenticated token using my existing ESRI global account:

import sys

# modules generated by wsdl2py
from Authentication_services import *

opts = {'tracefile': sys.stdout}

# Auth service
auth_loc = AuthenticationLocator()
auth_serv = auth_loc.getIAuthentication(**opts)

# Get a token
tok_req = getToken1InWrapper()
tok_req._username = '******'
tok_req._password = '******'
tok_resp = auth_serv.getToken(tok_req)
token_ustr = tok_resp._Result

and was informed that I could not use the public services with this account because I had an expired non-public subscription. Annoying, this was, and seems to support James Fee's contention that the public service release caught ESRI itself off-guard. So I marched through the ESRI account drill again, and continued on. The following code gets a token and uses it to make the simplest possible request for a map image and print the resulting map image URL:

## awmap.py

import sys

# modules generated by wsdl2py
from Authentication_services import *
from MapImage_services import *

opts = {'tracefile': sys.stdout}

def set_map_extent(o, e):
    o.Set_minx(e['minx'])
    o.Set_miny(e['miny'])
    o.Set_maxx(e['maxx'])
    o.Set_maxy(e['maxy'])

def set_map_size(o, s):
    o.Set_width(s[0])
    o.Set_height(s[1])

# extent and datasource
extent = {'minx': -105.14, 'miny': 40.53, 'maxx': -105.04, 'maxy': 40.63}
size = [400, 400]
datasource = 'GDT.Streets.US'

def main():
    # Auth service
    auth_loc = AuthenticationLocator()
    auth_serv = auth_loc.getIAuthentication()

    # get a token
    tok_req = getToken1InWrapper()
    tok_req._username = '******'
    tok_req._password = '******'
    tok_resp = auth_serv.getToken(tok_req)
    token_ustr = tok_resp._Result

    # map service implementation
    map_loc = MapImageLocator()
    map_serv = map_loc.getIMapImage()

    # get map image url
    map_req = getMap0InWrapper()
    map_req._token = token_ustr
    map_req._mapExtent = ns4.Envelope_Def()
    set_map_extent(map_req._mapExtent, extent)
    map_req._mapImageOptions = ns5.MapImageOptions_Def()
    map_req._mapImageOptions._dataSource = datasource
    map_resp = map_serv.getMap(map_req)

    print map_resp._Result._mapUrl

if __name__ == '__main__':
    main()

Running the script:

$ [sean@lenny arcweb]$ python awmap.py
http://redlandsarcweb.esri.com/out/maps/GDT_ArcWeb_US_2_blackmap2248241332.png

Produced the following image at the URL:

/files/GDT_ArcWeb_US_2_pimap257553707.png

In my opinion, ESRI needs to make some cosmetic improvements to its default map if it is going to catch on with web designers and programmers. I know for a fact that the software behind the service allows for great looking maps, so let's see some fine cartography in this default map. This is the first look that many people will have of the public ESRI maps, so it must look sharp.

This exercise increases my fondness for SOAP very little, but ZSI makes using services such as these a fairly painless task for an intermediate Python programmer.