Java - find the first cause of an exception

Viewed 49312

I need to check if an exception is caused by some database problem. I receive an Exception and check if its cause contains the "ORA" string and return that (something like "ORA-00001"). The problem here is that the exception I receive is nested inside other exceptions, so if I don't find out if it's an oracle exception, I have to check into the cause of that exception and so on. Is there a cleaner way to do this? Is there a way to know the first cause (the deep-nested exception) of a given exception?

My current code looks like this:

private String getErrorOracle(Throwable e){
        final String ORACLE = "ORA";
        if (e.getCause() != null && e.getCause().toString().contains(ORACLE)){
            return e.getCause().toString();
        } else if(e.getCause() != null){
            return getErrorOracle(e.getCause());
        } else {
            return null;
        }
    }
13 Answers

In my Spring Boot project for getRootCause IDEA suggest 3 static import:

Spring Core: org.springframework.core.NestedExceptionUtils.getRootCause
Jackson: com.fasterxml.jackson.databind.util.ClassUtil.getRootCause
Guava (Swagger transitive) com.google.common.base.Throwables.getRootCause

Most smart (with cycle check) is Spring NestedExceptionUtils.getRootCause. But, if your excetion has no cause, method returns null. In my case it is wrong, so I've done:

@NonNull
public static Throwable getRootCause(@NonNull Throwable t) {
    Throwable rootCause = NestedExceptionUtils.getRootCause(t);
    return rootCause != null ? rootCause : t;
}

One line solution using core Java API:

    try {
        i = 1 / 0; 
    } catch (ArithmeticException e) {
        System.out.println(new ArithmeticException().initCause(e).getCause());
    }

One more solution below works as well:

    try {
        i = 1 / 0; 
    } catch (ArithmeticException e) {
        System.out.println(new Exception().initCause(e).getCause());
    }

Both of them will print

java.lang.ArithmeticException: / by zero

I want to add Kotlin extension functions to get root causes:

fun Throwable.rootCause(): Throwable {
  return if (cause == null) this else cause!!.rootCause()
}

//Return null if first cause is null
fun Throwable.optRootCause(): Throwable? {
  return if (cause == null) null else cause!!.rootCause()
}

Or this one if need to find a cause inside the throwable chain at any points:

fun <T : Throwable> Throwable.isOrContainsCauseOfType(clazz: KClass<T>): Throwable?  {
  return when {
    clazz.isInstance(this) -> this //remove if you want to exclude [this]
    cause == null -> null
    clazz.isInstance(cause) -> cause
    else -> cause!!.isOrContainsCauseOfType(clazz)
  }
}

ExceptionUtils.getRootCause(), and Throwables.getRootCause() returns null if the cause of the exception being passed is null.The following method will return the original throwable if an throwable without a cause is being passed as the input parameter.

/**
 * @return the root cause of a given throwable.
 *   If throwable without a cause is being passed, the original throwable will be returned
 */
public static Throwable getRootCause(@NonNull final Throwable throwable) {
    List<Throwable> throwableList = ExceptionUtils.getThrowableList(throwable);
    return throwableList.get(throwableList.size() - 1);
}
Related