Skip to content

Commit a149832

Browse files
committed
1.x: Use the correct Throwable to set the cause for CompositeException
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`.
1 parent fef520e commit a149832

File tree

2 files changed

+59
-2
lines changed

2 files changed

+59
-2
lines changed

src/main/java/rx/exceptions/CompositeException.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,12 @@ public synchronized Throwable getCause() {
147147
// we now have 'e' as the last in the chain
148148
try {
149149
chain.initCause(e);
150-
chain = chain.getCause();
151150
} catch (Throwable t) {
152151
// ignore
153152
// the javadocs say that some Throwables (depending on how they're made) will never
154153
// let me call initCause without blowing up even if it returns null
155-
chain = e;
156154
}
155+
chain = getRootCause(chain);
157156
}
158157
cause = _cause;
159158
}
@@ -293,4 +292,25 @@ private List<Throwable> getListOfCauses(Throwable ex) {
293292
}
294293
}
295294
}
295+
296+
/**
297+
* Returns the root cause of {@code e}. If {@code e.getCause()} returns {@null}, just return {@code e} itself.
298+
*
299+
* @param e the {@link Throwable} {@code e}.
300+
* @return The root cause of {@code e}. If {@code e.getCause()} returns {@null}, just return {@code e} itself.
301+
*/
302+
private Throwable getRootCause(Throwable e) {
303+
Throwable root = e.getCause();
304+
if (root == null) {
305+
return e;
306+
} else {
307+
while(true) {
308+
if (root.getCause() == null) {
309+
return root;
310+
} else {
311+
root = root.getCause();
312+
}
313+
}
314+
}
315+
}
296316
}

src/test/java/rx/exceptions/CompositeExceptionTest.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828

2929
import org.junit.Test;
3030

31+
import rx.exceptions.CompositeException.CompositeExceptionCausalChain;
32+
3133
public class CompositeExceptionTest {
3234

3335
private final Throwable ex1 = new Throwable("Ex1");
@@ -239,4 +241,39 @@ public void messageVarargs() {
239241
CompositeException compositeException = new CompositeException(ex1, ex2, ex3);
240242
assertEquals("3 exceptions occurred. ", compositeException.getMessage());
241243
}
244+
245+
@Test
246+
public void complexCauses() {
247+
Throwable e1 = new Throwable("1");
248+
Throwable e2 = new Throwable("2");
249+
e1.initCause(e2);
250+
251+
Throwable e3 = new Throwable("3");
252+
Throwable e4 = new Throwable("4");
253+
e3.initCause(e4);
254+
255+
Throwable e5 = new Throwable("5");
256+
Throwable e6 = new Throwable("6");
257+
e5.initCause(e6);
258+
259+
CompositeException compositeException = new CompositeException(e1, e3, e5);
260+
assert(compositeException.getCause() instanceof CompositeExceptionCausalChain);
261+
262+
List<Throwable> causeChain = new ArrayList<Throwable>();
263+
Throwable cause = compositeException.getCause().getCause();
264+
while (cause != null) {
265+
causeChain.add(cause);
266+
cause = cause.getCause();
267+
}
268+
// The original relations
269+
//
270+
// e1 -> e2
271+
// e3 -> e4
272+
// e5 -> e6
273+
//
274+
// will be set to
275+
//
276+
// e1 -> e2 -> e3 -> e4 -> e5 -> e6
277+
assertEquals(Arrays.asList(e1, e2, e3, e4, e5, e6), causeChain);
278+
}
242279
}

0 commit comments

Comments
 (0)