Sunday, 27 August 2017

Future Method And Prevent Mixed DML Error Using Future Method



Future Method

Future method is the asynchronous method which runs in background and used to run processes in separate thread, when system resources become available.
We use @future annotation to define future method.
We can call future method for long-running processes, such as calling external web services or any operation you would like to run in its own thread.
We can also use future method to overcome Mixed DML Error.
Each future method is queued and executes when system resource available then execution of future method does not have to wait for the completion of long running processes.


Note-



      1.      Method with the future annotation must be static method with void return type.

      2.      Methods with the future annotation cannot take sObjects or objects as arguments.

      The reason why sObjects cannot be passed as arguments to future methods is because the sObjects might change between you call the future method and the time it executes.

      Syntax of future method

global class FutureMethodClass
{
    @future
    public static void processRecords(List<ID> recordIds)
    {  
         // Get those records based on the IDs
         List<Account> accts = [SELECT Name FROM Account WHERE Id IN :recordIds];
         // Process your  records here
    }
}
     
      Now if you want to call any external web service from future method then use syntax, see below-
         
     
global class FutureMethodClass
{
    @future(callout=true)
    public static void processRecords(List<ID> recordIds)
    {  
          // Perform a callout to an external service
    }
}

      Prevent Mixed DML Error Using Future Method

Now, let’s see how to use future method and how to overcome MIXED DML Error by using future method, firstly understand about Mixed DML Error.

What is Mixed DML ERROR?

This error occurs when you are performing DMLs on setup objects and Non-setup objects simultaneously. So in other words we can say in a piece of code you cannot INSERT/UPDATE/DELETE commands on Setup objects and Non-Setup objects together.
Setup Objects are—User, RecordType, Profile etc.
Non-Setup Objects are—All other  general objects like native objects(Standard Objects) and custom objects falls in to category of Non-setup objects. Ex- Contact, Account, Lead etc.

Now remove this error by taking an example—

Scenario is, insert user with non-null role after account has been inserted.

Step-1

Create apex class and write code to insert account and then insert user like-

public class MixedDMLFuture
{
    public void insertUserWithAccount()
    {
        Account a=new Account(Name='Aman');
        insert a;
        Profile p = [SELECT Id FROM Profile WHERE Name='Standard User'];
        UserRole r = [SELECT Id FROM UserRole WHERE Name='COO'];
        // Create new user with a non-null user role ID
        User u = new User(alias = 'mruiz', email='gargarun25322@gmail.com',
            emailencodingkey='UTF-8', lastname='garg',
            languagelocalekey='en_US',
            localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
            timezonesidkey='America/Los_Angeles',
            username='gargarun25322@gmail.com');
        insert u;
        
}

      Now run this class from developer console using anonymous window

MixedDMLFuture m=new MixedDMLFuture();
m.insertUserWithAccount();

Then you will get Mixed DML Error like—


Now to overcome this error, Inserting of user must be done in separate thread from DML operation and use future method to achieve this.

The future method, insertUserWithRole which is defined in FutureClass, perform the insertion of user with CEO role. insertUserWithAccount method in MixedDMLFuture class insert an account and calls the future method, insertUserWithRole.

This is the definition of the FutureClass class, which contains the future method for inserting a user with a non-null role.


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

        Profile p = [SELECT Id FROM Profile WHERE Name='Standard User'];
        UserRole r = [SELECT Id FROM UserRole WHERE Name='CEO'];
        // Create new user with a non-null user role ID
        User u = new User(alias = alias, email=email,
            emailencodingkey='UTF-8', lastname=lname,
            languagelocalekey='en_US',
            localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
            timezonesidkey='America/Los_Angeles',
            username=uname);
        insert u;
    }
}
    
     This is the class containing the main method that calls the future method defined previously.

public class MixedDMLFuture
{
    Public static void insertUserWithAccount()
    {
        Account a=new Account(Name='Aman');
        insert a;
       
        FutureClass.insertUserWithRole(
            'gargarun25322@gmail.com', 'mruiz',
            'gargarun25322@gmail.com', 'garg');
    }
}
     
      
     Now run the class then no error will come and you can insert both account and user successfully.

Limitations of Future Method-

  1. A future method cannot invoke another future method.
  2. No more than 50 methods call per Apex execution.
  3. The maximum number of future method invocation per a 24 hours period is 250,000 or the number of user licenses in your organization multiplied by 200, whichever is greater.



0 comments:

Post a Comment

If you have any doubts, please let me know.