Tuesday, November 20, 2018

Asynchronous Apex: Future Method in Salesforce.com

Future Method

1) Making callouts to external web services. 
i.e. When we are making callouts to external web services from a trigger or after performing a DML operation, we must use a future or queueable method.

2) Process we want to run in its separate thread in the back-end.
i.e. When we are working on some sort of resource consuming calculation or processing of records.

3) Isolating DML operations on different types of sObject.
i.e. When we are performing DML on setup and non-setup sObject types, it isolates DML to prevent the "Mixed DML Errors".


Future Method Syntax:
global class FutureClass {
     @future
     public static void futureMethod(List<Id> recordIds) {
     List<Account> accounts = [Select Id, Name from Account Where Id IN :recordIds];
     // process account records to do awesome stuff
     }
}


Future Method Considerations

1) Future methods must be static methods and return a void.

2) Parameters must be primitive data types, arrays of primitive data types, or collections of primitive data types.
Note:- Future methods can’t take standard or custom objects as arguments.

3) Common pattern is to pass a List<record IDs> that you want to process asynchronously.

4) Future methods can’t be used in Visualforce controllers in getMethod(), setMethod(), nor in the constructor.

5) You can’t call a future method from a future method.

6) You can not invoke a trigger that calls a future method while running a future method.

7) The getContent() and getContentAsPDF() methods can’t be used in future method.

8) You’re limited to 50 future calls per Apex invocation.

9) To test future methods, enclose your test code between the test.startTest() and test.stopTest() test methods.


Saturday, November 17, 2018

REGEX function, Validation Rule in Salesforce.com

REGEX or Regular Expression in Salesforce

REGEX(Input_Field_Name, 'Input_Format_Expression')

i.e. BLKPR7234B or blkpr7234b: 

NOT REGEX( PAN_Number__c , '[A-Z,a-z]{5}[0-9]{4}[A-Z,a-z]{1}' )

This function is Boolean, which is used to compare text format between the input text and the specified expression. If both the text format and expression are equal, then it returns true, else it returns false.

Prepare the regular expression by using wild-card characters as below.

[ ] --> Indicates a collection of characters

[A-Z] --> Indicates a collection of characters falls
between A-Z.

[a-z] --> Indicates a collection of characters falls
between a-z.

[A-Z,a-z] --> Indicates a collection of characters falls
between A-Z or a-z or combination of both.

[0-9] --> Indicates a Number, where each digit should be
falls between 0-9.

{Number} --> Indicates the Number of characters should be 
used in the string.

[JKL] --> Indicates a collection of characters, where
each characters should be either J/K/L.

 -  --> Represents a Single Character.

PAN Number Format: BLKPR 7234 J

BLKPR --> 5
7234   --> 4
J         --> 1

BLKPR7234J:
Format: [A-Z]{5}[0-9]{4}[A-Z]{1}


bLkPr7234j: 
Format: [A-Z,a-z]{5}[0-9]{4}[A-Z,a-z]{1}

//Create a validation rule, to validate the PAN Number format.
Validation Condition: 

i.e. BLKPR7234B or blkpr7234b: 

NOT REGEX( PAN_Number__c , '[A-Z,a-z]{5}[0-9]{4}[A-Z,a-z]{1}' )













Saturday, November 10, 2018

Mixed DML Error in Apex in Salesforce.com

Mixed DML Error 
Concept of Mixed DML error is to prevent transaction from incorrect user level access in the org.
Mixed DML error occurs when you try to insert or update the setup and non setup object records simultaneously.
To overcome from this restriction you need to insert or update setup and non setup object records separately, where one method must be implementing @future keyword.

Note:- This restriction exists because some sObjects affect the user's access to records in the org.

e.g. you can’t update an account and a user role in a single transaction but deleting has no restriction.

These fields of user object can not be updated
* Username
* ProfileId
* UserRoleId
* IsActive
* ForecastEnabled
* IsPortalEnabled

ApexCode1A

public class MixedDMLClass {
    public static void createAccountAndUser () {
        // First DML operation
        Account account = new Account(Name='Acme');
        insert account;
       
        // Second DML operation (insert a user with a role) can't be mixed with              // the previous insert unless it is within a future method.
        // Call future method to insert a user with a role.
        CreateUserUtil.insertUserWithRole(
           'allen','allenAs', 'allen@gmail.com', 'paul'
           );       

    }
}

ApexCode1B

public class CreateUserUtil {
    @future
    public static void insertUserWithRole(String uname, String alias, String email, String lname){

        Profile std_profile = [Select Id From Profile Where Name='Standard User'];
        UserRole coo_role = [Select Id From UserRole Where Name='COO'];

        // Create new user with a non-null user role ID
        User user = new User(
lastname=lname,
username=uname,
profileid = std_profile .Id,
userroleid = coo_role.Id,
alias = alias,
email=email,
emailencodingkey='UTF-8',
languagelocalekey='en_US',
localesidkey='en_US',
timezonesidkey='America/Los_Angeles'
);

        insert user;
    }
}










Thursday, November 8, 2018

Trigger to count total number of contacts of account in Salesforce.com

Rollup Summary Trigger on Account in Salesforce.com

trigger numberContactsEachAccount on Contact (after insert,after delete,after undelete,after update) {

Set<Id> accountIds = new Set<Id>();
 
//for insert and undelete operation
if(Trigger.isAfter && (Trigger.isInsert || Trigger.isUndelete)){
        for(Contact con : Trigger.New){
        accountIds.add(con.AccountId);
        }
List<Account> accList = [Select Id, Number_of_Contacts__c, (Select Id from Contacts) From Account Where Id In :accountIds];

for(Account acc : accList){
        acc.Number_of_Contacts__c = acc.contacts.size();
        }
update accList;
}

//for delete operation
if(Trigger.isAfter && Trigger.isDelete){
        for(Contact con : Trigger.old){
            accountIds.add(con.AccountId);
            }
     
List<Account> accList = [Select Id, Number_of_Contacts__c, (Select Id From Contacts) From Account where Id In :accountIds];

for(Account acc : accList){
acc.Number_of_Contacts__c = acc.contacts.size();
}
update accList;
}

//for update trigger
if(Trigger.isAfter && Trigger.isUpdate){
for(Contact con : Trigger.newMap.values()){
            //comparing accountId of both new and old contacts
            if(con.AccountId != Trigger.oldMap.get(con.id).AccountId ) {
                accountIds.add(con.AccountId);
                accountIds.add(Trigger.oldMap.get(con.id).AccountId);
            }
}
List<Account> accList = [Select Id, Number_of_Contacts__c, (Select Id From Contacts) From Account Where Id In :accountIds];

for(Account acc : accList){
acc.Number_of_Contacts__c = acc.contacts.size();
}
update accList;
    }
}






Click on image to view...






Governor Limits in Salesforce.com

Governor Limits

Governor Limits come into picture because of multitenant architecture of Salesforce.com, which enforce resources availability for each users.

Total number of SOQL queries >> 100 >> (Asynchronously: 200)


Total number of records retrieved by SOQL queries >> 50,000

Total number of SOSL queries issued >> 20

Total number of records retrieved by a single SOSL query >> 2,000

Total number of DML statements issued >> 150

Total number of records processed as a result of >> 10,000

DML statements or
Database.emptyRecycleBin or 
Approval.process 

Total heap size >> 6 MB >> (Asynchronously: 12 MB)              

Maximum CPU time on the servers >> 10 sec >> (Asynchronously: 60 sec)

Maximum Callouts >> 100

Total number of sendEmail methods allowed >> 10

Total number of the future call >> 50

Number of Queueable job added to the queue >> 50

Total number of records retrieved by Database.getQueryLocator >>       10,000

Maximum execution time for each Apex transaction >> 10 min

Total stack depth for any Apex invocation that >> 16

recursively fires triggers due to insert, update or delete 
            
Total number of callouts  in a transaction >> 10
(HTTP requests or Web services calls)

Maximum timeout for all callouts in a transaction >> 120 sec
(HTTP requests or Web services calls)

Number of mobile apex push call >> 10










Bulkified and Non-Bulkified Apex Code concepts in Salesforce.com

Non-Bulkified code:
It can not process large set of data and eventually can hit governor limit because it works on one record.

For example: It can process only one (first) account record from the Trigger.new collection, but if more than one account has initiated this trigger, then those additional records will not be processed.

trigger nonBulkifiedTrigger on Account (before insert, before update) {

   //It can get only first record from the collection


   Account acct = Trigger.new[0];
   List<Contact> contacts = [Select id, firstname, lastname, email 
                                                        From Contact 
                                                        Where accountId = :acct.Id];
   
}

Bulkified Code:
It can process large set of data and escape governor limit because it works on list of records.

For example: It can process all account record from the Trigger.new collection.

trigger bulkifiedTrigger on Account (before insert, before update) {

    //Loop through all records in the Trigger.new collection
    for(Account a: Trigger.new){

    //Concatenate the Name and billingState into the Description field
    a.Description = a.Name + ':' + a.BillingState
   }
}










Handle exception by Try, Catch and Finally statement in Apex in Salesforce.com

Try-Catch-Finally Statements Syntax:

try {

      //Perform some operation that might cause an exception.

} catch (exception e){ 

      //Handle generic exception here.

catch (dmlexception de){ 

      //Handle dml exception here.

finally { 

      //this block of code always execute and allows you to clean up your code.

}

Apex Code

try {
  // Perform some operation that might cause an exception.
    Merchandise__c m = new Merchandise__c();
    insert m;

    // This doesn't execute since insert causes an exception
    System.debug('Statement after insert.');

} catch (Exception e) {
    
   // Handle generic exception here.
   }catch(DmlException e) {
    System.debug('The following exception has occurred: ' + e.getMessage());
    
 } finally {
    // Perform some clean up.
}










Validation in flow input text field in sfdc: Maximum 255 characters limit

The input text field validate in sfdc flow behaves opposite of the generic sfdc validation rule.  Here the validation formula is evaluating ...