2014-10-01 127 views
8

我收到下面的日誌輸出。我猜drop wizard正在嘗試錯誤,但它使用的Jersey JAX-RS實現不知道如何格式化錯誤?我如何查看它?來自Jersey的Dropwizard錯誤消息

ERROR [2014-10-01 08:08:55,875] com.sun.jersey.spi.container.ContainerResponse: A message body writer for Java class io.dropwizard.jersey.errors.ErrorMessage, and Java type class io.dropwizard.jersey.errors.ErrorMessage, and MIME media type text/plain was not found. 
The registered message body writers compatible with the MIME media type are: 
*/* -> 
    com.sun.jersey.core.impl.provider.entity.FormProvider 
    com.sun.jersey.core.impl.provider.entity.StringProvider 
    com.sun.jersey.core.impl.provider.entity.ByteArrayProvider 
    com.sun.jersey.core.impl.provider.entity.FileProvider 
    com.sun.jersey.core.impl.provider.entity.InputStreamProvider 
    com.sun.jersey.core.impl.provider.entity.DataSourceProvider 
    com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General 
    com.sun.jersey.core.impl.provider.entity.ReaderProvider 
    com.sun.jersey.core.impl.provider.entity.DocumentProvider 
    com.sun.jersey.core.impl.provider.entity.StreamingOutputProvider 
    com.sun.jersey.core.impl.provider.entity.SourceProvider$SourceWriter 
    com.sun.jersey.server.impl.template.ViewableMessageBodyWriter 
    com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General 
    com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General 
    com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider 
text/plain -> 
    com.sun.jersey.core.impl.provider.entity.StringProvider 
    com.sun.jersey.core.impl.provider.entity.ReaderProvider 

FWIW我打的方法簽名是:

@POST 
@UnitOfWork 
@Path("/update") 
@Consumes(MediaType.APPLICATION_JSON) 
@Produces(MediaType.TEXT_PLAIN) 
public String updateResults(ResultsUpdate results) {...} 

回答

9

您需要的ErrorMessage一個serialiszer。如果使用eclipse Strg + Shift + T並搜索「JsonProcessingExceptionMapper」。這個異常映射器想用實體ErrorMessage構建響應,但是你沒有映射器。

你有兩個選擇:

  1. 刪除此異常映射並沒有實體
  2. 您創建一個郵件正文作家添加自定義的異常映射 。

選項1: 運行中的()添加這個方法:

private void removeDefaultExceptionMappers(boolean deleteDefault,Environment environment) 
{ 
    if(deleteDefault){ 
     ResourceConfig jrConfig = environment.jersey().getResourceConfig(); 
     Set<Object> dwSingletons = jrConfig.getSingletons(); 
     List<Object> singletonsToRemove = new ArrayList<Object>(); 

     for (Object singletons : dwSingletons) { 
      if (singletons instanceof ExceptionMapper && !singletons.getClass().getName().contains("DropwizardResourceConfig")) { 
       singletonsToRemove.add(singletons); 
      } 
     } 

     for (Object singletons : singletonsToRemove) { 
      LOG.info("Deleting this ExceptionMapper: " + singletons.getClass().getName()); 
      jrConfig.getSingletons().remove(singletons); 
     } 
    } 
} 

這將刪除默認情況下,DW添加的所有exeption映射器。現在你可以添加你真正想要的所有exeption mappers。在我的情況:

environment.jersey().register(new ConstraintViolationExceptionMapper()); 
    environment.jersey().register(new CustomJsonProcessingExceptionMapper()); 
    environment.jersey().register(new EarlyEofExceptionMapper()); 

現在寫自己的自定義CustomJsonProcessingExceptionMapper無實體:

@Provider 
public class CustomJsonProcessingExceptionMapper implements ExceptionMapper<JsonProcessingException> { 

    private static final Logger LOG = LoggerFactory.getLogger(CustomJsonProcessingExceptionMapper.class); 

    @Override 
    public Response toResponse(JsonProcessingException exception) { 
     /* 
     * If the error is in the JSON generation, it's a server error. 
     */ 
     if (exception instanceof JsonGenerationException) { 
      LOG.warn("Error generating JSON", exception); 
      return Response.serverError().build(); 
     } 

     final String message = exception.getOriginalMessage(); 

     /* 
     * If we can't deserialize the JSON because someone forgot a no-arg constructor, it's a 
     * server error and we should inform the developer. 
     */ 
     if (message.startsWith("No suitable constructor found")) { 
      LOG.error("Unable to deserialize the specific type", exception); 
      return Response.serverError().build(); 
     } 

     /* 
     * Otherwise, it's those pesky users. 
     */ 
     LOG.debug("Unable to process JSON (those pesky users...)", exception); 
     return Response.status(Response.Status.BAD_REQUEST) 
         .build(); 
    } 

} 

選項2: 您創建一個串行器/郵件正文作家的ErrorMessage。這樣做試試這個:

@Provider 
@Produces(MediaType.TEXT_PLAIN) 
public class ErrorMessageBodyWriter implements MessageBodyWriter<ErrorMessage> { 

    private static final Logger LOG = LoggerFactory.getLogger(ErrorMessageBodyWriter.class); 

    @Override 
    public boolean isWriteable(
     Class<?> type, 
     Type genericType, 
     Annotation[] annotations, 
     MediaType mediaType) 
    { 
     return ValidationErrorMessage.class.isAssignableFrom(type); 
    } 

    @Override 
    public long getSize(
     ErrorMessage t, 
     Class<?> type, 
     Type genericType, 
     Annotation[] annotations, 
     MediaType mediaType) 
    { 
     return -1; 
    } 

    @Override 
    public void writeTo(
     ErrorMessage t, 
     Class<?> type, 
     Type genericType, 
     Annotation[] annotations, 
     MediaType mediaType, 
     MultivaluedMap<String, Object> httpHeaders, 
     OutputStream entityStream) throws IOException, WebApplicationException 
    {  
     String message = t.getMessage();   
     entityStream.write(message.getBytes(Charsets.UTF_8)); 
     LOG.info(message); 
    } 

} 

添加在你的run():

// Serializer 
environment.jersey().register(new ErrorMessageBodyWriter());  

希望這有助於:-)

+1

選項2,工作對我來說,除了isWriteable()方法我不得不將其更改爲'return type == ErrorMessage.class;' – 2014-12-01 13:23:17

2

這是愚蠢的,但我點擊的dropwizard從主類運行,因此你可以把一個斷點的ErrorMessage並運行它在(例如)Eclipse中。

順便在這種情況下,潛在的錯誤是:

Can not deserialize instance of java.util.ArrayList out of START_OBJECT token 
4

只是需要讓dropwizard瞭解你的資源來指定這些頭哪個錯誤消息生成器用於響應:

@Consumes(MediaType.APPLICATION_JSON) 
@Produces(MediaType.APPLICATION_JSON) 
+1

我已經指定了這兩個註釋。 – rich 2014-11-07 19:03:08

+0

我得到了完全相同的錯誤,並修復了它。你做了什麼來解決你的問題?編寫自定義異常映射程序或錯誤消息主體編寫器似乎不正確。 – SameeraGupta 2014-11-09 03:12:50

1

我最近碰到過這幾次,所以提交編輯(現在接受的)拉取請求,以在發出警告而不是調試時記錄底層錯誤。

https://github.com/dropwizard/dropwizard/commit/ebdfcb47a030730233cf0984aadae155ec138ff3

+0

看起來像它恢復:https://github.com/dropwizard/dropwizard/commit/9f2df976b2b1fda7dfb19fbdfd0c670914791f8a 這是因爲有一個首選的替代? – Lorrin 2015-09-03 14:58:42

+0

不知道。對提交有幫助沒有解釋。 – rich 2015-09-03 21:00:19

2

Dropwizard將記錄在DEBUG級別的基本錯誤,這樣你就可以反過來說,在你的日誌配置,看看這裏的原因:

io.dropwizard.jersey.jackson.JsonProcessingExceptionMapper: DEBUG 
+0

這是最好,最簡單和最持久的答案。在你的config.yml文件中(或者任何名字),在「logging:」下,添加上面的行。目前在此頁面上沒有其他解決方案正常工作。 – Adrien 2017-09-12 21:29:55