4

I have an custom exception , just an example to see how I can write my own exception class and what could be the purpose of the exception.

public class AccountException extends Exception {

    public AccountException( Exception e, string sourceClass){

        system.debug('Exeption Name ******' + e);
    }



}

Below is the code where I use the exception:

public class accontecreation {

    public void createtheAcc(){

    try{

        Account a = new Account();
        insert a;

    }
    Catch(Exception e){
        throw new AccountException(e,'lkansldknas');

    }

   }



}

When I call the above class method using Execute Anonymous, I get an System.DMLException right away instead of showing up in the debug log. What am I doing wrong here? How can I catch various kind of exception and handle it using my own custom exception class? Is there any correction I can make to get this to go to catch block and show up the error in system.debug?

  • 1
    You are catching AccountException SF has no clue what that is and will never throw it. If you make a custom exception that doesn't mean the platform will throw it, that means you have to throw it. – Jesse Milburn Dec 28 '16 at 23:34
6

Catch allows you to catch a specific type of exception, such as a DmlException, a QueryException, or a SuperUncoolException. When you create a new Exception type, you're defining a new type of exception behavior that isn't already in the system. It doesn't replace existing exception types, as those are already "baked in" and can't be modified.

I actually wrote a class based on this concept that allowed me to build a Warning utility class. The basic framework looked like this:

public class Warnings {
    public class CpuTimeoutException extends Exception {}
    public static void checkCpuTime(Integer timeLimit) {
        if(Limits.getLimitCpuTime()-Limits.getCpuTime()<timeLimit) {
            throw new CpuTimeoutException();
        }
    }
}

There were numerous other methods, such as DML rows and so on. The purpose was to break out of deeply nested logic in time to avoid governor limits (which also spurred an idea I later posted).

So, I had a recursive function that did something, and I would periodically check to see if I ran out of time, and if so, break out all the way to the top:

 try {
     doRecursiveLogic(startingPoint);
 } catch(Warnings.CpuTimeoutException e) {
     // We ran out of time, report an error
     reportCpuTimeout();
 }

The doRecursiveLogic method would just check periodically to see if we ran out of time:

public static void doRecursiveLogic(Object someData) {
    Warnings.checkCpuTime(1000); // break if less than 1 second left
    // do more logic here
}

This was needed because I needed an easy way to break out of heavy XML processing if we were running out of CPU time. There's other uses for custom exceptions, but the entire point is this: they're used to signal your own custom logic exceptions. You can't use them to handle other types of exceptions in new ways.

  • This really good example to understand. Thanks for the effort – SfdcBat Dec 29 '16 at 0:11
  • What can you do inside the - public class CpuTimeoutException extends Exception {} class? can it used to do any operations? – SfdcBat Dec 29 '16 at 0:19
  • 1
    @SfdcBat Yes, you can. Usually, I do nothing, because I'm more concerned about the type of error than its contents, but you can add additional methods and variables if you need to. You get a default Constructor(String method) overload for free, but you could pass additional information there, too. For example, I might include a getRemainingTime() method that includes how much actual CPU time is left. Exceptions are basically normal classes, but have a few extra default methods you could override. – sfdcfox Dec 29 '16 at 1:00
3

You shouldn't re-throw the parent Exception in the constructor. It doesn't really make sense.

Regardless of how you set up your constructor, just because you define a custom exception type doesn't change the type of exception that is thrown by the platform. In your example, you need to catch (DmlException d), since that is the type being thrown. If you want, you could throw your custom exception from your catch block.

try
{
    insert new Account();
}
catch (DmlException d) // the exception type thrown by the platform is not going to change
{
    throw new MyShinyCustomException(d);
}

It's just like if you wanted to avoid a NullPointer, the following won't help you at all:

public class CollectionNotConstructedException extends Exception { }
try
{
    Set<Id> collection;
    Boolean value = collection.contains(UserInfo.getUserId());
}
catch (CollectionNotConstructedException e)
{
    // handle exception
}

Instead, you could, if you really wanted to, throw your custom exception.

public class CollectionNotConstructedException extends Exception { }
try
{
    Set<Id> collection;
    Boolean value = collection.contains(UserInfo.getUserId());
}
catch (NullPointerException e)
{
    throw new CollectionNotConstructedException(e);
}

However, I would advise against this sort of behavior. You should know what type of exception you expect your code to throw, and catch only that type. When you modify the type of exception that is thrown, you make it harder for other developers to know what to expect, and ultimately you make your system less maintainable.

  • Can you comment on my updated answer. I throw custom exception now but I get an error- Script-thrown exception – SfdcBat Dec 29 '16 at 0:06
  • That's what throw does...unless you catch the newly thrown exception as well. – Adrian Larson Dec 29 '16 at 0:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.