2014-10-01 22 views
8

Aşağıdaki log çıktılarını alıyorum. Sanırım açılan sihirbaz hata yapmaya çalışıyor ama kullandığı Jersey JAX-RS uygulaması hatanın nasıl biçimlendirileceğini bilmiyor mu? Nasıl görüntüleyebilirim?Dropwizard hata mesajları, 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 vuruyorum yöntem imzadır:

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

cevap

9

Sen errorMessage için serialiszer gerekir. Eclipse Strg + Shift + T kullanıyorsanız ve "JsonProcessingExceptionMapper" için arama yapın. Bu Özel Durum eşleyicisi, varlık ErrorMessage ile yanıt oluşturmak istiyor, ancak bunun için bir eşleştiriciniz yok.

  1. bu istisna mapper çıkarın ve hiçbir varlık
  2. Bir ileti gövdesi yazar oluşturmak ile özel istisna eşleştiricisini ekleyin:

    İki seçeneğiniz vardır.

1. Seçenek: Koşunuzdan() bu yöntemi ekleyin:

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

Bu DW varsayılan olarak eklenen tüm exeption haritacılarla kaldırır. Artık gerçekten istediğiniz tüm exeption haritalayıcılarını ekleyebilirsiniz. Benim durumumda:

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

Şimdi varlık olmadan kendi özel CustomJsonProcessingExceptionMapper yazma:

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

} 

Seçenek 2: Sen ErrorMessage için bir seri hale/mesaj gövdesi yazar oluşturun. bu yüzden bu deneyin için:

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

Umut bu

+1

seçeneği isWriteable() yöntemi 'return type == ErrorMessage.class; ' –

2

Bu aptal, ama sadece errorMessage bir aralık bırakalım ve çalıştırın böylece dropwizard bir ana sınıfından çalışır tıklandığında içinde (örneğin) Eclipse.

arada bu durumda altta yatan hata oldu:

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

Sadece o dropwizard anlar böylece kaynak için bu başlıkları belirtmek gerekir :-) yardımcı olur:

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

} 

Koşunuzdan() ekleyin Yanıt için kullanılacak hangi hata iletisi oluşturucu:

+1

' i değiştirmek zorunda kaldım. – rich

+0

Tam olarak aynı hatayı alıyorum ve bu düzeltildi. Sorununuzu çözmek için ne yaptınız? Özel istisna mapper veya hata mesajı vücut yazarı yazma doğru görünmüyor. – SameeraGupta

1

Bunu birkaç kez vurdum ve bu yüzden a (şimdi kabul edildi), hata ayıklamak yerine temeldeki hatayı uyarmak için istekte bulundu.

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

Burada nedenini görmek için günlük config o açabilirsiniz böylece
+0

Geri döndüğü anlaşılıyor: https://github.com/dropwizard/dropwizard/commit/9f2df976b2b1fda7dfb19fbdfd0c670914791f8a Tercih edilen bir alternatif olduğundan bu muydu? – Lorrin

+0

Hiçbir fikir. Taahhüt hakkında herhangi bir açıklama yok. – rich

2

Dropwizard, DEBUG düzeyinde yatan hatayı kaydeder: 2'de dışında benim için çalıştı

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

Bu en iyi, en basit ve en dayanıklı cevaptır. Config.yml dosyanızda (veya adı ne olursa olsun) "logging:" altında, yukarıdaki satırı ekleyin. Şu anda bu sayfada başka bir çözüm düzgün çalışmıyordu. – Adrien

İlgili konular