2017-07-07 38 views
0

在我的代码具有延伸抛出:IllegalArgumentException异常:杰克逊的readEntity被序列化我的异常转换成java.lang.Throwable的而不是正确的错误异常

public class InvalidDataSourceException extends IllegalArgumentException { 
    public InvalidDataSourceException(String message, Throwable cause) { 
    super(message, cause); 
    } 
} 

在我州的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串,然后重新序列:

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

那么首先,是另一种Java应用程序感知存在类InvalidDataSourceException的? –

+0

嗨@JamesCube非常感谢您的回复。我添加了一个重现问题的单元测试。 –

+1

好吧,现在它更有意义。你有序列化器,把关于类的信息放到json上,非常好。但是,你不应该有一个对称的解串器吗? [从中延伸](https://fasterxml.github.io/jackson-databind/javadoc/2.3.0/com/fasterxml/jackson/databind/JsonDeserializer.html)。没有直接的映射,这些只是字段,杰克逊默认只忽略不知道的字段(据我记忆,现在可能是错误的)。 –

回答

1

看看Throwable javadoc。

当您扩展Throwable并将另一个传递给构造函数时,它将传递给private Throwable cause属性。然后这是关于类型的唯一信息。因此,在反序列化过程中,Java只知道cause属性的类型为Throwable,如果它是InvalidDataSourceException或其他任何信息,则不会有任何信息。

编辑:现在看来,缺少解串器问题

+0

我们有一个Throwable串行器。对不起,我忘了提到这一点。我用那个更新了票。 –

+0

由于球衣与球衣无关,我将球衣参考由“球衣”改为“杰克逊”。我还添加了单元测试。 –