java - 使用注释时如何在 JAXB 解码器上设置自定义 ValidationEventHandler

标签 java validation jaxb jax-ws unmarshalling

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

注意:同一个问题 this comment目前没有答案。

最佳答案

上周我一直在努力解决这个问题,最后我找到了一个可行的解决方案。诀窍在于 JAXB 在使用 @XmlRootElement 注释的对象中查找方法 beforeUnmarshal 和 afterUnmarshal。

..
@XmlRootElement(name="MSEPObtenerPolizaFechaDTO")
@XmlAccessorType(XmlAccessType.FIELD)

public class MSEPObtenerPolizaFechaDTO implements Serializable {
..

public void beforeUnmarshal(Unmarshaller unmarshaller, Object parent) throws JAXBException, IOException, SAXException {
        unmarshaller.setSchema(Utils.getSchemaFromContext(this.getClass()));
        unmarshaller.setEventHandler(new CustomEventHandler());
  }

  public void afterUnmarshal(Unmarshaller unmarshaller, Object parent) throws JAXBException {
        unmarshaller.setSchema(null);
        unmarshaller.setEventHandler(null);
  }

使用此 ValidationEventHandler:

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

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

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

关于java - 使用注释时如何在 JAXB 解码器上设置自定义 ValidationEventHandler,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23751249/

相关文章:

java - MOXy/JAXB 注释在 weblogic 12c 上被忽略

java - 为什么axis2 1.6.2 java2wdsl.sh忽略复杂类型的类成员

java - 格式化日期 - 找不到符号

java - CloudBees 和 App Cells、实例和池

java - 如何向 JPanel 添加背景,然后在该 JPanel 上添加 JButton

php - AngularJS 表单验证 - 跳过预填充的输入字段

maven-2 - 哪些 Maven2 插件可用于 JAXB2?

java - 如何将idlj-maven-plugin创建的资源添加到generate-sources阶段

model-view-controller - 如何在主干应用程序中显示反馈/错误消息

检查输入是否为数字