2

I have a trigger that fires when the address has changed on a record. I make a callout to Google API to gain the longitude and latitude information that I then want to put inside of my record. When I use database.update(sObject), I get an error that I cannot update inside of an update trigger so I would like to find a work-around for this. This is the function that will perform the callout:

 @future(callout=true) public static void updateGeoLocation( Set<Id> objectsToUpdate, String objectAPI_Name, String longitudeAPI_Name, String latitudeAPI_Name, String streetAPI_Name, String cityAPI_Name, String countryAPI_Name, String zipAPI_Name )
{
    System.debug( 'get here?' );
    String placeHolder      = 'SELECT Id, {0}, {1}, {2}, {3}, {4}, {5} FROM {6}'; 
    List<String> fillers    = new List<String>{ longitudeAPI_Name, latitudeAPI_Name, streetAPI_Name, cityAPI_Name, countryAPI_Name, zipAPI_Name, objectAPI_Name };
    String soqlQuery        = String.format( placeHolder, fillers );

    soqlQuery               += ' WHERE Id IN : ' + 'objectsToUpdate';
    List<sObject> sobjList  = Database.query( soqlQuery );

    System.Debug( 'number of thingies: ' + sobjList );

    for ( sObject sObj : sobjList )
    {
        String street   = ( String )sObj.get( streetAPI_Name );
        String city     = ( String )sObj.get( cityAPI_Name );
        String country  = ( String )sObj.get( countryAPI_Name );
        String zip      = ( String )sObj.get( zipAPI_Name );

        String url              = 'https://maps.googleapis.com/maps/api/geocode/json?address=' + sanitizeLocation( street, city, country, zip ) + '&key=' + Label.GeoApiKeyMassUpdate;
        googleMapsResponse res  = requestGeoLocation( url );

        googleMapsResponse.location loc = res.results[0].geometry.location;

        sObj.put( longitudeAPI_Name, loc.lng );
        sObj.put( latitudeAPI_Name, loc.lat );
    }
    update sobjList;
}

1 Answer 1

1

Are you calling this in a before update trigger? Because it's not allowed to update the records being processed by the trigger by using a DML operation. Not sure if @future has any impact on this.

If you are doing it before update, try directly modifying the fields of the objects in Trigger.new, otherwise call this function only after update.

7
  • thank you for your reply, I tried it both in before and after and got the same error. Since a callout through a trigger can only be made in a @future function and a future function does not allow to pass a list of objects and must be of type void, I'm afraid I also can't change the data directly in the Trigger.new. Jun 12, 2015 at 12:04
  • 1
    What's the error you're getting exactly?
    – Valyrion
    Jun 12, 2015 at 12:07
  • The error message that I get is: Future method cannot be called from a future or batch method: CalculateGeoLocationAndUpdateRecord.updateGeoLocation(Set<Id>, String, String, String, String, String, String, String) So my first guess is that update itself is a future method Jun 12, 2015 at 12:40
  • @JurVanOerle It sounds like your first geolocation update starts another update trigger invocation that then tries to call the future method again. If this is the case, you should find a way to identify that these objects already have the right information and avoid calling the future method in that case.
    – Valyrion
    Jun 12, 2015 at 12:48
  • 1
    @JurVanOerle The function is still being called every time, even is the list of Ids is empty. Try wrapping the call in if(idsToGeoLocate.size() > 0){ ... } to catch this.
    – Valyrion
    Jun 12, 2015 at 13:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .