2017-07-07 40 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

由於球衣與球衣無關,我將球衣參考由「球衣」改爲「傑克遜」。我還添加了單元測試。 –