How can I loop through Exception getCause() to find root cause with detail message
JavaExceptionPlsqlJava Problem Overview
I am trying to call saveOrUpdate()
in hibernate to save data. Since columns have unique index, so its throws ConstraintViolationException
when I look through via Eclipse debugger.
Since root cause could be different for different exception while inserting data to table.
I wanted to know, how can I loop / traverse through getCause()
to check what is the root cause of exception and its message.
Update:
Thanks everyone for your kind response, thing is I want output like in below image:
I need to access detailMessage field.
(I am really sorry If could not make my question more clear.)
Thanks.
Java Solutions
Solution 1 - Java
The Apache ExceptionUtils provide the following method:
Throwable getRootCause(Throwable throwable)
as well as
String getRootCauseMessage(Throwable th)
Solution 2 - Java
I normally use the implementation below instead of Apache's one.
Besides its complexity, Apache's implementation returns null when no cause is found, which force me to perform an additional check for null.
Normally when looking for an exception's root/cause I already have a non-null exception to start with, which is for all intended proposes is the cause of the failure at hand, if a deeper cause can't be found.
Throwable getCause(Throwable e) {
Throwable cause = null;
Throwable result = e;
while(null != (cause = result.getCause()) && (result != cause) ) {
result = cause;
}
return result;
}
Solution 3 - Java
Using java 8 Stream API, this can be achieved by:
Optional<Throwable> rootCause = Stream.iterate(exception, Throwable::getCause)
.filter(element -> element.getCause() == null)
.findFirst();
Note that this code is not immune to exception cause loops and therefore should be avoided in production.
Solution 4 - Java
Are you asking for something like this?
Throwable cause = originalException;
while(cause.getCause() != null && cause.getCause() != cause) {
cause = cause.getCause();
}
or am I missing something?
Solution 5 - Java
Guava's Throwables
provides the following methods:
Throwable getRootCause(Throwable throwable)
as well as
String getStackTraceAsString(Throwable throwable)
Solution 6 - Java
} catch (Exception ex) {
while (ex.getCause() != null)
ex = ex.getCause();
System.out.println("Root cause is " + ex.getMessage());
}
Were you expecting something more complicated?
Solution 7 - Java
In APACHE; the implementation is like below.
The highlight is list.contains(throwable) == false
public static Throwable getRootCause(final Throwable throwable) {
final List<Throwable> list = getThrowableList(throwable);
return list.size() < 2 ? null : (Throwable)list.get(list.size() - 1);
}
public static List<Throwable> getThrowableList(Throwable throwable) {
final List<Throwable> list = new ArrayList<Throwable>();
while (throwable != null && list.contains(throwable) == false) {
list.add(throwable);
throwable = ExceptionUtils.getCause(throwable);
}
return list;
}
Solution 8 - Java
Try this, you can put this function in a kind of Util class:
public static Throwable getRootException(Throwable exception){
Throwable rootException=exception;
while(rootException.getCause()!=null){
rootException = rootException.getCause();
}
return rootException;
}
Example of usage :
catch(MyException e){
System.out.println(getRootException(e).getLocalizedMessage());
}
Solution 9 - Java
Recursively:
public static Throwable getRootCause(Throwable e) {
if (e.getCause() == null) return e;
return getRootCause(e.getCause());
}