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
sfadmin 182sfadmin 182 

how to run a method at the end of the apex execution context

Hello all,

I have a requirement to notify an external system after every dml event for Leads, Accounts, Contacts and AccountContacRelations. The external system does not want to consume any SFDC api so it is up to my SFDC system to send all the notifications for each dml event on the said objects. I have triggers that call a method that creates the JSON package to send to the external system and initially was sending them through a future call, the callout is bulkified so at least a large number of any of the objects will be handled.

There is a problem here though, first many updates to different objects can potentially go over the maximum number of queued future calls. Second, i cant ensure the order of execution, so for example on a lead convert there will be a lead update notification, an account insert notification, a contact insert and an accountContacRelation insert notification. Plus since i have to update record types on a couple of these records, that causes extra dmls and extra notifications. Since the order of execution of the future methods cant be guaranteed, this has caused incorrect sequence of callouts to the external system.

I am unsure how to successfully approach this? I would much rather send one large JSON package with all the notifications included, but then how do i add the trigger.new records from all the triggers to a list<object> then call the callout method since i dont know which will be the last trigger to run or related class executed from those triggers? 

Alternatively, is there a way to run the callouts synchronously? Any help/feedback will be greatly appreciated.

 
Best Answer chosen by sfadmin 182
David Zhu 🔥David Zhu 🔥
This seems a good use case of using Salesforce platform event.
You can use future method in the trigger to avoid DML limit. 
If you have triggers on different object, you can push separate records to platform event when each trigger completes, you can use an ID to associate all the records.

Then you create a trigger on platform event checking if all neccessary records are in platform event, and do callout if all is done.

All Answers

David Zhu 🔥David Zhu 🔥
This seems a good use case of using Salesforce platform event.
You can use future method in the trigger to avoid DML limit. 
If you have triggers on different object, you can push separate records to platform event when each trigger completes, you can use an ID to associate all the records.

Then you create a trigger on platform event checking if all neccessary records are in platform event, and do callout if all is done.
This was selected as the best answer
sfadmin 182sfadmin 182
Thank you for your help, i have implemented the cahnges as per your suggestion and it is working exactly as i wanted it to. This is basically what i did:
  • created a platform event, set it to publish after commit.
    • added custom fields to map the values i want in the notification
  • on all the sObject triggers I call a utility method which
    • dynamically determines which is the sobject type
    • casts a list of that specific sobject type and maps the correct fields i want in the notification.
    • creates platform event records and publishes them
  • added a trigger on the platform event which will then parse the individual event records, map the values to a wrapper object and serialize that wrapper to json which matches exactly the format of the notification to be sent
    • I grouped all the notifications in one big list of json objects since this will send all the updates within that one transaction, this was the best approach for us since this ensured that the notifications are received in the order we want them to.
  • finally i call a future method to perform the callout to the external system and tests have shown it is working as expected.
NOTE: This is not a bullet proof solution since the callouts are future methods, so if two users are making changes at the same time to records related to a parent, we cant be 100% sure the notifications will still be received in the order they were created. That said, we include the replayId which tells us the order and the system receiving the notifications compensates accordingly. We could have gone with Change Data Capture feature but I think this doesnt support AccountContactRelation records which we need to support.