2014-10-01 37 views
0

我正在運行的Java 8 Dropwizard啓用你的資源驗證0.7在Dropwizard

我無法得到驗證,在Dropwizard

在我的資源方面的工作,我有以下豆

@Data //lombok anntation 
@JsonRootName(value="CreateNewGame") 
@XmlRootElement 
public class CreateNewGameDTO { 
    @NotEmpty 
    public String name; 

    @NotNull 
    private GameType type; 
    @NotBlank 
    private String username; 

    @NotNull 
    @Min(1) 
    private Integer numOfPlayers; 
} 

而在我的資源類中,我有以下方法

@POST 
@Timed 
public Response createGame(@Valid CreateNewGameDTO dto) { ... } 

My JUnit test 

@ClassRule 
public static final DropwizardAppRule<CivBoardGameRandomizerConfiguration> RULE = 
     new DropwizardAppRule<CivBoardGameRandomizerConfiguration>(CivBoardgameRandomizerApplication.class, "src/main/resources/config.yml"); 

@Test 
public void createGameShouldFailBecauseOfMissingUsername() throws Exception { 
    List<NewCookie> cookies = performLogin(); 
    assertThat(cookies.size()).isEqualTo(2); 

    Client client = Client.create(); 

    CreateNewGameDTO dto = new CreateNewGameDTO(); 
    dto.setNumOfPlayers(4); 
    dto.setUsername(null); //Username NULL, so it should throw exception 
    dto.setName("PBF WaW"); 
    dto.setType(GameType.WAW); 

    ObjectMapper mapper = new ObjectMapper(); 
    String dtoAsJSon = mapper.writeValueAsString(dto); 

    URI uri = UriBuilder.fromPath(String.format(BASE_URL + "/game", RULE.getLocalPort())).build(); 
    ClientResponse response = client.resource(uri) 
      .type(MediaType.APPLICATION_JSON) 
      .cookie(cookies.get(0)) 
      .cookie(cookies.get(1)) 
      .entity(dtoAsJSon) 
      .post(ClientResponse.class); 

    assertThat(response.getStatus()).isEqualTo(HttpStatus.CREATED_201); 
    URI location = response.getLocation(); 
    assertTrue(location.getPath().matches(".*civilization/game/.*")); 
} 

當我創建單元測試撥打這個資源,我得到以下例外

ERROR [2014-10-01 11:03:39,515] com.sun.jersey.spi.container.ContainerResponse: A message body writer for Java class io.dropwizard.jersey.validation.ValidationErrorMessage, and Java type class io.dropwizard.jersey.validation.ValidationErrorMessage, and MIME media type application/xml 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 
application/xml -> 
    com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$App 
    com.sun.jersey.core.impl.provider.entity.DocumentProvider 
    com.sun.jersey.core.impl.provider.entity.SourceProvider$SourceWriter 
    com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$App 
    com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$App 

我還沒有做任何事情來「註冊」驗證。我以爲dropwizard是自動完成的。我還沒有在文檔中找到任何內容。 我正在使用Dropwizard的0.7版本

+1

當你sk ip lombok部分? – 2014-10-01 14:43:40

+0

@JanGalinski當然沒有。龍目島生成樣板代碼。它不應該影響這一點,也不會。仍然得到相同的錯誤 – 2014-10-01 16:03:34

+0

我正在使用Java 8,也許這就是原因。雖然,我無法想象爲什麼。我已經加入我的JUnit測試也 – 2014-10-01 16:05:00

回答

0

您可以嘗試向您的資源添加@Produces註釋,例如: @Produces(MediaType.APPLICATION_JSON),無論是在具體的方法或整個類上面,看看是否有效?我認爲我只是在同一件事上遇到了麻煩。如果是這種情況,這意味着Dropwizard無法確定MessageBodyWriter用於該tupe的響應(我認爲)

+0

我已經'@Produces({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON}) @Consumes({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON}) '在我的資源類 – 2014-10-01 19:56:36

+0

我刪除APPLICATION_XML生產者和消費者,它的工作。我認爲這可能是一個Dropwizard錯誤,因爲它應該檢測到我使用的是什麼類型,因爲我在客戶端發送JSON作爲類型 – 2014-10-01 20:21:59

0

問題是,存在引發的異常並且沒有exceptionMapper可以將其映射到有效輸出。你可以試試這個:

@Provider 
@Produces(MediaType.TEXT_PLAIN) 
public class ValidationErrorMessageBodyWriter implements MessageBodyWriter<ValidationErrorMessage> { 

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

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

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

    @Override 
    public void writeTo(
     ValidationErrorMessage t, 
     Class<?> type, 
     Type genericType, 
     Annotation[] annotations, 
     MediaType mediaType, 
     MultivaluedMap<String, Object> httpHeaders, 
     OutputStream entityStream) throws IOException, WebApplicationException 
    { 
     Joiner joiner = Joiner.on("; ").skipNulls(); 
     String message = joiner.join(t.getErrors().iterator()); 
     entityStream.write(message.getBytes(Charsets.UTF_8)); 
     LOG.info(message); 
    } 

} 

現在添加在你的應用程序運行(配置,環境)方法:

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

也許你想修改BodyWriter產生類似XML或某物其他輸出。其他!希望這能解決你的問題:-)


編輯:在你的資源的一個問題在評論

補充一點:

@GET 
@Path("getMBW") 
public Response getInTestResource(@Context MessageBodyWorkers workers) 
{ 
    Map<MediaType, List<MessageBodyWriter>> writers = workers.getWriters(MediaType.WILDCARD_TYPE); 

    for (Entry<MediaType, List<MessageBodyWriter>> entry : writers.entrySet()) { 
     for (MessageBodyWriter writer : entry.getValue()) { 
      System.out.println(String.format("For mediaType '%s' there is a class called %s", entry.getKey(),writer.getClass().getName())); 
     } 
    }  
    return Response.status(Status.OK).type(MediaType.TEXT_PLAIN).entity("get is ok").build(); 
} 

然後我得到這個:

For mediaType '*/*' there is a class called com.sun.jersey.core.impl.provider.entity.FormProvider 
For mediaType '*/*' there is a class called com.sun.jersey.core.impl.provider.entity.MimeMultipartProvider 
For mediaType '*/*' there is a class called com.sun.jersey.core.impl.provider.entity.StringProvider 
For mediaType '*/*' there is a class called com.sun.jersey.core.impl.provider.entity.ByteArrayProvider 
For mediaType '*/*' there is a class called com.sun.jersey.core.impl.provider.entity.FileProvider 
For mediaType '*/*' there is a class called com.sun.jersey.core.impl.provider.entity.InputStreamProvider 
For mediaType '*/*' there is a class called com.sun.jersey.core.impl.provider.entity.DataSourceProvider 
For mediaType '*/*' there is a class called com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General 
For mediaType '*/*' there is a class called com.sun.jersey.core.impl.provider.entity.ReaderProvider 
For mediaType '*/*' there is a class called com.sun.jersey.core.impl.provider.entity.DocumentProvider 
For mediaType '*/*' there is a class called com.sun.jersey.core.impl.provider.entity.StreamingOutputProvider 
For mediaType '*/*' there is a class called com.sun.jersey.core.impl.provider.entity.SourceProvider$SourceWriter 
For mediaType '*/*' there is a class called com.sun.jersey.server.impl.template.ViewableMessageBodyWriter 
For mediaType '*/*' there is a class called com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General 
For mediaType '*/*' there is a class called com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General 
For mediaType '*/*' there is a class called com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider 
+0

如果有人問:getSize()中的-1 - >「一個非負的返回值用於HTTP內容長度標頭。如果無法預先確定長度,它將返回長度(以字節爲單位)或-1「(來源:請參閱MessageBodyWriter說明) – user3280180 2014-10-16 13:43:49

+0

但是,如果我沒有驗證錯誤消息編寫器,在生產和消費中刪除APPLICATION_XML,它是如何工作的? – 2014-10-17 06:17:42

+0

如果刪除生產商,然後球衣可以使用另一個映射器爲請求的mediaTypes。每個客戶端發送Accepts頭,我想,另一個映射器用於輸出。也許你可以驗證你的客戶端接受頭研究請求 – user3280180 2014-10-17 07:15:24