Skip to content

BeforeInsert

Runs in before insert, before new records are saved. Set fields with a Populator or reject records with a Validator.

Roles

  • Populator: set, default or normalize fields on the new record.
  • Validator: reject a record with an error message.

Add-ons

  • ParentQuery: load parent (lookup) fields before the first handler runs; read them with getNewParent.
  • RelatedQuery: query children, siblings or any other records once per chunk; read them with getRelated.
  • Bypassable: skip this handler for the whole chunk when a condition holds.
  • Finalizer: run once after this handler’s records, with the records that qualified.
  • ContinueOnError: log and swallow this handler’s exceptions, so the save goes on.

Register

Implement TriggerOrchestrator.BeforeInsert on the orchestrator and return the handlers from beforeInsertHandlers(). List order is run order. The trigger must list before insert and call TriggerOrchestrator.run(new ContactTriggerOrchestrator()).

apex
public with sharing class ContactTriggerOrchestrator implements TriggerOrchestrator.BeforeInsert {
    public List<BeforeInsert.Handler> beforeInsertHandlers() {
        return new List<BeforeInsert.Handler>{ new ContactPopulator(), new ContactValidator() };
    }
}

Good to Know

  • No Id yet. record.getId() is null and records.getIds() is empty. Never key a map by the record Id here.
  • No DML. If a handler runs DML or publishes an event, the library throws. Change other records from an AfterInsert.Writer.
  • Lookups hold only the Id. ((Contact) record.getNewSObject()).Account is null. Declare a ParentQuery and read record.getNewParent('Account').
  • One role per class. A class that implements both roles runs only as a Populator. List Populators first, so Validators see the values they set.
  • Called per chunk. beforeInsertHandlers() runs for every chunk of up to 200 records. Handlers created there start with empty instance fields each time; static fields last the whole transaction.