如何在使用注释时在JAXB unmarshaller上设置自定义ValidationEventHandler

时间:2014-05-20 04:52:58

标签: java validation jaxb jax-ws unmarshalling

我们将JAX-WS与JAXB结合使用来接收和解析XML Web服务调用。这都是基于注释的,即我们从未在代码中掌握JAXBContext。我需要在unmarshaller上设置一个自定义ValidationEventHandler,这样如果不接受特定字段的日期格式,我们就可以捕获错误并在响应中报告一些好的东西。我们在相关字段上有一个XMLJavaTypeAdapter,它进行解析并抛出异常。我无法看到如何使用我们拥有的基于注释的配置将ValidationEventHandler设置到unmarshaller上。有什么想法吗?

注意:与this comment相同的问题目前尚无人接听。

1 个答案:

答案 0 :(得分:1)

上周我一直在努力解决这个问题,最后我已经设法解决了这个问题。诀窍是JAXB在使用@XmlRootElement注释的对象中查找beforeUnmarshal和afterUnmarshal之前的方法。

public class CustomEventHandler implements ValidationEventHandler{

      @Override
      public boolean handleEvent(ValidationEvent event) {
            if (event.getSeverity() == event.ERROR ||
                        event.getSeverity() == event.FATAL_ERROR)
            {
                  ValidationEventLocator locator = event.getLocator();
                  throw new RuntimeException(event.getMessage(), event.getLinkedException());
            }
            return true;
      }
}

使用此ValidationEventHandler:

  @SuppressWarnings("unchecked")
  public static Schema getSchemaFromContext(Class clazz) throws JAXBException, IOException, SAXException{
        JAXBContext jc = JAXBContext.newInstance(clazz);
        final List<ByteArrayOutputStream> outs = new ArrayList<ByteArrayOutputStream>();
        jc.generateSchema(new SchemaOutputResolver(){
              @Override
              public Result createOutput(String namespaceUri,
                         String suggestedFileName) throws IOException {
              ByteArrayOutputStream out = new ByteArrayOutputStream();
              outs.add(out);
              StreamResult streamResult = new StreamResult(out);
              streamResult.setSystemId("");
              return streamResult;
              }
        });
        StreamSource[] sources = new StreamSource[outs.size()];
        for (int i = 0; i < outs.size(); i++) {
              ByteArrayOutputStream out = outs.get(i);
              sources[i] = new StreamSource(new ByteArrayInputStream(out.toByteArray()), "");
        }
        SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        return sf.newSchema(sources);
  }

}

这是在Utility类中创建的getSchemaFromContext方法:

private BaseLoaderCallback  mLoaderCallback = new BaseLoaderCallback(this) {
    @Override
    public void onManagerConnected(int status) {
        switch (status) {
            case LoaderCallbackInterface.SUCCESS:
            {
                Log.i(TAG, "OpenCV loaded successfully");
                // either call your opencv code from **here**
                // or from onCameraViewStarted(). either way, you will have 
                // to wait, until this thing finished (async!)
            } break;
            default:
            {
                super.onManagerConnected(status);
            } break;
        }
    }
};


@Override
public void onResume()
{
    super.onResume();
    OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);
}