Saturday 18 May 2013

Master in Salesforce Apex collection

Before starting collection ,My first question is what is the meaning of collection? Why collection came to picture ?
Collection is nothing but a group of elements.So Now my question  is,  how can we handle a group of elements?  Ok we can handle a group of elements with help of array.My next question is Can we handle a group of objects with the help of array ? yes we can ,but still why we need collection ? What are the inconveniences  for which we need collection?
Below are the drawback with array for which we need collections.
1.We can not store different class objects into the same array, reason is that array can store a single data type.
2.We can add an element to the end of the array.But inserting and deleting  an element to the middle of the array is difficult.
3.We can retrieve the elements from the array but there is no such methods to process the elements.

Due to such problems  developers wants an object to store a group of  objects .Such an object is nothing but collection.

For a java developer apex collection is very simple, because java collection frame work  has a lot of classes,abstract classes and also interfaces.

Sales force Apex  has  only three types of  collections.
1.List :-
    List is an ordered collection of primitive,sObjects,userdefind objects,apex objects or collection that are distinguished by indexes.We can add duplicate element in the list.
List are index-based so the index position of first element in a list is always zero(0).
List can have upto five level of nested collection inside it.
2 . Set :-
      A set represents a group of  elements arranged just like an array. Set will grow dynamically    when the elements are stored into it .  Set elements can be of any data type—primitive , collections, sObjects, user-defined types, and built-in Apex types.Set will not allow duplicate elements.

3.Map:-
       A map is a collection of key-value pairs ,where key should be  unique and value can be duplicate . Each unique key maps to a single value.Through the key we can retrieve values.  
Keys and values can be any data type—primitive types, collections, sObjects, user-defined types, and built-in Apex types. 

Note : There is no such  limit on the number of items a collection can hold. How ever there is a general limit on  heap size.

All collection in apex are ordered from 34 version on wards .

Lets play with the methods of different collection.

List class have some methods ,just click on the link   list methods    to  refer  all list methods .

Set class have some methods ,just click on the link   set methods    to  refer  all Set methods .

Map class have some methods ,just click on the link   Map methods    to  refer  all map methods .


I think now we are familiar with all methods in above three classes .
Lets discuss one real time scenario where we can implement collection to over come the limits .

Here is one scenario like when you will update any  account owner then related contact owner should update with same value

Below is the trigger code which can write in Account and test it will work ,however in case of mass update it will give you error .

1.101 SOQL error because contact query is inside the for loop .
2.Too many  DML rows: 10001 .

Trigger updateownerofcontact on Account(before update) {
 for(Account currentAccount : trigger.new) {
  if(currentAccount.OwnerId != Trigger.oldMap.get(currentAccount.Id).OwnerId){
   for(Contact con: [SELECT Id, OwnerId, AccountId FROM Contact
                     WHERE  AccountId = :currentAccount ]) {
    con.OwnerId=currentAccount.OwnerId;
    update con;
   }
  }
 }
}
 
To avoid this we need to use collection ,check below code where collection
used to avoid all above error .
Here we need to remove contact query and update statement to out of for  loop 
  
Trigger UpdateOwnerOfContact on Account(before update) {
 //Map to collect account id with changed owner id(user id ) .
 Map<Id,Id> accIdWithOwnerIdMap = new Map<Id,Id>();
 List<Contact> listOfContactsToUpdate = new List<Contact>();
 for(Account currentAccount : trigger.new) {
     if(currentAccount.OwnerId != Trigger.oldMap.get(currentAccount.Id).OwnerId){
        accIdWithOwnerIdMap.put(currentAccount.Id,currentAccount.OwnerId);
     }         
 }
 if(!accIdWithOwnerIdMap.isEmpty()){
  for(Contact con: [SELECT Id, OwnerId, AccountId FROM Contact 
                    WHERE AccountId IN :accIdWithOwnerIdMap.keySet() ]) {
   con.OwnerId = accIdWithOwnerIdMap.get(con.AccountId);
   listOfContactsToUpdate.add(con);
  }
 }
 if(!listOfContactsToUpdate.isEmpty()) {
  try{
   update listOfContactsToUpdate;
  }catch(DmlException de){
   System.debug(de);
  }
  
 }




Saturday 9 March 2013

Concept of Salesforce Trigger

If I will ask question ,what is a  trigger in salesfore ? Is it a class,an Object or apex code ? Most of the people will answer Trigger is an apex code ,yes it is correct ,However rest two are also correct .
Trigger is an object where for each trigger we have written , Sales force will create a record in ApexTrigger object .To know more detail click on the link Trigger object details or login to workbench and select the object .
Trigger is also a class which contains twelve static context variable we will discuss in detail .

Salesforce  trigger executes when we do some DML operation in salesforce object.
In order to execution of trigger it is broadly  of two types ,After Trigger and Before Trigger.
Basic syntax of trigger:-
trigger triggerName on ObjectName (trigger_events) {
    //code_block
}
trigger TestTrigger on Case (Before Insert,After Insert,Before Update ,After Update ,Before Delete ,After Delete,After Undelete) {
 //Code Block
}

[Note:-Keep in mind that only the trigger of that particular object will invoke in which object we will do DML operation, not like  you will insert a record in child object and the trigger in parent object will invoke . It is possible to do  some data manipulation in different object but any way the trigger invoke only the object in which we will do Dml operation].

We can declare more than one trigger event in one trigger ,but each should be separated by comma.
Below are the possible event for trigger.

 >>Before Insert
>>Before Update
>> Before Delete
 >>After Insert
 >>After Update
 >>After Delete
>> After Undelete

There is a System defind class called Trigger which contains 12(twelve) implicit variable,which we can access at run time.
Below are the varibales with description.

1.isExecuting-It rutuns ture if the any code inside trigger context is executing.That means you can test whether your trigger is excuting or not by the help of this variable.It may be from salesforce user interface .apex or  any API


2.isBefore-It rutuns ture if the any code inside trigger context is executing before record is saved to the database.It may be from salesforce user interface .apex or  any API


3.isAfter-It rutuns ture if the any code inside trigger context is executing after record is saved to the database.It may be from salesforce user interface .apex or  any API


4.isInsert-It rutuns ture if the any code inside trigger context is executing due to an insert operation.It may be from salesforce user interface .apex or  any API

5.isUpdate-It rutuns ture if the any code inside trigger context is executing due to an update operation.It may be from salesforce user interface .apex or  any API


6.isDelete-It rutuns ture if the any code inside trigger context is executing due to a delete operation.It may be from salesforce user interface .apex or  any API


7.isUnDelete-It rutuns ture if the any code inside trigger context is executing due to undelete operation  i,e when we recovered data from recycle bin .It may be from salesforce user interface .apex or  any API .


8.new-It returns the new version of the object records.Suppose you have inserted/updated 10 records trigger.new will contain that 1o records .

9.newMap-It returns a map  which contains an IDs  as a key and  the old versions of the sObject records as value.This map is only available in before update, after insert, and after
update triggers.

10.old-It returns the old version of the object records

11.oldMap-It returns a map  which contains an IDs  as a key and  the new versions of the sObject records as value.This map is available for only update and delete trigger.

12.size- It return the size of the manipulated record .It will return one if you will insert one record, It will return the size of the record you are inserting ,updating or deleting or undeleting.

13.Operation Type- This will return an Enum(TriggerOperation) .  Below are the values in enum .
   
  • AFTER_DELETE
  • AFTER_INSERT
  • AFTER_UNDELETE
  • AFTER_UPDATE
  • BEFORE_DELETE
  • BEFORE_INSERT
  • BEFORE_UPDATE


Examples to test the implicit variable:
trigger  TestTrigger on Case (Before Insert,After Insert,Before Update ,After Update ,Before Delete ,After Delete,After Undelete) {
    System.debug('*********testExecution*************'+Trigger.isExecuting);
    System.debug('****************size of trigger***************'+Trigger.size);
    if(Trigger.isBefore){
        if(Trigger.isInsert){
            for(Case cs:Trigger.new){
                System.debug('********beforeInsertNew************'+Trigger.new);
            }
        }
        if(Trigger.isUpdate){
            for(Case cs:Trigger.new){
                System.debug('********beforeUpdateNew************'+Trigger.new);
                System.debug('**********beforeUpdateOld**********'+Trigger.old);
                System.debug('********beforeMapUpdateNewMap************'+Trigger.newMap);
                System.debug('**********beforeMapUpdateOldMap**********'+Trigger.oldMap);
            }
       }
        if(Trigger.isDelete){
            for(Case cs:Trigger.old){
             
                System.debug('**********beforeDeleteOld**********'+Trigger.old);
                System.debug('**********beforeMapDeleteOldMap**********'+Trigger.oldMap);
            }
      }
  }
    if(Trigger.isAfter){
        if(Trigger.isInsert){
             for(Case cs:Trigger.new){
                System.debug('**********afterInsertNew**********'+Trigger.new);
                System.debug('**********afterInsertNewMap**********'+Trigger.newMap);
             }
         }
        if(Trigger.isUpdate){
             for(Case cs:Trigger.new){
                System.debug('**********afterUpdateNew**********'+Trigger.new);
                System.debug('*************afterUpdateOld*******'+Trigger.Old);
                System.debug('**********afterUpdateNewMap**********'+Trigger.newMap);
                System.debug('*************afterUpdateOldMap*******'+Trigger.oldMap);
            }
        }
       if(Trigger.isDelete){
            for(Case cs:Trigger.old){
                System.debug('*************afterDeleteold*******'+Trigger.Old);
                System.debug('*************afterDeleteoldMap*******'+Trigger.oldMap);
            }
       }
       if(Trigger.isUnDelete){
            for(Case cs:Trigger.new){
                System.debug('**********afterunUndeleteNew**********'+Trigger.new);
                System.debug('**********afterunUndeleteNewMap**********'+Trigger.newMap);
             
           }
       }
    }
}
[Note: Just copy this code and paste in case object or else in which object you want to test just the object name you need to change in the above example.After saving the trigger you can insert ,update ,delete and undelete records and just create debug log for different situation and observe.]

Below is the steps how to add this trigger in sales force in case object.
click Your Name Setup Cases Case   Triggers  New
Just remove the existing code and paste the above code ans save the code .
After that follow the below steps to create the debug log.
click Your Name Setup Monitoring Debug logs  
Click on New button to set the debug log in your name .
Now you can create record for case object and try to observe the debug log and just realize all context variable.
Just Insert ,update delete and undelete one record from recycle bin.

Also you can write trigger from developer console 

In the Developer Console, click File | New | Apex Trigger

 Click the below link for some more concepts on before insert trigger .

Before insert conecpt