Saturday, December 18, 2010

Using Google Maps service in a Pascal based Web Application

My final team assignment of Information Retrieval (IR) class allows us to create any kind of IR system, and we decided to create a food ingredients and restaurant search system. It displays ingredients for a chosen food and then displays 10 top restaurants that provide the food. For the first one, it's simply a database approach. But the latter is a Geographic IR (GIR). Instead of creating it from scratch (which could take probably a whole life), we decided to use google maps service.

Due to the requirement that the system must be accessible from web, it's splitted into two parts: client and server. The client part is coded by my friend and the server part is mine. The client part is coded with ExtJS and we use JSON to communicate between the client and server. Since the server is a Service Oriented Application (SOA), it's no problem what language it's written in. And since I'm a Pascal geek (you can call me maniac if you want), I choose to write it in Pascal.

To create the server, I use fpWeb components available from standard Lazarus distribution. The server itself connects to Google Maps service to look for the coordinates. Hmm... how can the server do this? Luckily, there are two powerful networking components and libraries for Pascal, namely lNet and Synapse. I used to lNet due to its component based approach, however after struggling a bit, lNet seems to leak some features I need (esp. proxy support because my campus' internet access is protected by that). Then another Pascalian told me that it's very easy to do with Synapse. And so it goes:

with THTTPSend.Create do
  try
    ProxyHost := ConfigFile.ReadString('proxy','host','');
    ProxyPort := ConfigFile.ReadString('proxy','port','');
      URL := Format('http://maps.google.com/maps/geo?q=%s&output=json&oe=utf8&sensor=true' +
        '&key=%s',[QueryStr,GoogleAPIKey]);
      if not HTTPMethod('GET',URL) then begin
        AResponse.Content := Format('Error %d: %s',[ResultCode,ResultString]);
      end else begin
        AResponse.Contents.LoadFromStream(Document);
      end;
      AppendToLog(Headers.Text + AResponse.Content);
  finally
      Free;
    end;
  Handled := true;

The server uses TIniFile (as ConfigFile in above code) to store and retrieve proxy information so it can be adjusted without recompilation. QueryStr is the string that we want Google Maps to look for and GoogleAPIKey is the... err.. API key to access Google Maps. FYI, I'm using version 2 of the API which still requires a key, version 3 doesn't need it anymore.

It doesn't yet show anything useful, only the original JSON from Google Maps. Later, this JSON must be processed and merged with database result, and then sent to the client to be processed further. But after all... it's done in Pascal :)

No comments:

Post a Comment