BeforeUpdate.Bypassable
Skips a Populator or Validator for the whole chunk when a condition holds, such as a static flag or a custom permission.
Interface
apex
public class BeforeUpdate {
public interface Bypassable {
Boolean bypassOnBeforeUpdateWhen();
}
}bypassOnBeforeUpdateWhen(): called once per chunk, before parents load; not called when metadata orTriggerOrchestrator.bypass()already skips the handler. Returnstrueto skip this handler for this chunk.
Example
apex
public with sharing class ContactPopulator implements BeforeUpdate.Populator, BeforeUpdate.Bypassable {
public static Boolean isDisabled = false;
public Boolean bypassOnBeforeUpdateWhen() {
return ContactPopulator.isDisabled;
}
public Boolean populateOnBeforeUpdateWhen(TriggerHandler.UpdateRecord record) {
return record.isChanged(Contact.Email);
}
public void populateOnBeforeUpdate(TriggerHandler.UpdateRecord record) {
record.put(Contact.HasOptedOutOfEmail, false);
}
}cls
public with sharing class OpportunityReopenValidator implements BeforeUpdate.Validator, BeforeUpdate.Bypassable {
public static Boolean isBypassed = false;
public Boolean bypassOnBeforeUpdateWhen() {
return isBypassed;
}
public Boolean errorShouldBeAttachedOnBeforeUpdateWhen(TriggerHandler.UpdateRecord record) {
return record.isChangedFrom(Opportunity.StageName, 'Closed Won');
}
public void addErrorOnBeforeUpdate(TriggerHandler.RejectableUpdateRecord record) {
Opportunity newOpportunity = (Opportunity) record.getNewSObject();
record.addError(
Opportunity.StageName,
'A Closed Won Opportunity cannot be moved back to ' + newOpportunity.StageName + '. Raise a new Opportunity for the follow-up business.'
);
}
}Good to Know
- Not per record. To skip only some records, return false from the predicate.
- Reset a static flag in
finally. The flag stays set for every chunk and every nested update in the transaction. - Exceptions here are not logged.
bypassOnBeforeUpdateWhen()runs outside the handler's error handling. ContinueOnError does not apply, and the update fails. - Only this context. A
TriggerHandler__mdtrow orTriggerOrchestrator.bypass().handler(X.class)switches the class off in every context. This add-on skips only before update. - Inner classes need this add-on.
TriggerOrchestrator.bypass().handler(X.class)and.orchestrator(X.class)never match an inner class. Use aTriggerHandler__mdtrow or this add-on.
