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
louisa barrett 7louisa barrett 7 

Call future method from trigger handler class method

Hi,
This is my first time using the @future annotation and was wondering if I could get some guidance.
I have a trigger on the contact, which is handled by a handler class. When a contact is deleted, I need to perfom a call out, so within the handler class I need to call a future method to perform that call out. As a future method only takes primitive data types, I have created another method which passes just the IDs to the future method. Is this the correct way to do this, or is there a better way?
I'm also a little concerned what happens if a mass delete is performed. How do you bulkify call outs?

Trigger:
trigger ContactTrigger on Contact (before delete, before insert, before update, after delete, after insert, after update) 
{
    ContactTriggerHandler handler = new ContactTriggerHandler(Trigger.isExecuting, Trigger.size);
    
    if (Trigger.isInsert && Trigger.isBefore)
    {
        handler.OnBeforeInsert(Trigger.new);       
    }
    else if (Trigger.isInsert && Trigger.isAfter)
    {
        handler.OnAfterInsert(Trigger.new, Trigger.newMap);
    }
    else if (Trigger.isUpdate && Trigger.isBefore)
    {
        handler.OnBeforeUpdate(Trigger.old, Trigger.oldmap, Trigger.new, Trigger.newmap);
    }
    else if (Trigger.isUpdate && Trigger.isAfter)
    {
        handler.OnAfterUpdate(Trigger.old, Trigger.oldmap, Trigger.new, Trigger.newmap);
    }
    else if(Trigger.isDelete && Trigger.isBefore)
    {
        handler.onBeforeDelete(trigger.old, trigger.oldMap);
    }
    else if(Trigger.isDelete && Trigger.isAfter)
    {
        handler.onAfterDelete(trigger.old, trigger.oldMap);
    }
}

Trigger handler class:
public class ContactTriggerHandler extends BaseTriggerHandler
{
    public ContactTriggerHandler(boolean isExecuting, integer size)
    {
        super(isExecuting, size);
    }
    
    public void OnBeforeInsert(Contact[] newContacts) 
    {}     
    
    public void OnAfterInsert(Contact[] newContacts, Map<ID, Contact> newContactsMap) 
    {}
    
    public void OnBeforeUpdate(Contact[] oldContacts, Map<ID, Contact> oldContactsMap, Contact[] updatedContacts, Map<ID, Contact> updatedContactsMap)
    {}
    
    public void OnAfterUpdate(Contact[] oldContacts, Map<ID, Contact> oldContactsMap, 
                              Contact[] updatedContacts, Map<ID, Contact> updatedContactsMap)
    {}
    
    public void OnBeforeDelete(Contact[] oldContacts, Map<ID, Contact> oldContactsMap)
    {}
    
    public void OnAfterDelete(Contact[] oldContacts, Map<ID, Contact> oldContactsMap)
    {
        passIDsToCallOut(oldContactsMap);
    }

    Private void passIDsToCallOut(Map<ID, Contact> contactsMap)
    {
        Set<Id> conIds = contactsMap.keySet();
        system.debug('con Ids for forget request');
        system.debug(conIds);
        sendForgetRequestGDPR(conIds);
    }
    
    @future(callout=true)
    Public static void sendForgetRequestGDPR(Set<id> contactIds)
    {
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://****.com/api/auth/v1/login?email=myemail@email.co.uk&password=myPassword');
        request.setMethod('POST');
        request.setHeader('Content-Type', 'application/x-www-form-urlencoded');
        request.setHeader('Accept', 'application/json');
        HttpResponse authResponse = http.send(request);
        if (authResponse.getStatusCode() == 200) {
            system.debug('got auth!');
            // Deserialize the JSON string into collections of primitive data types.
            Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(authResponse.getBody());
            List<Object> myresults = new List<Object>();
            for(Object obj : results.values())
            {
                myresults.add(obj);
            }
            string sessionId = string.ValueOf(myresults[0]);
            system.debug('session Id = ' +sessionId);
            request = new HttpRequest();
            request.setEndpoint('https://*****.com/api/v1/services/*****/gdpr/forget');
            request.setMethod('POST');
            request.setHeader('Content-Type','application/x-www-form-urlencoded');
            request.setHeader('Accept','application/json');
            request.setHeader('X-SESSION-ID',sessionId); 
            string comment = 'API Call';
            string contactId;
            for(Id conId : contactIds)
            {
                contactId = conId;
                request.setBody('record_id='+contactId+'&table_name=Contact&comment=' + EncodingUtil.urlEncode(comment, 'UTF-8'));
                system.debug(request);
                HttpResponse forgetResponse = http.send(request);
                if(forgetResponse.getStatusCode() == 200)
                {
                    system.debug('got GDPR!');
                }
                else
                {
                    system.debug('Forget Broken =' + forgetResponse.getStatusCode());
                }           
            }       
        }
        else
        {
            system.debug('Auth Broken =' + authResponse.getStatusCode());
        } 
    }
}

Many thanks
 
SUCHARITA MONDALSUCHARITA MONDAL

Hi Louisa,

Please check with the following link: (for more insights)
https://salesforce.stackexchange.com/questions/107095/callouts-bulkification-in-triggers

Hope this helps!
Sucharita

louisa barrett 7louisa barrett 7
Hi,
Thank you for the link. My primary concern was related to calling the future method(sendForgetRequestGDPR) from the method(passIDsToCallOut) that is called from the trigger. Is it ok to do it like that? 

Thanks