BeforeUpdate.Finalizer
Runs once after the handler has processed the chunk, with the records that qualified. Use it for checks across records, such as duplicates within one save.
Interface
apex
public class BeforeUpdate {
public interface Finalizer {
void finalizeBeforeUpdate(TriggerHandler.UpdateRecords records);
}
}finalizeBeforeUpdate(records): called once per chunk, after this handler’s records, only if at least one record qualified. It receives only the qualified records.
Example
apex
public with sharing class ContactPopulator implements BeforeUpdate.Populator, BeforeUpdate.Finalizer {
public Boolean populateOnBeforeUpdateWhen(TriggerHandler.UpdateRecord record) {
return record.isChanged(Contact.Email) && record.isNotBlank(Contact.Email);
}
public void populateOnBeforeUpdate(TriggerHandler.UpdateRecord record) {
record.put(Contact.Email, ((Contact) record.getNewSObject()).Email.trim().toLowerCase());
}
public void finalizeBeforeUpdate(TriggerHandler.UpdateRecords records) {
Set<String> emails = new Set<String>();
for (TriggerHandler.UpdateRecord record : records.getRecords()) {
Contact contactRecord = (Contact) record.getNewSObject();
if (!emails.add(contactRecord.Email)) {
contactRecord.Email.addError('Another contact in this save has the same email.');
}
}
}
}Good to Know
- Put it on a Populator. On a Validator, it receives only the records that Validator already rejected.
putworks here.records.getRecords()returnsUpdateRecords. On a Populator, a lookup the Finalizer re-points is loaded before the next handler runs.- Reject with the field form.
UpdateRecordhas noaddError. Call((Contact) record.getNewSObject()).Email.addError(message), as the Skeleton does. - Only this chunk. Other chunks of the same update are out of reach. A query returns their saved values.
- No DML. If the Finalizer runs DML or publishes an event, the library throws, even with ContinueOnError.
