2011-04-29 108 views
12

我正在使用Jersey爲外部世界提供Java REST服務。我提供了一些採用JSON的函數,我將Jackson框架與球衣結合使用,將它們轉換爲POJO。ExceptionMapper的澤西島/傑克遜異常問題

我有問題,如果錯誤的傑克遜格式發送到服務器,答案(http響應的內容)是傑克遜特定的異常說明。如果我有一個屬性「姓」一個POJO和JSON字符串發送「sursname」服務器,我得到:

Unrecognized field "sursname" (Class XY), not marked as ignorable at [Source: [email protected]; line: 1, column: 49] (through reference chain: XY["sursname"]) 

那是相當確定的,但我想有我自己的響應內容,例如我自己的錯誤代碼。我已經寫了一個自定義的ExceptionMapper,它應該映射所有的Throwables。

@Provider 
public class WebserviceExceptionMapper implements ExceptionMapper<Throwable> { 

@Override 
public Response toResponse(Exception e) { 
    e.printStackTrace(); 
    return Response.status(400).entity("{\"errorcode\":\"CRITICAL_ERROR\"}").type(MediaType.APPLICATION_JSON).build(); 
    } 
} 

似乎傑克遜異常是在我的webservice方法被調用之前拋出的,所以我沒有機會映射它?

有沒有人有想法?非常感謝,對不起我的英語;)

回答

1

當然傑克遜的例外被拋出:傑克遜的提供者被調用,以創建一個你期望在你的方法中的對象。但是,使用ExceptionMapper,您不僅可以映射您的異常,還可以映射提供者異常。

您確定您的提供者已註冊?如果拋出你的方法而不是來自提供者的異常,它會被調用嗎?

如果上一個問題的答案是「是」,請嘗試爲具體異常實現ExceptionMapper而不是Throwable。

-1

感謝您的幫助,JsonParseException的ExceptionMapper沒有幫助。我從我的項目中刪除了傑克遜jar文件,幷包含傑克遜源文件。然後我修改了ord.codehaus.jackson.jaxrs.JsonParseExceptionMapper和JacksonMappingExceptionMapper來返回我的自定義響應內容。我對此不滿意,但它現在起作用了!

感謝您的幫助!

2

我在使用Jackson和Apache CXF時遇到了類似的問題。如果異常沒有發生在我的JAX-RS方法中,而是發生在JacksonJsonProvider中,則異常映射器不會被調用。在我的情況下,解決方案是延長JacksonJsonProvider,抓住特定的傑克遜json例外,並將其重新推回爲WebApplicationException

下面是我的擴展JacksonJsonProvider我被覆蓋的readFrom方法:

@Override 
    public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType, 
      MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException { 
     try { 
      return super.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream); 
     } catch (JsonParseException jpe) { 
      throw new WebApplicationException(jpe, Response.status(Status.BAD_REQUEST) 
        .entity(new ErrorEntity("Malformed json passed to server: \n" + jpe.getMessage())).build()); 
     } catch (JsonMappingException jme) { 
      throw new WebApplicationException(jme, Response 
        .status(Status.BAD_REQUEST) 
        .entity(new ErrorEntity("Malformed json passed to server, incorrect data type used: \n" 
          + jme.getMessage())).build()); 
     } 
    } 
13

的原因,您的自定義ExceptionMapper沒有捕捉到的異常是因爲傑克遜庫提供了自己的異常映射器,這之前它捕捉異常會被你的基因異常映射器捕獲。

一些建議您應該爲JsonParseExceptionMapper和JacksonMappingExceptionMapper實現自己的異常映射器,但是,這會導致不一致的結果。 See this issue on their GitHub

要解決此問題,您必須確保沒有任何內置的異常映射程序已註冊。如果您使用的傑克遜JAXRS-提供商庫JSON:傑克遜JAXRS JSON的提供商,確保你只或者註冊JacksonJaxbJsonProvider.classJacksonJsonProvider.class您應用類:

public class MyApplication extends ResourceConfig { 
    public MyApplication() { 
     register(JacksonJaxbJsonProvider.class) 
    } 
} 

注意的JacksonFeature.class的,因爲它註冊內置的ExceptionMappers。還要遠離圖書館,它會自動添加一些內置的異常映射器,而無需執行任何操作。

+3

我剛剛花了相當長的一段時間這個問題,看了很多關於它的線程,多提exceptionmappers。最後偶然發現了你的答案,這是我發現的唯一一個能夠正確解釋問題的人,爲什麼exceptionmappers不會工作並且有一個簡單的解決方案。謝謝!應該被市場接受爲答案。 – patman 2015-06-15 14:31:38

+1

有史以來最佳答案!只註冊JacksonJsonProvider.class適用於我,但不適用於JacksonJaxbJsonProvider.class。這真的應該是被接受的答案。 – wolf97084 2016-04-07 20:08:57

0

我有同樣的問題,並解決覆蓋ExceptionMapper。完善!我需要做的還有一件額外的事情,那就是如何爲我的應用程序重寫JacksonProvider(我不知道它是否與我使用的Jersey版本有關 - - 2.19)。下面是重寫它我的web.xml部分:

<init-param> 
<param-name>jersey.config.server.provider.classnames</param-name> 
    <param-value> 
     com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider 
    </param-value>