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;

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.

| improve this answer | |
  • 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. – Jur Van Oerle Jun 12 '15 at 12:04
  • 1
    What's the error you're getting exactly? – Valyrion Jun 12 '15 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 – Jur Van Oerle Jun 12 '15 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 '15 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 '15 at 13:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.