2014-10-01 3 views
8

Я получаю ниже выход журнала. Я думаю, что мастер удаления пытается ошибиться, но реализация Джерси JAX-RS, которую он использует, не знает, как отформатировать ошибку? Как я могу просмотреть его?Сообщения об ошибках Dropwizard от Jersey

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

Вам нужен serialiszer для ErrorMessage. Если вы используете eclipse Strg + Shift + T и выполните поиск «JsonProcessingExceptionMapper». Этот диспетчер Exception хочет построить ответ с сущностью 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); 
     } 
    } 
} 

Это удаляет все Exeption картографами по умолчанию добавляется в DW. Теперь вы можете добавить всех желающих, которые вы действительно хотите. В моем случае:

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); 
    } 

} 

Добавить в пробежках():

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

Надеется, что это помогает :-)

+1

вариант 2 работал для меня кроме того, что в isWriteable() Мне пришлось изменить его на 'return type == ErrorMessage.class;' –

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

+0

Я получал точно такую ​​же ошибку, и это исправлено. Что вы сделали, чтобы исправить свою проблему? Написание персонализированного сборщика исключений или автора сообщения об ошибке не представляется правильным. – SameeraGupta

1

Я ударил это пару раз недавно и поэтому отправлю ed (теперь принятый) запрос pull для регистрации основной ошибки при предупреждении, а не для отладки.

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

+0

Похоже, что он вернулся: https://github.com/dropwizard/dropwizard/commit/9f2df976b2b1fda7dfb19fbdfd0c670914791f8a Было ли это потому, что есть предпочтительная альтернатива? – Lorrin

+0

Не знаю. Полезно никаких объяснений по поводу фиксации. – rich

2

Dropwizard будет регистрировать основную ошибку на уровне DEBUG, так что вы можете включить, что в вашем журналирования конфигурации, чтобы увидеть причину здесь:

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

Это лучший, самый простой и прочный ответ. В файле config.yml (или любом другом имени) в разделе «logging:» добавьте строку выше. Ни одно другое решение, которое на данный момент работает на этой странице, не работает должным образом. – Adrien

Смежные вопросы