Add Validation in Apex
By the end of this lesson, you'll be able to:
- Prevent an Opportunity from being marked Closed Won without a positive Amount
- Use addError() to block a save with a field-level message
- Explain why this validation belongs in a before trigger, not after
Prerequisites: "Bulkify the Logic"
The validation rule
public void beforeUpdate(List<Opportunity> newOpportunities, Map<Id, Opportunity> oldMap) {
for (Opportunity opp : newOpportunities) {
Opportunity oldOpp = oldMap.get(opp.Id);
Boolean justWon = opp.StageName == 'Closed Won' && oldOpp.StageName != 'Closed Won';
if (justWon && (opp.Amount == null || opp.Amount <= 0)) {
opp.Amount.addError('An Opportunity cannot be marked Closed Won without a positive Amount.');
}
}
}
addError(), called on the specific field, blocks the entire save and shows the message directly next to that field — a much better user experience than a generic failure, and it prevents exactly the "Closed Won with a blank Amount silently rolls up as 0" scenario this lesson exists to close.
Why this belongs in before, not after
addError() only works meaningfully in a before trigger — calling it in an after trigger doesn't prevent the save, since the record is already saved by the time after runs (Module 24's before/after distinction, once again). This validation needs its own beforeUpdate method on the handler, separate from the rollup logic living in afterUpdate.
Updating the trigger to route both events
trigger OpportunityTrigger on Opportunity (before update, after update) {
OpportunityTriggerHandler handler = new OpportunityTriggerHandler();
if (Trigger.isBefore) {
handler.beforeUpdate(Trigger.new, Trigger.oldMap);
}
if (Trigger.isAfter) {
handler.afterUpdate(Trigger.new, Trigger.oldMap);
}
}
This is Module 24's "Trigger Framework Fundamentals" routing pattern, now genuinely needed — one trigger, two events, each routed to its own clearly-named handler method.
Exercise
Add a validation that blocks any Opportunity update where StageName is being set to 'Closed Won' but CloseDate is null, using addError() on CloseDate.
Show hint
opp.CloseDate.addError(...)
Add Validation in Apex Quiz
My Notes
Log in to keep private notes on this lesson.
Questions about this lesson
No questions yet — be the first to ask.
Log in to ask a question about this lesson.
Summary
A Closed Won Opportunity with no Amount would roll up as 0, silently hiding real revenue — this lesson blocks that scenario at the source with a before-trigger validation.