Java Exception Handling – Alternatives to Nested Try-Catches

exception handlingjava

I have a situation where I am trying to retrieve an object. If the lookup fails I have several fallbacks in place, each of which may fail. So the code looks like:

try {
    return repository.getElement(x);
} catch (NotFoundException e) {
    try {
        return repository.getSimilarElement(x);
    } catch (NotFoundException e1) {
        try {
            return repository.getParentElement(x);
        } catch (NotFoundException e2) {
            //can't recover
            throw new IllegalArgumentException(e);
        }
    }
}

This looks awfully ugly. I hate to return null, but is that better in this situation?

Element e = return repository.getElement(x);
if (e == null) {
    e = repository.getSimilarElement(x);
}
if (e == null) {
    e = repository.getParentElement(x);
}
if (e == null) {
    throw new IllegalArgumentException();
}
return e;

Are there other alternatives?

Is using nested try-catch blocks an anti-pattern? is related, but the answers there are along the lines of "sometimes, but it's usually avoidable", without saying when or how to avoid it.

Best Answer

The usual way to eliminate nesting is to use functions:

Element getElement(x) {
    try {
        return repository.getElement(x);
    } catch (NotFoundException e) {
        return fallbackToSimilar(x);
    }  
}

Element fallbackToSimilar(x) {
    try {
        return repository.getSimilarElement(x);
     } catch (NotFoundException e1) {
        return fallbackToParent(x);
     }
}

Element fallbackToParent(x) {
    try {
        return repository.getParentElement(x);
    } catch (NotFoundException e2) {
        throw new IllegalArgumentException(e);
    }
}

If these fallback rules are universal, you could consider implementing this directly in the repository object, where you might be able to just use plain if statements instead of an exception.