Wednesday, 29 August 2012

Creating Custom Exceptions - Apex

Since you can’t throw built-in Apex exceptions but can only catch them, you can create custom exceptions to throw in your methods. That way, you can also specify detailed error messages and have more custom error handling in your catch blocks.
To create your custom exception class, extend the built-in Exception class and make sure your class name ends with the word Exception. Append extendsException after your class declaration as follows.
public classMyException extends Exception {}
Here are some ways you can create your exceptions objects, which you can then throw.
You can construct exceptions:
  • With no arguments:
    new MyException();
  • With a single String argument that specifies the error message:
    new MyException('This is bad');
  • With a single Exception argument that specifies the cause and that displays in any stack trace:
    new MyException(e);
  • With both a String error message and a chained exception cause that displays in any stack trace:
    new MyException('This is bad', e);
Now that you’ve seen how to create an exception class and how to construct your exception objects, let’s create and run an example that demonstrates the usefulness of custom exceptions.
  1. In the Developer Console, create a class named MerchandiseException and add the following to it:
    public class MerchandiseException extends Exception {}
    You’ll use this exception class in the second class that you’ll create. Note that the curly braces at the end enclose the body of your exception class, which we left empty because we get some free code—our class inherits all the constructors and common exception methods, such as getMessage, from the built-in Exception class.
  2. Next, create a second class named MerchandiseUtility.
    public class MerchandiseUtility {
        public static void mainProcessing() {
            try {
                insertMerchandise();
            } catch(MerchandiseException me) {
                System.debug('Message: ' + me.getMessage());    
                System.debug('Cause: ' + me.getCause());    
                System.debug('Line number: ' + me.getLineNumber());    
                System.debug('Stack trace: ' + me.getStackTraceString());    
            }
        }
        
        public static void insertMerchandise() {
            try {
                // Insert merchandise without required fields 
        
                Merchandise__c m = new Merchandise__c();
                insert m;
            } catch(DmlException e) {
                // Something happened that prevents the insertion 
        
                // of Employee custom objects, so throw a more 
        
                // specific exception. 
        
                throw new MerchandiseException(
                    'Merchandise item could not be inserted.', e);
            }
        }
    }
    This class contains the mainProcessing method, which calls insertMerchandise. The latter causes an exception by inserting a Merchandise without required fields. The catch block catches this exception and throws a new exception, the custom MerchandiseException you created earlier. Notice that we called a constructor for the exception that takes two arguments: the error message, and the original exception object. You might wonder why we are passing the original exception? Because it is useful information—when the MerchandiseException gets caught in the first method, mainProcessing, the original exception (referred to as an inner exception) is really the cause of this exception because it occurred before the MerchandiseException.
  3. Now let’s see all this in action to understand better. Execute the following:
    MerchandiseUtility.mainProcessing();
  4. Check the debug log output. You should see something similar to the following:
    18:12:34:928 USER_DEBUG [6]|DEBUG|Message: Merchandise item could not be inserted.
    18:12:34:929 USER_DEBUG [7]|DEBUG|Cause: System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Description, Price, Total Inventory]: [Description, Price, Total Inventory]
    18:12:34:929 USER_DEBUG [8]|DEBUG|Line number: 22
    18:12:34:930 USER_DEBUG [9]|DEBUG|Stack trace: Class.EmployeeUtilityClass.insertMerchandise: line 22, column 1
    A few items of interest:
    • The cause of MerchandiseException is the DmlException. You can see the DmlException message also that states that required fields were missing.
    • The stack trace is line 22, which is the second time an exception was thrown. It corresponds to the throw statement of MerchandiseException.
      throw new MerchandiseException('Merchandise item could not be inserted.', e);

No comments:

Post a Comment