You need to sign in to do that
Don't have an account?
How to bulkify triggers
Dear All,
I am immense need of help from all of you. After giving a much thought and so much brainstorming happened finally I turned up here for advise.
Requirement:
I need to fetch coordinates value of account based on Map address provided
Solution approach
I create few fields on accounts like MapAddressCity,MapAddressState,MapAddressStreet,MapAddressPostalCode and MapAddresscountry on account. When an user enters values in Map fields and clicks on save button I am calling Google API. Google API will returns one coordinate value based on address filled in Map fields. I have created one field called "Location"(Data Type-Geolocation) which will stores coordinates and also I created 2 formula fields which stores the longitude and latitude values of coordinates in "LonField" and "LatField" respectively
If an user enters below in account:
MapAddressCity: San Francisco
MapAddressCountry: United States
MapAddressPostalCode: 94105
MapPostalState: CA
MapAddressStreet: One Market Street
and clicks on Save-Google API call will be made and below information wiull be stored on account:
Location-37°47'38''N 122°23'41''W
LongValue-122.3948
LatValue37.7939
My Question:
In our org there is already one trigger written on account and there is already one accounthandler class and we always follow best practices so I didnt write a separate trigger and class to achieve above mentioned requirement. I am reusing same accounttriggerhandler class and apex trigger which is written on account.
If I write separate class and trigger to achieve above mentioned functionality then I have no issue everything works smoothly but when I am trying to include my code in already existing account trigger handler then I am not able to make my code bulkify. I am calling my class method on after insert and after update and coordinates fields are updating perfectly but only for single account because I am not able to make my code bulkify and runs for multiple accounts.
Kindly help me. Below is trigger which is already existing on account:
My class code is as belows:
I have removed all the extra codes and methods from class and only kept my method in class to have a better visibility for code to all of you.
I am calling "DoAddressGeocode" method on HandleAfterInsert and HandleAfterUpdate.
Right now I am not able to do bulkification of my code and wrote only for 1 accounts like DoAddressGeocode(newAccs[0].id)
Any help would be greatly appreciated.
Thanks in advance!
Kindly help
I am immense need of help from all of you. After giving a much thought and so much brainstorming happened finally I turned up here for advise.
Requirement:
I need to fetch coordinates value of account based on Map address provided
Solution approach
I create few fields on accounts like MapAddressCity,MapAddressState,MapAddressStreet,MapAddressPostalCode and MapAddresscountry on account. When an user enters values in Map fields and clicks on save button I am calling Google API. Google API will returns one coordinate value based on address filled in Map fields. I have created one field called "Location"(Data Type-Geolocation) which will stores coordinates and also I created 2 formula fields which stores the longitude and latitude values of coordinates in "LonField" and "LatField" respectively
If an user enters below in account:
MapAddressCity: San Francisco
MapAddressCountry: United States
MapAddressPostalCode: 94105
MapPostalState: CA
MapAddressStreet: One Market Street
and clicks on Save-Google API call will be made and below information wiull be stored on account:
Location-37°47'38''N 122°23'41''W
LongValue-122.3948
LatValue37.7939
My Question:
In our org there is already one trigger written on account and there is already one accounthandler class and we always follow best practices so I didnt write a separate trigger and class to achieve above mentioned requirement. I am reusing same accounttriggerhandler class and apex trigger which is written on account.
If I write separate class and trigger to achieve above mentioned functionality then I have no issue everything works smoothly but when I am trying to include my code in already existing account trigger handler then I am not able to make my code bulkify. I am calling my class method on after insert and after update and coordinates fields are updating perfectly but only for single account because I am not able to make my code bulkify and runs for multiple accounts.
Kindly help me. Below is trigger which is already existing on account:
//Single Master Trigger on Account using Handlers for each individual actions trigger AccountTrigger on Account (before delete, before insert, before update, after insert, after update,after delete) { checkRecursive.isRunOnce = true; // ToDo : Need to change the recursive handling logic AccountTriggerHandler accHandler = new AccountTriggerHandler(trigger.new,trigger.old,trigger.newMap,trigger.oldMap,trigger.isUpdate); if(trigger.isBefore && trigger.isInsert){ accHandler.HandleBeforeInsert(); } if(trigger.isBefore && trigger.isUpdate){ accHandler.HandleBeforeUpdate(); } if(trigger.isAfter && trigger.isInsert) { accHandler.HandleAfterInsert(); } if(trigger.isAfter && trigger.isUpdate){ accHandler.HandleAfterUpdate(); } if(trigger.isBefore && trigger.isDelete) accHandler.HandleBeforeDelete(); if(trigger.isAfter && trigger.isDelete) accHandler.HandleAfterDelete(); }
My class code is as belows:
//Handler Class to handle Account Trigger public class AccountTriggerHandler { public static Boolean runAccountTriggerHandler = true; private static Boolean geocodingCalled = false; public static boolean run = true; public static boolean runOnce(){ if(run){ run=false; return true; }else{ return run; } } //trigger variables List<Account> newAccs; List<Account> oldAccs; Map<Id,Account> newAccMap; Map<Id,Account> oldAccMap; Id accountId; boolean isUpdate; //constructor public AccountTriggerHandler(List<Account> newAccs, List<Account> oldAccs, Map<Id,Account> newAccMap, Map<Id,Account> oldAccMap, boolean isUpdate){ this.newAccs = newAccs; this.oldAccs = oldAccs; this.newAccMap = newAccMap; this.oldAccMap = oldAccMap; this.isUpdate = isUpdate; this.accountId= accountId; this.consentService = new ConsentManagementService(Account.sObjectType); } public void HandleAfterInsert(){ //if(!System.isFuture()) //getLocation(newAccs[0].Id); DoAddressGeocode(newAccs[0].id); } } public void HandleAfterUpdate(){ //if(!System.isFuture()) //getLocation(newAccs[0].Id); DoAddressGeocode(newAccs[0].id); } } } public void HandleBeforeDelete(){ } public void HandleAfterDelete(){ } // wrapper method to prevent calling futuremethods from an existing future context public static void DoAddressGeocode(id accountId) { if(geocodingCalled || System.isFuture()) { System.debug(LoggingLevel.WARN,'***Address Geocoding Future Method Already Called - Aborting...'); return; } // if not being called from future context, geocode the address geocodingCalled= true; getLocation(accountId); } @future (callout=true) // future method needed to run callouts from Triggers static public void getLocation( id accountId){ // gather account info Account a =[SELECT MapAddressCity__c,MapAddressCountry__c,MapAddressPostalCode__c,MapAddressStreet__c,MapPostalState__c FROM Account WHERE id =: accountId]; //List<Account> a= new List<Account>(); //a= [SELECT id, MapAddressCity__c,MapAddressCountry__c,MapAddressPostalCode__c,MapAddressStreet__c,MapPostalState__c FROM Account WHERE id =: accountId]; // create an address string String address = ''; if (a.MapAddressStreet__c!= null) address += a.MapAddressStreet__c+', '; if (a.MapAddressCity__c != null) address += a.MapAddressCity__c +', '; if (a.MapPostalState__c!= null) address += a.MapPostalState__c+' '; if (a.MapAddressPostalCode__c!= null) address += a.MapAddressPostalCode__c+', '; if (a.MapAddressCountry__c!= null) address += a.MapAddressCountry__c; 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(); } } } // update coordinates if we get back if (lat != null){ a.Location__Latitude__s = lat; a.Location__Longitude__s = lon; update a; } } catch (Exception e) { } } }
I have removed all the extra codes and methods from class and only kept my method in class to have a better visibility for code to all of you.
I am calling "DoAddressGeocode" method on HandleAfterInsert and HandleAfterUpdate.
Right now I am not able to do bulkification of my code and wrote only for 1 accounts like DoAddressGeocode(newAccs[0].id)
Any help would be greatly appreciated.
Thanks in advance!
Kindly help
Thanks for your kind response.
I will be happy to get in touch with you If I will be able to solve my bulkification issue.
Many thanks in advance
Thanks & Regards,
Harjeet
I am using future callout for updating geofields.Kindly refer 85 of my class
Thanks & Regards,
Harjeet