在我的代码中,我有一个扩展IllegalArgumentException的异常:
public class InvalidDataSourceException extends IllegalArgumentException {
public InvalidDataSourceException(String message, Throwable cause) {
super(message, cause);
}
}
在我的Jersey REST Web服务中,所有错误都包含在类RESTError
中
所有其他服务都可以抛出同样的异常:
public class RESTError extends Throwable {
public RESTError(Throwable cause) {
super(cause);
}
}
因此,当InvalidDataSourceException发生时,它会被抛出为RESTError
的原因:
throw new RESTError(invalidDataSourceException);
我们已经为Throwable对象注册了一个序列化器:
public class ThrowableSerializer extends JsonSerializer<Throwable> {
@Override
public void serialize(Throwable value, JsonGenerator jgen,
SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeStartObject();
jgen.writeStringField("class", value.getClass().getCanonicalName());
jgen.writeStringField("message", value.getMessage());
jgen.writeObjectField("stackTrace", value.getStackTrace());
jgen.writeStringField("stackTraceAsString", Throwables.getStackTraceAsString(value));
jgen.writeObjectField("cause", value.getCause());
jgen.writeEndObject();
}
}
下面是一个单元测试,我尝试将RESTError编写为string,然后重新序列化:
public class TestJsonSerializationOfExceptions {
private static final Logger log = LoggerFactory.getLogger(TestJsonSerializationOfExceptions.class);
@Test
public void testBasic() throws Exception {
ObjectMapper objectMapper = ObjectMapperFactory.create();
try {
throw new InvalidDataSourceException("test msg");
} catch (Throwable t) {
RESTError restError = new RESTError(Response.Status.INTERNAL_SERVER_ERROR, Errors.General, t);
String str = objectMapper.writeValueAsString(restError); // It is correct here!
log.info("Rest error when serialized: {}", str);
restError = objectMapper.readValue(str, RESTError.class);
Assert.assertEquals(restError.getCause().getClass(), InvalidDataSourceException.class);
}
}
}
执行此操作时,异常原因会序列化为java.lang.Throwable
,而不是我的自定义InvalidDataSourceException
。它降级了它。因此单元测试失败。这是为什么?
答案 0 :(得分:1)
查看Throwable javadoc。
当您扩展Throwable并将另一个传递给构造函数时,它将传递给private Throwable cause
属性。然后这是关于类型的唯一信息。因此,在反序列化期间,Java只知道存在类型为cause
的属性Throwable
,并且如果它是InvalidDataSourceException
或其他任何内容,则没有信息。
编辑:现在看起来缺少反序列化问题