15

I don't want to catch generic exceptions, but I want to handle all the exceptions I want to catch exactly the same way.

For arguments sake, lets say the code is:

try {
   doSomething();
}
catch(AException ex) {
   handleException();
}
catch(BException ex) {
   handleException();
}
catch(CException ex) {
   handleException();
}
/* ... */
catch(ZException ex) {
   handleException();
}

Is there an elegant way to express this?

I thought about creating a variable

Set<Type> exceptionsToHandle = new Set<Type>{
   AException.class, 
   BException.class, 
   CException.class, 
   /* ... */
   ZException.class 
}
try {
   doSomething();
}
catch(Exception ex) {
  if (exceptionsToHandle.contains(getType(ex)) {
       handleException();
  }
  else {
      throw ex;
  }
}

Except there is a fundamental problem: We have no way to actually get the exception's Type outside of ugly trial and error code which will be as inelegant as the problem I'm trying to solve.

Alternatively, I could make a set of strings and then check the class name for the instance of the Exception, but I'd rather have a typesafe solution.

Any ideas?

5
  • getTypeName won't work for you?
    – Girbot
    Commented Apr 12, 2018 at 11:50
  • @Girbot, I'd rather a typesafe solution, so I want the Type, not a string of its name. Commented Apr 12, 2018 at 12:09
  • @BrianKessler Did you check my answer already. Should be a solution. Hope you find it more elegant than the standard code. Commented Apr 12, 2018 at 20:11
  • 1
    @BrianKessler you should also have a look at this similar Java question and how it uses polymorphism in the handle methods: stackoverflow.com/questions/13112976/… Commented Apr 13, 2018 at 14:56
  • 1
    @RobertSösemann, thanks for the response, but that wasn't really what I was looking for. Adrian Larson's answer below was exactly what I wanted. That said, your link has useful and interesting information... I'd scratched my head over similar issues in the past. Commented Apr 13, 2018 at 20:04

2 Answers 2

12

You can still support concrete types with getTypeName by using the Type.forName method.

Set<Type> allowlist = new Set<Type> { DmlException.class, ListException.class };
try
{
    // do stuff
}
catch (Exception pokemon)
{
    if (!allowlist.contains(Type.forName(pokemon.getTypeName()))
    {
        throw pokemon;
    }
    // actual error handling logic here
}
1
  • This is what I was looking for, cheers! Commented Apr 13, 2018 at 19:55
5

It's doable with an abstract base class as shown below.

public abstract class CustomException extends System.Exception {

}

Implementing exception classes

public class AException extends CustomException {

}


public class BException extends CustomException {

}

This test proves that it works

@IsTest
private class CustomException_Test {

    @IsTest
    private static void genericHandling() {

        Boolean aCatched = false;
        Boolean bCatched = false;
        Boolean othersIgnored = true;

        try {
            throw new AException();
        }
        catch(CustomException cex) {
            aCatched = true;
        }

        try {
            throw new BException();
        }
        catch(CustomException cex) {
            bCatched = true;
        }

        try {
            throw new NotACustomException();
        }
        catch(CustomException cex) {
            othersIgnored = false;
        }
        catch(Exception ex) {
            othersIgnored = true;
        }

        System.assert(aCatched);
        System.assert(bCatched);
        System.assert(othersIgnored);
    }
}
3
  • 1
    Very creative. I like it! Doesn't work if any of the exception types you want to catch are standard though.
    – Adrian Larson
    Commented Apr 12, 2018 at 23:04
  • True. But then he could use Polymorphism. Provide a version of handleException(Type ex) for each required type and one for generic Exceptions that basically does nothing. Commented Apr 13, 2018 at 14:54
  • 1
    Good answer. I thought to do something similar with interfaces, but SFDC wouldn't seem to let an Exception implement anything. Also, as @Adrian Larson observed, it can be a problem if I want to catch some standard exceptions, or similarly if I have Exceptions which are already extending some other base since Apex doesn't allow multiple inheritance. Commented Apr 13, 2018 at 19:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .