rockneybot has asked for the wisdom of the Perl Monks concerning the following question:

Hi all. I've been messing with Google Maps API ( who hasn't? ). I've got my own local Tiger/Line address data. I can feed it addresses via Geo::Coder::US and get useful lat/long coordinates for mapping. My dumb perl script that does this is called in a PHP page ( I know, I should learn mod_perl ), using the PHP exec function. This is suckingly slow because it calls my little Perl script in series to get the lat/long. So, I decided to try to setup a Perl SOAP server. I've followed the "instructions" in this article: http://www.developer.com/tech/article.php/3566631. However, it isn't working for me. Some component is breaking down, and I'm not sure how to trace it. Here's the code peices. At the bottom, I'll post the error I get.
[root@mycomputer html]# ls -lah /data/geocode/ca/geocode_ca.db -rw-r--r-- 1 root root 60M May 23 18:04 /data/geocode/ca/geocode_ca.db [root@mycomputer html]# cat /usr/lib/perl5/site_perl/5.8.8/geocode.pm package geocode; sub geocode { # Designate the location of the geocoding database $geocodes = "/data/geocode/ca/geocode_ca.db"; # Retrieve the address value passed into the function my ($class,$address) = @_; # Point to the geocoding database Geo::Coder::US->set_db($geocodes); # Retrieve coordinates from geocoding database my ($coords) = Geo::Coder::US->geocode($address); # Return the latitudinal and longitudinal coordinates return $coords->{lat},$coords->{long}; } return 1; [root@mycomputer html]# cat geocodews.pl #!/usr/bin/perl -w use Geo::Coder::US; use SOAP::Transport::HTTP; require("geocode.pm"); SOAP::Transport::HTTP::CGI->dispatch_to('geocode')->handle; [root@mycomputer html]# cat geocodeclient.pl #!/usr/bin/perl -w use SOAP::Lite; $soap = SOAP::Lite -> uri('http://localhost/geocode') -> proxy('http://localhost/geocodews.pl'); $address = "900 Cherry Ave., San Bruno, CA"; my $result = $soap->call('geocode', $address); my $latitude = $result->result; my $longitude = $result->paramsout; print "Latitude: ".$latitude."\n"; print "Longitude: ".$longitude."\n";
So, when I run geocodeclient.pl, I get this error:
[root@mycomputer html]# ./geocodeclient.pl not well-formed (invalid token) at line 1, column 1, byte 1 at /usr/li +b/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/XML/Parser.pm line +187 #!/usr/bin/perl -w use Geo::Coder::US; use SOAP::Transport::HTTP; require("geocode.pm"); SOAP::Transport::HTTP::CGI->dispatch_to('geocode')->handle; at ./geocodeclient.pl line 11
I'm totally hacking things together here, but a little tip on how to troubleshoot this would be much appreciated. Thank you!

Replies are listed 'Best First'.
Re: SOAP::Lite geocode server
by rhesa (Vicar) on May 25, 2006 at 00:25 UTC
    in geocodeclient.pl, change use SOAP::Lite; to
    use SOAP::Lite ( +trace => 'all', readable => 1, outputxml => 1, ); # +for debugging
    It'll show you all the data exchange, and might help you to track down the issue.

    I assume you're running the soap server under Apache, right? Check the error log, there's probably something there that'll be closer to the problem. Show us what it says if you can't figure it out.

    Some additional suggestions:

    1. use strict and warnings
    2. move the use Geo::Coder::US; from gecodews.pl to geocode.pm where it belongs
    3. I'd recommend returning your values as a hash reference, instead of pulling one value out of result and the other from paramsout:
      1. in geocode.pm, simply return $coords
      2. in geocodeclient.pl, change it to
        my $result = $soap->call('geocode', $address); my $coords = $result->result; print "Latitude: ".$coords->{lat}."\n"; print "Longitude: ".$coords->{lon}."\n";
      I followed your recommendations. Here are the results of the trace (truncated):
      SOAPAction: "http://localhost/geocode#geocode" <?xml version="1.0" encoding="UTF-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <geocode xmlns="http://localhost/geocode"> <c-gensym3 xsi:type="xsd:string">900 Cherry Ave., San Bruno, CA< +/c-gensym3> </geocode> </soap:Body> </soap:Envelope> SOAP::Transport::HTTP::Client::send_receive: HTTP::Response=HASH(0x859 +a190) SOAP::Transport::HTTP::Client::send_receive: HTTP/1.1 200 OK Connection: close Date: Thu, 25 May 2006 01:11:56 GMT Accept-Ranges: bytes ETag: "16d01ff-94-89b58cc0" Server: Apache/2.2.0 (Fedora) Content-Length: 148 Content-Type: text/plain; charset=UTF-8 Last-Modified: Thu, 25 May 2006 01:11:55 GMT Client-Date: Thu, 25 May 2006 01:11:56 GMT Client-Peer: 127.0.0.1:80 Client-Response-Num: 1 #!/usr/bin/perl -w use strict; use SOAP::Transport::HTTP; require("geocode.pm"); SOAP::Transport::HTTP::CGI->dispatch_to('geocode')->handle; Can't call method "result" without a package or object reference at ./ +geocodeclient.pl line 13. SOAP::Transport::HTTP::Client::DESTROY: () SOAP::Data::DESTROY: () SOAP::Data::DESTROY: () SOAP::Data::DESTROY: () SOAP::Transport::DESTROY: () SOAP::Serializer::DESTROY: () SOAP::Deserializer::DESTROY: () SOAP::Lite::DESTROY: () SOAP::Deserializer::DESTROY: () SOAP::Parser::DESTROY: () SOAP::Transport::DESTROY: () SOAP::Serializer::DESTROY: () SOAP::Data::DESTROY: () SOAP::Data::DESTROY: () SOAP::Lite::DESTROY: ()
        Aha! Your soap server isn't executed, it's returned by the web server as a plaintext document!

        You need to make sure that your geocodews.pl is executed as a perl script by the web server. The simplest way to do that, I guess, is by putting it in your cgi-bin directory. Change the proxy() call to reflect the new url of the soap server.

Re: SOAP::Lite geocode server
by sgifford (Prior) on May 25, 2006 at 05:39 UTC