Tuesday, April 30, 2019

How to call future(asynchronous class in apex) methods from salesforce apex triggers and not run into governor limits


 Use @future Appropriately
     As articulated throughout this article, it is critical to write your Apex code to efficiently handle bulk or many records at a time. This is also true for asynchronous Apex methods (those annotated with the @future keyword).
          Even though Apex written within an asynchronous method gets its own independent set of higher governor limits, it still has governor limits. Additionally, no more than ten @future methods can be invoked within a single Apex transaction.

·    Here is a list of governor limits specific to the @future annotation:
·    No more than 10 method calls per Apex invocation
·    No more than 200 method calls per Salesforce license per 24 hours.
·    The parameters specified must be primitive dataypes, arrays of primitive  datatypes, or collections of primitive datatypes.
·    Methods with the future annotation cannot take sObjects or objects as arguments.
·    Methods with the future annotation cannot be used in Visualforce controllers in either getMethodName or setMethodName methods, nor in the constructor.
 the Apex trigger inefficiently invokes an asynchronous method for each Account record it wants to process:
EX :
trigger accountAsyncTrigger on Account (after insert, after update) {
  for(Account a: Trigger.new){
    // Invoke the @future method for each Account
    // This is inefficient and will easily exceed the governor limit of
    // at most 10 @future invocation per Apex transaction
    asyncApex.processAccount(a.id);
   }    
}
Here is the Apex class that defines the @future method:
EX :
global class asyncApex {

  @future
  public static void processAccount(Id accountId) {
       List<Contact> contacts = [select id, salutation, firstname, lastname, email
                from Contact where accountId =&nbsp;:accountId];
            
         for(Contact c: contacts){
              System.debug('Contact Id[' + c.Id + '], FirstName[' + c.firstname + '], LastName[' + c.lastname +']');
                                                    c.Description=c.salutation + ' ' + c.firstName + ' ' + c.lastname;
        }
        update contacts;       
  }  
}

Since the @future method is invoked within the for loop, it will be called N-times (depending on the number of accounts being processed). So if there are more than ten accounts, this code will throw an exception for exceeding a governor limit of only ten @future invocations per Apex transaction.

Instead, the @future method should be invoked with a batch of records so that it is only invoked once for all records it needs to process:
EX:
trigger accountAsyncTrigger on Account (after insert, after update) {
    //By passing the @future method a set of Ids, it only needs to be
    //invoked once to handle all of the data.
    asyncApex.processAccount(Trigger.newMap.keySet());
}

And now the @future method is designed to receive a set of records:
EX :
global class asyncApex {
   @future
  public static void processAccount(Set<Id> accountIds) {
       List<Contact> contacts = [select id, salutation, firstname, lastname, email from Contact where accountId IN&nbsp;:accountIds];
       for(Contact c: contacts){
           System.debug('Contact Id[' + c.Id + '], FirstName[' + c.firstname + '], LastName[' + c.lastname +']');
                                  c.Description=c.salutation + ' ' + c.firstName + ' ' + c.lastname;
        }
        update contacts;
  }
}
Writing Test Methods to Verify Large Datasets :
             Here is the poorly written contact trigger. For each contact, the trigger performs a SOQL query to retrieve the related account. The invalid part of this trigger is that the SOQL query is within the for loop and therefore will throw a governor limit exception if more than 100 contacts are inserted/updated.
EX :
trigger contactTest on Contact (before insert, before update) {
             
             for(Contact ct: Trigger.new){
              Account acct = [select id, name from Account where Id=:ct.AccountId];
                 if(acct.BillingState=='CA'){
                    System.debug('found a contact related to an account in california...');
                    ct.email = 'test_email@testing.com';
                    //Apply more logic here....
                 }
             }
}
Here is the test method that tests if this trigger properly handles volume datasets:
EX :
public class sampleTestMethodCls {
              static testMethod void testAccountTrigger(){
                  //First, prepare 200 contacts for the test data
                  Account acct = new Account(name='test account');
                  insert acct;          
                  Contact[] contactsToCreate = new Contact[]{};
                  for(Integer x=0; x<200;x++){
                      Contact ct = new Contact(AccountId=acct.Id,lastname='test');
                      contactsToCreate.add(ct);
                  }
                  //Now insert data causing an contact trigger to fire.
                  Test.startTest();
                  insert contactsToCreate;
                  Test.stopTest();  
              } 
          }
Note the use of Test.startTest and Test.stopTest. When executing tests, code called before Test.startTest and after Test.stopTest receive a separate set of governor limits than the code called between Test.startTest and Test.stopTest. This allows for any data that needs to be setup to do so without affecting the governor limits available to the actual code being tested.

Now let's correct the trigger to properly handle bulk operations. The key to fixing this trigger is to get the SOQL query outside the for loop and only do one SOQL Query:
EX :
trigger contactTest on Contact (before insert, before update) {              
             Set<Id> accountIds = new Set<Id>();
             for(Contact ct: Trigger.new)
                 accountIds.add(ct.AccountId);             
             //Do SOQL Query   
             Map<Id, Account> accounts = new Map<Id, Account>(
                  [select id, name, billingState from Account where id in :accountIds]);                
             for(Contact ct: Trigger.new){
                 if(accounts.get(ct.AccountId).BillingState=='CA'){
                     System.debug('found a contact related to an account in california...');
                     ct.email = 'test_email@testing.com';
                     //Apply more logic here....
                 }
             }
          }
Note how the SOQL query retrieving the accounts is now done once only. If you re-run the test method shown above, it will now execute successfully with no errors and 100% code coverage.
Avoiding Hardcoding :
                    Here is a sample that hardcodes the record type IDs that are used in an conditional statement. This will work fine in the specific environment in which the code was developed, but if this code were to be installed in a separate org (ie. as part of an AppExchange package), there is no guarantee that the record type identifiers will be the same.
EX :
for(Account a: Trigger.new){
             //Error - hardcoded the record type id
             if(a.RecordTypeId=='012500000009WAr'){         
                //do some logic here.....
             }else if(a.RecordTypeId=='0123000000095Km'){
                //do some logic here for a different record type...
             }
       }
}       
           Now, to properly handle the dynamic nature of the record type IDs, the following example queries for the record types in the code, stores the dataset in a map collection for easy retrieval, and ultimately avoids any hardcoding.
EX :
//Query for the Account record types
               List<RecordType> rtypes = [Select Name, Id From RecordType
                            where sObjectType='Account' and isActive=true];
               //Create a map between the Record Type Name and Id for easy retrieval
               Map<String,String> accountRecordTypes = new Map<String,String>{};
               for(RecordType rt: rtypes)
                  accountRecordTypes.put(rt.Name,rt.Id);
                for(Account a: Trigger.new){
                    //Use the Map collection to dynamically retrieve the Record Type Id
                    //Avoid hardcoding Ids in the Apex code
                    if(a.RecordTypeId==accountRecordTypes.get('Healthcare')){           
                       //do some logic here.....
                    }else if(a.RecordTypeId==accountRecordTypes.get('High Tech')){
                       //do some logic here for a different record type...
                    }
               }  


Introduction to Salesforce Process Builder

Tap this to watch the video tutorial

 Certification Guide

How to get certified
Salesforce Administrator 201 Certification

Salesforce is one of the fastest growing and most in-demand skills in IT right now, and to add that knowledge to your resume can have a payoff almost immediately. The Salesforce ecosystem extends far past its original cloud-based CRM platform, so Salesforce technical skills prove extremely useful and necessary in a wide range of areas, from system administrators, to product managers, developers, integration architects and beyond.

Becoming Salesforce Certi fied is not only a highly effective way to prove your skills are current and at the expected baseline level but more often than not a prerequisite for companies who seek Salesforce experts. Most Salesforce-related jobs will require a minimum of one certi cation, and the entry-level – but no less challenging – is the Salesforce Certi ed Administrator certi cation.

One thing I hear a lot from people with multiple Salesforce certifications is that passing the Certi ed Administrator exam was one of the hardest. Why? Well, because it’s the rst one and the material covered is very comprehensive. So although this is a prerequisite exam to several other certi cation paths, it’s not one you can simply show up and take the test without preparation, even if you’ve worked with Salesforce for years.

Don’t let the dif culty level of the test put you off, though. The good news is that it doesn’t matter whether you’re already an experienced system administrator who wants to take the next step and get certi ed, or if you come from a completely different background and decided to learn a new set of skills from scratch. Getting that rst certi cation can be achieved in a few months, even if this is the rst time you’re reading the word “Salesforce”. You just need to devise a plan, prepare and practice.

I passed the Salesforce Certi ed Administrator exam exactly 3 months after I started studying for it. Before that, my Salesforce knowledge was very limited, to say the least. But with that goal in mind, I also wanted to pass the rst time I took the test. Ambitious? Maybe, but very feasible as I later found out.

There are different ways you can prepare for the exam. Salesforce University runs courses onsite or online, one of them being the Administration Essentials for New Admins (Admin201), which can run you about $4500 for the 3-day course. You read that gure correctly. So if you or the company you work for are not willing to make that investment on your certi cation goals, there are many self-study resources online that can help you prepare for the exam. I took the second option which proved to be highly rewarding and I plan on using those same resources for my future certi cation exams.


What to expect from the exam?

Understanding the format of this test will help you structure the way you study for it.
There are 60 multiple-choice questions (plus 5 unscored questions) and 105 minutes to complete.

65% is the passing score, which means you need 39 correct answers.

You may take the test at a test centre, or remotely on your own computer. The second option is monitored through a webcam and you must submit your biometrics and follow strict guidelines beforehand, but may be worth it if you don’t have a test centre near
you or need more exibility in terms of scheduling. You can nd the information about scheduling your exam and the guidelines here.

The fee to take the test is $200 and the retake fee is $100.

Every question is worth 1 mark on the test. Some questions will ask you to pick more than one correct answer but you either get the whole point or nothing. There’s no partial marks for a multi-select question.
The questions on the exam are scenario based. Some questions are longer than others.

You can mark questions for review on your screen during the test, and that’s a tool I highly recommend using so you can maximize your ef ciency during the test.
When taking the test, if you know the answer to a question right away, don’t dwell on it or second-guess yourself. Pick your answer and move on. Likewise, if you don’t know the answer, mark for review and come back to it later so you have time to answer the ones you know.
Use all the allotted time given on the test and read each question carefully, while always being mindful of the clock. I recommend spending 70 minutes on the 60 questions, allowing yourself the remaining 20 minutes for questions marked for review. So if you see yourself spending over 1 minute per question, it may be time to move quicker.
Some of the multiple choice options will have made-up names for things such as a “List” Report Format, which doesn’t exist or is not one of the report formats in Salesforce. You can eliminate those options easily right off the bat.
None of the exams are open-book so you may not bring any notes, hardcopy material or take notes with you during the exam. Before 2017, Salesforce would only give you “Pass” or “Fail” results at the end of your exam. Now, they are including Section-Level Feedback Results, shown as a percentage of correct answers from each topic on the exam, as outlined on the exam guide. It’s great feedback because it shows you exactly what your strong points are or areas you could practice more, in case you fail.
Once you pass, you’ll receive an email with your test results, a link to your certifi cate as well as a link to the of cial “Salesforce Certi ed” badge that you can add to your pro le photos on LinkedIn, social media, or pretty much anywhere you would like to brag about! You’ll also be invited to the exclusive Salesforce Certifi ed Success Community.
Your certi fication may be displayed on their offi cial veri fication website, which you can opt in or out before you take the exam (or after if you change your mind).


Some very important topics to focus on:

Standard & Custom Objects 15%

Sales & Marketing Applications 15%

Security & Access 14%