Reputation: 4716
I am trying to get Jackson to deserialize a JSON-encoded custom exception, and it fails if the exception disables the stacktrace.
Working example:
public static class CustomException extends Exception {
public CustomException(String msg) {
super(msg);
}
}
@Test
public void testSerializeAndDeserializeCustomException() throws Exception {
log.info("Test: testSerializeAndDeserializeCustomException");
CustomException ex1 = new CustomException("boom");
ObjectMapper om = new ObjectMapper();
String json = om.writerFor(CustomException.class).writeValueAsString(ex1);
assertNotNull(json);
log.info("JSON: {}", json);
CustomException ex2 = om.readerFor(CustomException.class).readValue(json);
assertNotNull(ex2);
assertEquals(ex2.getMessage(), ex1.getMessage());
}
Not working example:
public static class CustomNoStackException extends Exception {
public CustomNoStackException(String msg) {
super(msg, null, true, false);
}
}
@Test
public void testSerializeAndDeserializeCustomNoStackException() throws Exception {
log.info("Test: testSerializeAndDeserializeCustomNoStackException");
CustomNoStackException ex1 = new CustomNoStackException("boom");
ObjectMapper om = new ObjectMapper();
String json = om.writerFor(CustomNoStackException.class).writeValueAsString(ex1);
assertNotNull(json);
log.info("JSON: {}", json);
CustomNoStackException ex2 = om.readerFor(CustomNoStackException.class).readValue(json);
assertNotNull(ex2);
assertEquals(ex2.getMessage(), ex1.getMessage());
}
In the second case, readValue(json)
actually throws the CustomNoStackException
wrapped in an IOException
.
What am I doing wrong?
Upvotes: 1
Views: 1371
Reputation: 279990
When an Exception
is initialized without a cause
, it marks itself as the cause
.
private Throwable cause = this;
It uses that as a sentinel value to indicate that it has no cause. initCause
only lets you change the cause
if it's not itself.
Your CustomNoStackException
constructor is initializing the cause
with null
, breaking the sentinel value. When Jackson later tries to call initCause
method because of the
"cause":null
pair in the JSON, initCause
throws an exception saying you can't overwrite an exception's cause
(this is nested in the JsonMappingException
).
Upvotes: 2