Skip to content

Commit

Permalink
1.x: Use the correct Throwable to set the cause for CompositeException
Browse files Browse the repository at this point in the history
The cause of #3679 is we use a wrong Throwable (its cause has been set) to set the cause and `initCause` will throw an exception. Hence, the cause chain is not created correctly. In this PR, it searches the root cause (which doesn't have a cause) and use it to call `initCause`.
  • Loading branch information
zsxwing committed Jun 1, 2016
1 parent fef520e commit 8d8fdc3
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 4 deletions.
29 changes: 25 additions & 4 deletions src/main/java/rx/exceptions/CompositeException.java
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,12 @@ public synchronized Throwable getCause() {
// we now have 'e' as the last in the chain
try {
chain.initCause(e);
chain = chain.getCause();
} catch (Throwable t) {
// ignore
// the javadocs say that some Throwables (depending on how they're made) will never
// let me call initCause without blowing up even if it returns null
chain = e;
}
chain = getRootCause(chain);
}
cause = _cause;
}
Expand Down Expand Up @@ -280,17 +279,39 @@ public String getMessage() {
private List<Throwable> getListOfCauses(Throwable ex) {
List<Throwable> list = new ArrayList<Throwable>();
Throwable root = ex.getCause();
if (root == null) {
if (root == null || root == ex) {
return list;
} else {
while(true) {
list.add(root);
if (root.getCause() == null) {
Throwable cause = root.getCause();
if (cause == null || cause == root) {
return list;
} else {
root = root.getCause();
}
}
}
}

/**
* Returns the root cause of {@code e}. If {@code e.getCause()} returns {@null} or {@code e}, just return {@code e} itself.
*
* @param e the {@link Throwable} {@code e}.
* @return The root cause of {@code e}. If {@code e.getCause()} returns {@null} or {@code e}, just return {@code e} itself.
*/
private Throwable getRootCause(Throwable e) {
Throwable root = e.getCause();
if (root == null || root == e) {
return e;
} else {
while(true) {
Throwable cause = root.getCause();
if (cause == null || cause == root) {
return root;
}
root = root.getCause();
}
}
}
}
37 changes: 37 additions & 0 deletions src/test/java/rx/exceptions/CompositeExceptionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

import org.junit.Test;

import rx.exceptions.CompositeException.CompositeExceptionCausalChain;

public class CompositeExceptionTest {

private final Throwable ex1 = new Throwable("Ex1");
Expand Down Expand Up @@ -239,4 +241,39 @@ public void messageVarargs() {
CompositeException compositeException = new CompositeException(ex1, ex2, ex3);
assertEquals("3 exceptions occurred. ", compositeException.getMessage());
}

@Test
public void complexCauses() {
Throwable e1 = new Throwable("1");
Throwable e2 = new Throwable("2");
e1.initCause(e2);

Throwable e3 = new Throwable("3");
Throwable e4 = new Throwable("4");
e3.initCause(e4);

Throwable e5 = new Throwable("5");
Throwable e6 = new Throwable("6");
e5.initCause(e6);

CompositeException compositeException = new CompositeException(e1, e3, e5);
assert(compositeException.getCause() instanceof CompositeExceptionCausalChain);

List<Throwable> causeChain = new ArrayList<Throwable>();
Throwable cause = compositeException.getCause().getCause();
while (cause != null) {
causeChain.add(cause);
cause = cause.getCause();
}
// The original relations
//
// e1 -> e2
// e3 -> e4
// e5 -> e6
//
// will be set to
//
// e1 -> e2 -> e3 -> e4 -> e5 -> e6
assertEquals(Arrays.asList(e1, e2, e3, e4, e5, e6), causeChain);
}
}

0 comments on commit 8d8fdc3

Please sign in to comment.