4

This could be quite a dumb question though, I would like to ask is there a way to retrieve the oldMap of a trigger in a @future method?

In the below code please refer the collection "oldReportsMap", Can I refer the old map of the record Ids?

BELOW CODE IS THE EXSISTING ONE AND NEED TO MAKE GENERIC FOR MULTIPLE OBJECTS
/*
 * Populate acount fields on creation of the Report record.
 */
public class updateAccountFields implements Triggers.Handler {
    public void run(){

        if (!(Trigger.isAfter && Trigger.isInsert)) { return; }

        List<Report__c> triggerReports = (List<Report__c>) Trigger.new;
        Set<Id> reptIds = new Set<Id>();

        for (Report__c report: triggerNewReports) { 
            reptIds.add(report.id);
        }

        // process accounts fields
        if (Test.IsRunningTest()) {
            processUpdateAccountFields(reptIds);
        } else {
            processUpdateAccountFieldsFuture(reptIds);
        }

    }
}

@future
public static void processUpdateAccountFieldsFuture(Set<ID> reptIds) {
    processUpdateAccountFields(reptIds);
}

/*
 * Populate account fields on creation of the Report record.
 */
public static void processUpdateAccountFields(Set<ID> reptIds) {   
    Set<Id> acctIds = new Set<Id>();

    Map<Id, Report__c> reports = new Map<Id, Report__c>([SELECT Id, ReceivedDate__c, DueDate__c, Account__c FROM Report__c WHERE id IN: reptIds]);

    // retrieve the related accounts
    for (Report__c report: reports) { 
        acctIds.add(report.Account__c);
    }

    Map<Id, Report__c> oldReportsMap = new Map<Id, Report__c>([SELECT Id, ReceivedDate__c, DueDate__c, Account__c FROM Report__c WHERE id IN: ????]);

    for(Id reptId :  oldReportsMap.keyset()){
        ... some more code...
    }
    .... Some more code/logic....
}

Thanks

UPDATE:

Unfortunately serialization doesn't work for me it takes considerable amount of time to serialize the old object, and I have an sObject which could be a standard object or a custom object depends on the sObjectType. eg: our account object has 943 fields at the moment. I do not want to serialize all account object's fields just to track one field change. so far what I could see is, according to my scenario, there is no way of accessing oldMap since it is not in the trigger context when at a future call.

  • I found that there is an idea to for an isChangefunctionality for apex.
  • please note that our org gets updates for multiple objects via webservice API and this could update considerable number of records at a one call, which leads to a timeout the service request due to above mention issue.

Thanks all for your support!

  • 4
    you could always use json.serialize and put it in a string – cropredy Jan 28 '16 at 1:52
  • 2
    depends on how big the sobject is (# fields); of course you could always extract only the fields you care about and serialize those – cropredy Jan 28 '16 at 2:25
  • 4
    You could also construct a Queueable with that map. – Adrian Larson Jan 28 '16 at 4:16
  • 1
    Yes use json.serialize and again in your future method use json.deserialize to get that list.. – Ratan Paul Jan 28 '16 at 5:03
  • 1
    I disagree that this question is a duplicate. oldMap records can't be accessed via Id. – Adrian Larson Jan 28 '16 at 19:00
1

If the poor performance of the serialization process is a roadblock for you, I recommend you create a Queueable implementation instead of using @future. It would look something like:

public with sharing class MyAsyncProcessor implements Queueable
{
    final Map<Id, Report__c> oldMap;
    public MyAsyncProcessor(Map<Id, Report__c> oldMap) { this.oldMap = oldMap; }
    public void execute(QueueableContext context)
    {
        // run your logic here
    }
}

Then in your trigger/handler, you would just do something like:

system.enqueueJob(new MyAsyncProcessor(trigger.oldMap));

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.