Skip to content

Commit 0b102a0

Browse files
committed
INTERNAL: stacktrace all exceptions
1 parent 132254c commit 0b102a0

File tree

4 files changed

+105
-1
lines changed

4 files changed

+105
-1
lines changed

src/main/java/net/spy/memcached/ExceptionMessageFactory.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ private static boolean isBulkOperation(Operation op, Collection<Operation> ops)
7070
}
7171

7272
public static String createCompositeMessage(List<Exception> exceptions) {
73+
if (exceptions == null || exceptions.isEmpty()) {
74+
throw new IllegalArgumentException("At least one exception must be specified");
75+
}
76+
7377
StringBuilder rv = new StringBuilder();
7478
rv.append("Multiple exceptions (");
7579
rv.append(exceptions.size());

src/main/java/net/spy/memcached/internal/CompositeException.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package net.spy.memcached.internal;
22

3+
import java.io.PrintWriter;
4+
import java.io.StringWriter;
35
import java.util.ArrayList;
46
import java.util.List;
57
import java.util.concurrent.ExecutionException;
@@ -10,13 +12,49 @@ public class CompositeException extends ExecutionException {
1012

1113
private static final long serialVersionUID = -599478797582490012L;
1214
private final ArrayList<Exception> exceptions = new ArrayList<>();
15+
private final Throwable cause;
1316

14-
CompositeException(List<Exception> exceptions) {
17+
public CompositeException(List<Exception> exceptions) {
1518
super(ExceptionMessageFactory.createCompositeMessage(exceptions));
19+
if (exceptions.size() > 1) {
20+
StringWriter sw = new StringWriter();
21+
sw.write(System.lineSeparator());
22+
23+
for (Exception e : exceptions) {
24+
e.printStackTrace(new PrintWriter(sw));
25+
}
26+
27+
this.cause = new ExceptionOverview(sw.toString());
28+
} else {
29+
this.cause = exceptions.get(0);
30+
}
1631
this.exceptions.addAll(exceptions);
1732
}
1833

1934
public List<Exception> getExceptions() {
2035
return exceptions;
2136
}
37+
38+
public int size() {
39+
return exceptions.size();
40+
}
41+
42+
@Override
43+
public synchronized Throwable getCause() {
44+
return cause;
45+
}
46+
47+
static final class ExceptionOverview extends RuntimeException {
48+
49+
private static final long serialVersionUID = -641960514509105302L;
50+
51+
ExceptionOverview(String message) {
52+
super(message);
53+
}
54+
55+
@Override
56+
public synchronized Throwable fillInStackTrace() {
57+
return this;
58+
}
59+
}
2260
}

src/test/java/net/spy/memcached/compat/log/LoggingTest.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
// XXX: This really needs to get log4j configured first.
66

7+
import java.util.ArrayList;
8+
import java.util.List;
9+
10+
import net.spy.memcached.internal.CompositeException;
11+
import net.spy.memcached.ops.OperationErrorType;
12+
import net.spy.memcached.ops.OperationException;
13+
714
import org.junit.jupiter.api.BeforeEach;
815
import org.junit.jupiter.api.Test;
916

@@ -154,4 +161,12 @@ void testNoExceptionArg() throws Exception {
154161
assertNull(t);
155162
}
156163

164+
@Test
165+
void logCompositeException() {
166+
List<Exception> exceptions = new ArrayList<>();
167+
exceptions.add(new OperationException(OperationErrorType.SERVER, "msg1"));
168+
exceptions.add(new OperationException(OperationErrorType.CLIENT, "msg2"));
169+
170+
logger.error("failed to get", new CompositeException(exceptions));
171+
}
157172
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package net.spy.memcached.internal;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
import net.spy.memcached.ops.OperationErrorType;
7+
import net.spy.memcached.ops.OperationException;
8+
9+
import org.junit.jupiter.api.Test;
10+
11+
import static org.junit.jupiter.api.Assertions.assertTrue;
12+
13+
class CompositeExceptionTest {
14+
15+
16+
17+
@Test
18+
void printStackTraceOfAllExceptions() {
19+
List<Exception> exceptions = new ArrayList<>();
20+
exceptions.add(new OperationException(OperationErrorType.SERVER, "msg1"));
21+
exceptions.add(new OperationException(OperationErrorType.CLIENT, "msg2"));
22+
Exception e = throwError1();
23+
exceptions.add(e);
24+
CompositeException compositeException = new CompositeException(exceptions);
25+
String message = compositeException.getCause().getMessage();
26+
27+
compositeException.printStackTrace();
28+
assertTrue(message
29+
.contains("OperationException: SERVER: msg1"));
30+
assertTrue(message
31+
.contains("OperationException: CLIENT: msg2"));
32+
assertTrue(message
33+
.contains("OperationException: SERVER: msg3"));
34+
assertTrue(message
35+
.contains("at net.spy.memcached.internal.CompositeExceptionTest.throwError2"));
36+
assertTrue(message
37+
.contains("at net.spy.memcached.internal.CompositeExceptionTest.throwError1"));
38+
}
39+
40+
private Exception throwError1() {
41+
return throwError2();
42+
}
43+
44+
private Exception throwError2() {
45+
return new OperationException(OperationErrorType.SERVER, "msg3");
46+
}
47+
}

0 commit comments

Comments
 (0)