+ Start a Discussion
David HollandDavid Holland 

Geolocation fields not updating on callout from GoogleMaps trigger.

Hi everyone.

I have created a new 'Geolocation' field on a custom object and am trying to get a trigger to fire which will populate the latitude and longitude via a callout to Google Maps.

I have added Google Maps to the remote site settings. This is in a Sandbox environment.

CLASS:

public class LocationCallouts {
 
     @future (callout=true)  // future method needed to run callouts from Triggers
      static public void getLocation(id Id){
        // gather account info
        Transaction__c t = [SELECT Street__c, City__c, County__c, Country__c, Postcode__c FROM Transaction__c WHERE id =: Id];
 
        // create an address string
        String address = '';
        if (t.Street__c!= null)
            address += t.Street__c+', ';
        if (t.City__c!= null)
            address += t.City__c+', ';
        if (t.County__c!= null)
            address += t.County__c+', ';
        if (t.Postcode__c != null)
            address += t.Postcode__c +', ';
        if (t.Country__c!= null)
            address += t.Country__c;
 
        address = EncodingUtil.urlEncode(address, 'UTF-8');
 
        // build callout
        Http h = new Http();
        HttpRequest req = new HttpRequest();
        req.setMethod('GET');
        req.setTimeout(60000);
 
        try{
            // callout
            HttpResponse res = h.send(req);
 
            // parse coordinates from response
            JSONParser parser = JSON.createParser(res.getBody());
            double lat = null;
            double lon = null;
            while (parser.nextToken() != null) {
                if (parser.getText() == 'coordinates'){
                       parser.nextToken(); // object start
                           String txt = parser.getText();
                           parser.nextToken();
                           if (txt == 'lat')
                               lat = parser.getDoubleValue();
                           else if (txt == 'lng')
                               lon = parser.getDoubleValue();
                }
            }
 
            // update coordinates if we get back
            if (lat!= null){
                t.Location__Latitude__s = lat;
                t.Location__Longitude__s = lon;
                update t;
            }
 
        } catch (Exception e) {
        }
    }
}

TRIGGER:


// Trigger runs getLocation() on Transaction
trigger SetGeolocation on Transaction__c (after insert, after update) {
    for (Transaction__c t : trigger.new){
        if (t.Location__Latitude__s == null){
            LocationCallouts.getLocation(t.id);
        }
    }
}

I am sure I have just done something stupid but cannot see what I have done wrong!!

Any help would be greatly appreciated.
BritishBoyinDCBritishBoyinDC

I think it's an issue with the JSON - when I request the data, I see geometry and location, but not coordinates

 

Also - the LAT/LONG is stored in a location object by the looks of it, so I think the parser needs updating...maybe try serializing the response into an object?

 

See here for example:

http://wiki.developerforce.com/page/Getting_Started_with_Apex_JSON

ericmonteericmonte

i'm in the same boat. did you manage to resolve the issue? if so can you share?

David HollandDavid Holland

Well, I must be honest, after updating to the newest API in our testing sandbox, this coding worked perfectly. I don't believe it has caught up in Live yet, but Sandbox is working fine for us now.

ericmonteericmonte

I am drawing a blank on how to update my developer sandbox api version, can you tell me how you refresh the api version?

ericmonteericmonte

So i tried updating the API version on my class, trigger, and my project to winter 13. And still getting nowhere.

 

Class

public with sharing class GoogleMapsCallOut {
 @future (callout=true)  // future method needed to run callouts from Triggers
      static public void getLocation(id addressId){
        // gather account info
        Address__c a = [Select Name, City__c, State__c, Zip_Code__c from Address__c where id =: addressId];
        
        system.debug('what is my Address Id and Name ' +a.Name +' ' +a.id);
        
        // create an address string
        String address = '';
        if (a.Name != null)
            address += a.Name +', ';
        if (a.City__c != null)
            address += a.City__c +', ';
        if (a.State__c != null)
            address += a.State__c +' ';
        if (a.Zip_Code__c != null)
            address += a.Zip_Code__c +', ';
       	address += 'USA';    
        //if (a.BillingCountry != null)
          //  address += a.BillingCountry;
 		system.debug('what is my full address ' +address);
 		
        address = EncodingUtil.urlEncode(address, 'UTF-8');
 
        // build callout
        Http h = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint('http://maps.googleapis.com/maps/api/geocode/json?address='+address+'&sensor=false');
        req.setMethod('GET');
        req.setTimeout(60000);
 
        try{
            // callout
            HttpResponse res = h.send(req);
 
            // parse coordinates from response
            JSONParser parser = JSON.createParser(res.getBody());
            double lat = null;
            double lon = null;
            while (parser.nextToken() != null) {
                if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) &&
                    (parser.getText() == 'location')){
                       parser.nextToken(); // object start
                       while (parser.nextToken() != JSONToken.END_OBJECT){
                           String txt = parser.getText();
                           parser.nextToken();
                           if (txt == 'lat')
                               lat = parser.getDoubleValue();
                           else if (txt == 'lng')
                               lon = parser.getDoubleValue();
                       }
 
                }
            }
            
            system.debug('what is my latitude passing back' +lat);
 
            // update coordinates if we get back
            if (lat != null){
                a.GeoLocation__Latitude__s = lat;
                a.GeoLocation__Longitude__s = lon;
                update a;
            }	
 
        } catch (Exception e) {
        }
    }
}



Trigger

trigger triggerAddressAfterInsert on Address__c (after insert) {
    for (Address__c a : trigger.new)
        if (a.GeoLocation__Latitude__s == null)
            GoogleMapsCallOut.getLocation(a.id);

}

 what you think i did wrong here?

David HollandDavid Holland

Have you added www.maps.googleapis.com to your list of trusted sites?

ericmonteericmonte

Yup i did that

bujjibujji
Hi,
Make your trigger after Insert, Before Update and add this condition also in the trigger
if( a.Geolocation__Latitude__s == null || a.Geolocation__Latitude__s == 0.0 ).

It will resolve your problem. If resolved hit the kudos.

Thanks,
Bujji.
Rocks_SFDCRocks_SFDC

Hello Developers,

 

Could anyone send test class for above class.

 

We have implemented the same functionality.

 

Thanks,

Anil

ericmonteericmonte

Sorry for the delay on this, i havent been on. Here is my code and hope this helps

 

public class ClassGoogleGeoLocationCallout {

@future (callout=true)  // future method needed to run callouts from Triggers
      static public void getLocation(id addId){
        // gather account info
        Address_vod__c a = [select Name, City__c, State__c,Zip__c, Latitude__c, Longitude__c, Country__c
        from Address__c
        where id =: addId];
        
        String address = '';
        if (a.Name != null)
            address += a.Name +', ';
        if (a.City_vod__c != null)
            address += a.City_vod__c +', ';
        if (a.State_vod__c != null)
            address += a.State_vod__c +' ';
        if (a.Zip_vod__c != null)
            address += a.Zip_vod__c +', ';
        if (a.Country_vod__c != null)
        address += 'USA';
 
        address = EncodingUtil.urlEncode(address, 'UTF-8');
         system.debug('=== ADDRESS ===' +address);
        // build callout
        Http h = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint('http://maps.googleapis.com/maps/api/geocode/json?address='+address+'&sensor=false');
        req.setMethod('GET');
        req.setTimeout(60000);
        
 
        try{
            // callout
            HttpResponse res = h.send(req);
             System.debug('====RESPONSE====' +res.getBody());
            // parse coordinates from response
            JSONParser parser = JSON.createParser(res.getBody());
            double lat = null;
            double lon = null;
            while (parser.nextToken() != null) {
                if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) &&
                    (parser.getText() == 'location')){
                       parser.nextToken(); // object start
                       while (parser.nextToken() != JSONToken.END_OBJECT){
                           String txt = parser.getText();
                           parser.nextToken();
                           if (txt == 'lat')
                               lat = parser.getDoubleValue();
                           else if (txt == 'lng')
                               lon = parser.getDoubleValue();
                       }
                       System.debug('====LAT====' +lat);
 
                }
            }
 
            // update coordinates if we get back
            if (lat != null){
                a.AddressGeoLocation__latitude__s = lat;
                a.AddressGeoLocation__longitude__s = lon;
                update a;
            }
 
        } catch (Exception e) {
        }
    }
    
    static testmethod void testGeoLocation(){
        
        Account a = new Account (Name='TEST DATA');
        insert a;
        
        Address_vod__c add = new Address_vod__c
        (Name = '6 West',
        Address_line_2_vod__c = '',
        City_vod__c = 'Way',
        State_vod__c = 'NJ',
        Zip_vod__c = '07470',
        Country_vod__c = 'USA',
        Account_vod__c = a.id
        
        );
        
        insert add;
        
        StaticResourceCalloutMock mock = new StaticResourceCalloutMock();
        mock.setStaticResource('GoogleGeoLocationJson');
        mock.setStatusCode(200);
        mock.setHeader('Content-Type', 'application/json');
        
        // Set the mock callout mode
        Test.setMock(HttpCalloutMock.class, mock);
        
        // Call the method that performs the callout
      
        ClassGoogleGeoLocationCallout.getLocation(add.id);
        
    }
}

Rocks_SFDCRocks_SFDC

Hello everyone,

 

Could you please send test code for the code which you have provided.

 

Thanks,

Anil

ericmonteericmonte

I did at it. It's part of my class. Here you go again:

 

static testmethod void testGeoLocation(){
        
        Account a = new Account (Name='TEST DATA');
        insert a;
        
        Address_vod__c add = new Address_vod__c
        (Name = '6 West',
        Address_line_2_vod__c = '',
        City_vod__c = 'Way',
        State_vod__c = 'NJ',
        Zip_vod__c = '07470',
        Country_vod__c = 'USA',
        Account_vod__c = a.id
        
        );
        
        insert add;
        
        StaticResourceCalloutMock mock = new StaticResourceCalloutMock();
        mock.setStaticResource('GoogleGeoLocationJson');
        mock.setStatusCode(200);
        mock.setHeader('Content-Type', 'application/json');
        
        // Set the mock callout mode
        Test.setMock(HttpCalloutMock.class, mock);
        
        // Call the method that performs the callout
      
        ClassGoogleGeoLocationCallout.getLocation(add.id);
        
    }

KR_ForceKR_Force
Hi ericmonteericmonte,
now im in the same boat trying to implment the same solution and got struck with test class
can you please share you HttpCalloutMock.class as well?