/** * Introspects the {@code Throwable} to obtain the cause. * * The method searches for methods with specific names that return a {@code Throwable} object. * This will pick up most wrapping exceptions, including those from JDK 1.4. * * The default list searched for are:</p> <ul> <li>{@code getCause()}</li> * <li>{@code getNextException()}</li> <li>{@code getTargetException()}</li> * <li>{@code getException()}</li> <li>{@code getSourceException()}</li> * <li>{@code getRootCause()}</li> <li>{@code getCausedByException()}</li> * <li>{@code getNested()}</li> </ul> * * <p>In the absence of any such method, the object is inspected for a {@code detail} * field assignable to a {@code Throwable}.</p> * * If none of the above is found, returns {@code null}. * * @param throwable The throwable to introspect for a cause, may be null. * @return The cause of the {@code Throwable}, * {@code null} if none found or null throwable input. */ public static Throwable getCause(Throwable throwable) { return getCause(throwable, CAUSE_MTD_NAMES); }
/** * Returns the list of {@code Throwable} objects in the exception chain. * * A throwable without cause will return a list containing one element - the input throwable. * A throwable with one cause will return a list containing two elements - the input throwable * and the cause throwable. A {@code null} throwable will return a list of size zero. * * This method handles recursive cause structures that might otherwise cause infinite loops. * The cause chain is processed until the end is reached, or until the next item in the chain * is already in the result set.</p> * * @param throwable The throwable to inspect, may be null. * @return The list of throwables, never null. */ public static List<Throwable> getThrowableList(Throwable throwable) { List<Throwable> list = new ArrayList<>(); while (throwable != null && !list.contains(throwable)) { list.add(throwable); throwable = getCause(throwable); } return list; }
assertTrue(X.getCause(ex).getMessage().contains("Cannot serialize transaction due to write conflict"));
/** * Introspects the {@code Throwable} to obtain the cause. * * The method searches for methods with specific names that return a {@code Throwable} object. * This will pick up most wrapping exceptions, including those from JDK 1.4. * * The default list searched for are:</p> <ul> <li>{@code getCause()}</li> * <li>{@code getNextException()}</li> <li>{@code getTargetException()}</li> * <li>{@code getException()}</li> <li>{@code getSourceException()}</li> * <li>{@code getRootCause()}</li> <li>{@code getCausedByException()}</li> * <li>{@code getNested()}</li> </ul> * * <p>In the absence of any such method, the object is inspected for a {@code detail} * field assignable to a {@code Throwable}.</p> * * If none of the above is found, returns {@code null}. * * @param throwable The throwable to introspect for a cause, may be null. * @return The cause of the {@code Throwable}, * {@code null} if none found or null throwable input. */ public static Throwable getCause(Throwable throwable) { return getCause(throwable, CAUSE_MTD_NAMES); }
/** * Returns the list of {@code Throwable} objects in the exception chain. * * A throwable without cause will return a list containing one element - the input throwable. * A throwable with one cause will return a list containing two elements - the input throwable * and the cause throwable. A {@code null} throwable will return a list of size zero. * * This method handles recursive cause structures that might otherwise cause infinite loops. * The cause chain is processed until the end is reached, or until the next item in the chain * is already in the result set.</p> * * @param throwable The throwable to inspect, may be null. * @return The list of throwables, never null. */ public static List<Throwable> getThrowableList(Throwable throwable) { List<Throwable> list = new ArrayList<>(); while (throwable != null && !list.contains(throwable)) { list.add(throwable); throwable = getCause(throwable); } return list; }