Wednesday, 15 August 2018

what is the Recursive trigger and how to handle it?

Trigger when called over and over then its called recursive trigger.Below error will be display
if not controlled.

error message : maximum trigger depth exceeded

ex : Recursive code

Trigger AccountTrigger on Account(before insert)
{
    insert new Account(Name='test');

}

How to stop it ?

In order to avoid the situation of the recursive call,make sure your trigger is getting executed only one time.To do so, you can create a class with a static Boolean variable with default value true.

In the trigger,before executing your code keep a check that the variable is true or not.once you check,make a variable false.

ex :

public class checkRecursive
{

  private static boolean run=true;

  public static boolean runOnce()
  {
     if(run){
         run=false;
        return true;
      }
      else
       {
         return run;
       }

  }

}

Trigger AccountTrigger on Account(before insert)
{

    if(checkRecursive.runonce())
      {
        insert new Account(Name='test');
      }

}

After executing workflow rules again before trigger and after triggers will execute,how can you avoid?

class :
==========

global class validator_cls
{

 private static boolean blnAlreadyDone=false;

 public static boolean hasAlreadyDone()
  {
     return blnAlreadyDone;
  }

 public static boolean hasAlreadyDone()
  {
     blnAlreadyDone=true;
  }


}

Class :
============


public class AccountTriggerHandler
{

 public void OnBeforeInsert(Account[] newaccounts)
 {
   if(!validator_cls.hasAlreayDone)
     {

        AddUpdateFields(newAccounts);
        validator_cls.setAlreadyDone();
     }

 }


}

Trigger :
==============

Trigger AccountTrigger on Account(before insert,after insert,before update,after update)
{

AccountTriggerHandler handler=new AccountTriggerHandler();

/* Before Insert */

 if(Trigger.isBefore && Trigger.isInsert)
  {
    handler.OnBeforeInsert(Trigger.new);
  }
/* After Insert */
  else if(Trigger.isAfter && Trigger.isInsert)
  {
     handler.onAfterInsert(Trigger.new);
  }
/* Before Update */
  else if(Trigger.isBefore && Trigger.isUpdate)
  {
    handler.onBeforeUpdate(Trigger.old,Trigger.new,Trigger.newMap);
  }
/* After Update */
  else if(Trigger.isAfter && Trigger.isUpdate)
  {
    handler.onAfterUpdate(Trigger.old,Trigger.new,Trigger.newmap);
  }
/* Before Delete */
  else if(Trigger.isBefore && Trigger.isDelete)
  {
    handler.onBeforeDelete(Trigger.old,Trigger.oldmap);
  }
/* After Delete */
  else if(Trigger.isAfter && Trigger.isDelete)
  {
    handler.OnAfterDelete(Trigger.old,Trigger.oldmap);
  }
  else if(Trigger.isUnDelete)
  {
    handler.onUndelete(Trigger.new);
  }

}

Roll up summary functionality through trigger

public class SampleRollupSummary {
 
    public static void rollupContacts(list<contact> lstOfconts){
        system.debug('==lstOfconts== : '+lstOfconts);
        set<id> accIds = new set<id>();
        list<account> updLstOfAccs = new list<account>();
        list<contact> lstCons = new list<contact>();
     
        for(contact con : lstOfconts){
            accIds.add(con.accountid);
        }
        system.debug('==accIds==:'+accIds);
        list<account> lstAccs = [select id,name,Total_Count__c, (select id from contacts) from account where id in : accIds];
     
        for(account acc : lstAccs){
            system.debug('==acc.contacts.size()=='+acc.contacts.size());
            acc.Total_Count__c = acc.contacts.size();
            updLstOfAccs.add(acc);
        }
        if(updLstOfAccs.size() > 0){
            update updLstOfAccs;
        }     
     
    }
 
}


trigger RollupSummaryTriggerOnAccountObj on contact(after insert, after update, after delete, after undelete) {
    if (trigger.isAfter && (trigger.isInsert || trigger.isUpdate || trigger.isUndelete)) {
        SampleRollupSummary.rollupContacts(trigger.new);
    }
    else if (trigger.isAfter && trigger.isDelete) {
        SampleRollupSummary.rollupContacts(trigger.old);
    }
}

Salesforce Governer Limits

1.DML Governing Limits

we can have only 150 DML statements with in a transaction.

we rectify this type of errors by using bulky operations. put similar operation on the object in list and invoke the DML on the list.

2.SOQL Governing Limits

with in a transaction we can write only 100 SOQL queries.

use
Map<Id,Account> accMap=new map<Id,Account>([select id,Name from Account]);

3.DML rows Limit :

Number of DML rows : 10000

4.SOSL Governing Limits :

Number of SOSL queries : 20

5.Maximum CPU time : 10000
6.Maximum heap size : 6000000
7.Number of callouts : 100
8.Number of Email Invocation : 10
9.Number of future calls : 50
10.Number of queueable jobs added to the queue:50
11.Number of mobile apex push calls :10
12.Number of query rows : 50000

DML statements vs Database class Methods


Apex offers two ways to perform DML operations

1.Using DML statements
2.Database class methods

Difference between the two options that by using the Database class method.

You can specify whether or not to allow for partial record processing if errors are encountered.

you can do so by passing an additional second Boolean parameters.

if you specify FALSE for this parameter and if a record fails,the remainder of DML
operations can still succeed.

 ex : Database.insert(accList,false);

False : partial processing allowed
True  : partial processing not allowed

By default this optional parameter is true,which means that if at least one sObject can't be processed,all remaining sObjects won't and an exception will be thrown for the record that causes a failure.

Order of execution of apex code

1. Before triggers:
     If we update child records in before triggers then parent record automatically update.
2. Validation rules:
 If validation matches the criteria then error will populate in same page.
Runs most system validation steps again, such as verifying that all required fields have a non-null value, and runs any user-defined validation rules. The only system validation that Salesforce does not run a second time (when the request comes from a standard UI edit page) is the enforcement of layout-specific rules.
*Note: Saves the record to the database, but does not commit yet.

3. After Triggers:
4. Assignment Rules:
5. Auto Response Rules:
6. Workflow Rules:
If there are workflow field updates, updates the record again.
7. Escalation Rules:
       If the record contains a roll-up summary field or is part of a cross-object workflow, performs calculations and updates the roll-up summary field in the parent record. Parent record goes through save procedure.
     If the parent record is updated, and a grand-parent record contains a roll-up summary field or is part of a cross-object workflow, performs calculations and updates the roll-up summary field in the parent record. Grand-parent record goes through save procedure.
Executes Criteria Based Sharing evaluation.
Commits all DML operations to the database.

8.Executes post-commit logic, such as sending emails



simple steps:
==============
Order of Events
  1. Original record is loaded or new record is initialized
  2. Fields values are loaded into sObjects
  3. System validations rules are executed:
  4. Before triggers are executed
  5. System validations rules are run again and custom validation rules are checked.
  6. Duplicate rules are executed
  7. Record is saved but not committed
  8. After triggers are executed
  9. Assignment rules are executed
  10. Auto-response rules are executed
  11. Workflow rules are executed
  12. Before triggers,system validation rules and after triggers are executed due to workflow field updates
  13. Processes are executed
  14. Escalation rules are executed
  15. Entitlement rules are executed
  16. Rull-up summary fields and cross-object formula fields are updated
  17. Updated parent and grand parent records are saved
  18. Criteria based sharing rules are evaluated
  19. DML operations are committed to the database
  20. Post-commit logic is executed

Apex Basics

Apex is a strongly typed,object -oriented programming language that allows developers
to execute flow and transaction control statements on the Force.com platform.

Apex enables developers to add business logic to most system events,including button clicks,
related record updates and visualforce pages.

Data Types :
============
1.primitives
2.sObjects
3.Collections

Apex primitive data types include :

1.Boolean : can only be assigned true,false or null
2.Decimal : A number that includes a decimal points.
3.Double : A 64-bit number that includes a decimal point
4.ID : Any Valid salesforce.com ID
5.Integer : A 32bit number that does not include a decimal point.
6.Long : A 64-bit number that does not include a decimal point.
7.String : Any set of characters surrounded by single quotes.
8.Date : A value that indicates a particular day.
9.DateTime : A value that indicates a particular day and time
10.Time : A value that indicates a particular time.

sObjects :
=============
the term sObject refers to any object that can be stored in the Force.com platform database.

An sObject variable represents a row of data and can only be declared in Apex.

ex :
Contact c= new Contact(FirstName='raj';LastName='kiran';
Email ='test@gmail.com');

Account a =new Account(Name='TCS');
insert a;

Account a1=[select Name from Account
where ID='857598jh'];
a1.Name='new  Name';
update a1;

Collection :
============
collection of primitives or sObjects.

A LIST is an ordered collection.so use
list when you wnat to identify list element
based on INDEX NUMBER.
List can contain duplicates.

List<string> colors =new List<string>('red','purple','green');

List<Account> accts=[select Name,Type from Account
where Industry='Energy'];

List<Contact> email_contacts=
[select FirstName,LastName from Contact where
Email!=Null];

1. Set
2. List
3. Map

A set is a collection of unique,unordered elements.it can contain primitive data types or sObjects.

A set is an unordered collection of primitives or sObjects that do not contain any duplicate elements.so use SET if you want to make sure that your collection should not conatin Duplicates.

ex :
Set<String> s = new Set<String>();
Set<String> s = new Set<String>{'Jon', 'Quinton', 'Reid'};

commonly you'll see developers construct a set of IDs from a query,trigger context,etc.
and the use it as part of WHERE clause in their SOQL query.

ex :

Set<ID> ids = new Set<ID>{'0017000000cBlbwAAC','0017000000cBXCWAA4'};
List<Account> accounts = [Select Name From Account Where Id = :ids];


Map :
=====
A MAP is a collection of key-value pairs where each unique key maps to a single value.
Keys can be any primitive data type,while values can be a primitive,sObject,Collection
types or an Apex Object.

Use a map when you want to quickly find something by a key.Each key must be unique
but you can have duplicate values in your MAP.

Map<Integer, String> m = new Map<Integer, String>{5 => 'Jon', 6 => 'Quinton', 1 => 'Reid'};
Map<ID, Set<String>> m = new Map<ID, Set<String>>();
// creates a map where the key is the ID of the record
Map<Id,Account> aMap = new Map<Id, Account>([Select Id, Name From Account LIMIT 2]);