function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
William Roach-BarretteWilliam Roach-Barrette 

Future method cannot be called from a future or batch method

Dear Forum, 

I am trying to develope an Apex program and corresponding trigger that will grab JSON from an endpoint im hosting and based on values inside that json file make updates to custom fields "checkboxes" under the contacts object. Right now I have a wrapper that stores my JSOn, a program that grabs my data from an endpoint then stores it, and finally a piece of data that creates a list of contact objects that I then use to update my database. The problem is I am now getting this error: "Future method cannot be called from a future or batch method." Below are snippits of code showing what I am doing, as well as the corresponding apex trigger. I am still very new to Apex development and apologize if this question was ansered in another post somewhere else. 
public class JSONDeserialize {

    public GDPRWrapper wrapper {get;set;}
    public JSONDeserialize(){
    
        
        deserialize();
    }
    
    @Future(callout=true)
    public static void deserialize() {
        GDPRWrapper wrapper;
    
        
        Http h = new Http();
        HttpRequest request = new HttpRequest();
        
        request.setEndPoint('***********************');
        Blob headerValue = Blob.valueOf('*****************');
        String authorizationHeader = ('Basic ' + EncodingUtil.base64Encode(headerValue));
        
        
        request.setHeader('Authorization', authorizationHeader);
        request.setMethod('GET');
        
        HttpResponse response = h.send(request);
        
        
        List<GDPRWrapper.GDPRData> obj = GDPRWrapper.parse(response);
        wrapper = new GDPRWrapper(obj);
         
        System.assert(wrapper.GDPRList!=null);
        updateData(wrapper);
        

      }
      
      
      public static void UpdateData(GDPRWrapper wrapper){
                    List<Contact> contactPref = new List<Contact>();
          
        for(Integer i = 0; i < wrapper.GDPRList.size(); i ++){
            Contact toInsert = new Contact();
            toInsert.firstName = wrapper.GDPRList[i].firstName;
            toInsert.lastName = wrapper.GDPRList[i].lastName;
            toInsert.email = wrapper.GDPRList[i].email;
            
            toInsert.Id = wrapper.GDPRList[i].contactId;
            toInsert.Sales_and_Marketing__c = wrapper.GDPRList[i].marketing;
            toInsert.Critical_Security_Notes__c = wrapper.GDPRList[i].security;
            toInsert.Product_Information__c = wrapper.GDPRList[i].support;
            toInsert.Contact_Via_Text__c = wrapper.GDPRList[i].contactPhone;
            toInsert.Contact_Via_Email__c = wrapper.GDPRList[i].contactEmail;
            contactPref.add(toInsert);
            
          
        
        }
          try{
              insert contactPref;
           
                        
            } 
            catch(DmlException e){
                    System.debug('An unexpected error has occured: ' + e.getMessage());
                }
      
      }
     }
 
public class GDPRWrapper{

    public GDPRWrapper(List<GDPRData> templst){
            GDPRList = templst;
        }
    public List<GDPRData> GDPRList {get; set;}

    public class GDPRData {

        public Integer gdprId {get; set;}  //26636
        public String firstName {get; set;}
        public String lastName {get; set;}
        public String email {get; set;}
        public String phone {get; set;}
        public String accountName {get; set;}
        public String contactId {get; set;}    //AA111222333AAAe
        public String emailHash {get; set;}    //78fcb5ad502033c46d35abcecb3615bd92757fb0451485a19b27b7515f6d82d0
        public String createDate {get; set;}   //2018-05-17T15:19:37.000+0000
        public String responseDate {get; set;} //2018-05-21T10:38:53.000+0000
        public String notifyDate {get; set;}
        public boolean marketing {get; set;}
        public boolean security {get; set;}
        public boolean support {get; set;}
        public boolean contactPhone {get; set;}
        public boolean contactEmail {get; set;}
        public boolean contactOther {get; set;}
        public boolean invalid {get; set;}
        
        
    }
   public static List<GDPRData> parse(httpResponse json){
        return (List<GDPRData>) System.JSON.deserialize(json.getBody(), List<GDPRData>.class);
    }
 
   
        }
        
}
 
trigger GDPR_Prefrences_Updater on Contact (after insert, after update) {
    JSONDeserialize.deserialize();

}

 
Best Answer chosen by William Roach-Barrette
Narender Singh(Nads)Narender Singh(Nads)
Hi Willliam,
Your code looks except for few mistakes.
The major problem with your code is you are using after insert and after update. So what's happening is when you insert a contact, your trigger is executed, an your trigger is calling a future method which is inserting a list of contacts. So when this future method inserts a contact, your trigger is again executed, calling the future method again!
End result:
Your future method ends up calling the same future method again. Hence the error.
Note: Let's say if you instead of a future method you had a normal method, in that case you would have faced a problem of Infinite loop of trigger call(Because everytime you insert a record, your trigger will be executed). 

Refer to this link to get some more understanding of it: https://www.linkedin.com/pulse/considerations-invoking-future-method-from-trigger-andi-giri/

The solution of this will depend on what exactly you are trying to achieve.

Mark it as the best answer if it helps you so that other can benefit from this post as well.
Regards,
Nads

All Answers

William Roach-BarretteWilliam Roach-Barrette
Thanks! This worked and has fixed this particular error.
Narender Singh(Nads)Narender Singh(Nads)
Hi Willliam,
Your code looks except for few mistakes.
The major problem with your code is you are using after insert and after update. So what's happening is when you insert a contact, your trigger is executed, an your trigger is calling a future method which is inserting a list of contacts. So when this future method inserts a contact, your trigger is again executed, calling the future method again!
End result:
Your future method ends up calling the same future method again. Hence the error.
Note: Let's say if you instead of a future method you had a normal method, in that case you would have faced a problem of Infinite loop of trigger call(Because everytime you insert a record, your trigger will be executed). 

Refer to this link to get some more understanding of it: https://www.linkedin.com/pulse/considerations-invoking-future-method-from-trigger-andi-giri/

The solution of this will depend on what exactly you are trying to achieve.

Mark it as the best answer if it helps you so that other can benefit from this post as well.
Regards,
Nads
This was selected as the best answer
Asad WaliAsad Wali

How about this Error ?

 Update failed. First exception on row 0 with id 00Q2x00000CZm0tEAD; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, TriggerOnLead: execution of AfterUpdate

How can we resolve this error ?