Intermediate
25 min read
Handle Errors
By the end of this lesson, you'll be able to:
- Reject checking out a book that's already checked out
- Reject returning a book via a checkout that's already closed
- Use a custom exception for a genuinely invalid library operation
Prerequisites: "Search the Library"
A custom exception for library errors
public class LibraryException extends Exception {}
public class LibraryException extends Exception {}— exactly Module 13's custom exception pattern — a one-line class that lets library-specific failures be caught and handled distinctly from generic Apex exceptions.
Guarding against checking out an already-borrowed book
public Checkout__c checkOutBook(Id bookId, String memberName) {
Book__c book = [SELECT Id, Is_Checked_Out__c FROM Book__c WHERE Id = :bookId];
if (book.Is_Checked_Out__c) {
throw new LibraryException('This book is already checked out.');
}
book.Is_Checked_Out__c = true;
update book;
Checkout__c checkout = new Checkout__c(Book__c = bookId, Member_Name__c = memberName, Checkout_Date__c = Date.today());
insert checkout;
return checkout;
}
public Checkout__c checkOutBook(Id bookId, String memberName) {— the method.Book__c book = [SELECT Id, Is_Checked_Out__c FROM Book__c WHERE Id = :bookId];— queries the book first.- (blank line)
if (book.Is_Checked_Out__c) {— checking this before doing anything else prevents exactly the "two members borrow the same physical book" scenario the previous lesson flagged as the reasonBook__candCheckout__cmust stay in sync.throw new LibraryException('This book is already checked out.');— rejects with a clear, named failure.}— closes theif.- (blank line)
book.Is_Checked_Out__c = true;— only reached if the guard passed.update book;— saves the change.- (blank line)
Checkout__c checkout = new Checkout__c(Book__c = bookId, Member_Name__c = memberName, Checkout_Date__c = Date.today());— builds the checkout record.insert checkout;— saves it.return checkout;— hands it back.}— closes the method.
Guarding against returning an already-closed checkout
public void returnBook(Id checkoutId) {
Checkout__c checkout = [SELECT Id, Book__c, Return_Date__c FROM Checkout__c WHERE Id = :checkoutId];
if (checkout.Return_Date__c != null) {
throw new LibraryException('This checkout has already been returned.');
}
checkout.Return_Date__c = Date.today();
update checkout;
Book__c book = [SELECT Id FROM Book__c WHERE Id = :checkout.Book__c];
book.Is_Checked_Out__c = false;
update book;
}
public void returnBook(Id checkoutId) {— the method.Checkout__c checkout = [SELECT Id, Book__c, Return_Date__c FROM Checkout__c WHERE Id = :checkoutId];— queries the checkout, includingReturn_Date__c.- (blank line)
if (checkout.Return_Date__c != null) {— aCheckout__cwith aReturn_Date__calready set means that borrowing event is closed.throw new LibraryException('This checkout has already been returned.');— a genuine misuse, worth a clearLibraryExceptionrather than silently double-processing the return.}— closes theif.- (blank line)
checkout.Return_Date__c = Date.today();— only reached if the guard passed.update checkout;— saves the change.- (blank line)
Book__c book = [SELECT Id FROM Book__c WHERE Id = :checkout.Book__c];— queries the related book.book.Is_Checked_Out__c = false;— marks it available again.update book;— saves the change.}— closes the method.
Exercise
Given a Book__c queried with Is_Checked_Out__c, write a guard that throws LibraryException("This book is already checked out.") if it's already checked out.
Show hint
if (book.Is_Checked_Out__c) { throw new LibraryException(...); }
Handle Errors 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
Real library operations can fail in predictable ways — this lesson guards checkOutBook and returnBook against the two most obvious misuses, using a custom exception from Module 13.