使用JAX-RS对JAXB数据进行实际验证?

时间:2012-05-01 13:11:58

标签: java validation jaxb jax-rs

我们正在使用JAX-RS和一些相当基本的POJO实体,并且@GET@POST @Produce@ConsumeMediaType.APPLICATION_JSON个带注释的方法,MediaType.APPLICATION_XML。没什么了不起的。

我的问题是我应该如何最好地验证进来的数据?

我们没有XML Schema,尽管我可以生成一个。我需要以某种方式挂钩,这看起来并不那么吸引人,我还没有找到一个简洁的例子。

我们可以使用“bean验证”,但我再次不确定如何将其挂钩并调用它。

最后(我认为)我们可以为实体POJO添加一些isValidForXXX()方法,并在我们有一个交给我们的实例时调用它们。

建议任何人?

3 个答案:

答案 0 :(得分:2)

如果您有XML架构,那么您可以在MessageBodyReader内使用JAXB验证。有关具体示例,请参阅我对类似问题的回答。

<强> ValidatingReader

以下是MessageBodyReader的简单实现,它执行以下四项操作:1)Create a JAXBContext,2)创建Schema的实例,3)在{{1}上设置架构4)解组Unmarshaller

InputStream

答案 1 :(得分:1)

希望完成与原始海报相同的事情。由于似乎希望避免MessageBodyReader我认为我会分享此解决方案,它只使用HttpServletRequest作为参数,然后使用getInputStream方法直接使用数据。

@POST
@Path("/myPath")
@Consumes(MediaType.APPLICATION_XML)
public Response saveCustomerInteraction(@Context HttpServletRequest httpRequest) {

    Response response = null;
    try {
        CustomerInteraction ci = this.handleCustomerInteractionRequest(httpRequest);
        if (ci!=null){
            // save your data or whatever your app does
        }
        else {
            response = Response.status(Status.BAD_REQUEST).entity("invalid XML").build();               
        }
    }
    catch(Exception e){
        log.error(e.getMessage(),e);
        response = Response.serverError().entity(e.getMessage()).build();
    }
    return response;
}

然后handleCustomerInteractionRequest方法将处理servlet流并验证XML

protected CustomerInteraction handleCustomerInteractionRequest(HttpServletRequest request){

    CustomerInteraction ci = null;
    try {
        SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema = sf.newSchema(schemaUrl);
        JAXBContext jaxbContext = JAXBContext.newInstance(CustomerInteraction.class);
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        unmarshaller.setSchema(schema);
        ci = (CustomerInteraction) unmarshaller.unmarshal(request.getInputStream());    
    }
    catch (Exception e){
        // log error and return a null (or whatever you want to do with the error)
    }

    return ci;
} 

答案 2 :(得分:0)

使用MessageBodyReader作为优秀的@Blaise Doughan建议为您提供了很大的灵活性。 显然,如果你已经拥有了@Consumes Annotation和你的JAXB注释类,我可以看到它看起来很冗长。

这真的取决于你的舒适程度。我注意到你没有定义XML模式,因此你手动创建了JAXB类,并且在同一个类(或外部自定义验证器)中编写验证逻辑似乎是合乎逻辑的。

我个人会考虑编写XML Schema,特别是如果您的验证规则很容易表达的话。对您的项目来说,这可能是一项很好的投资:从那时起您可以自动生成JAXB类,并自动获得验证,因此您应该具有更好的可维护性。