我使用Dropwizard 0.7运行Java 8
我无法通过Dropwizard中的资源进行验证
我有以下bean
@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;
}
在我的Resource类中,我有以下方法
@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
我还没有做任何事情来注册&#34;验证。我以为dropwizard会自动执行此操作。我还没有在文档中找到任何内容。 我使用0.7版本的Dropwizard
答案 0 :(得分:0)
您可以尝试在资源中添加@Produces注释,例如@Produces(MediaType.APPLICATION_JSON),在特定方法之上或整个类上,看看是否有效?我想我只是在相同的事情上发生了变化。如果是这种情况,则意味着Dropwizard无法确定MessageBodyWriter用于该tupe的响应(我认为)
答案 1 :(得分: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);
}
}
现在添加app app(config,enviroment)方法:
// Serializer
environment.jersey().register(new ValidationErrorMessageBodyWriter());
也许您想修改BodyWriter以生成其他输出,如xml或sth。其他!希望这能解决您的问题: - )
编辑 :评论中的问题
在您的一个资源中添加:
@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