【问题标题】:Is SAAJ compatible with MTOM + XOP?SAAJ 与 MTOM + XOP 兼容吗?
【发布时间】:2016-11-30 11:47:05
【问题描述】:

我正在尝试使用 MTOM + XOP 在 Spring Web 服务中返回一个字节 [],但是在编组结果时它会抛出一个 SAXParseException 并带有消息:

cvc-type.3.1.2:元素'dataHandler'是简单类型,所以它必须没有元素信息项[children]。

似乎在编写 XOP 标记后,验证器会遇到它而不是它期望的 byte[] 内容,并抛出具有 FATAL 级别的 SAXParseException 以停止进程。

我正在使用:

  • JDK 1.7
  • SAAJ 1.3
  • SOAP 1.1
  • Spring 4.1.4.RELEASE
  • Spring WS 2.2.0.RELEASE

提前致谢

【问题讨论】:

    标签: java spring-ws mtom saaj xop


    【解决方案1】:

    针对我的情况,我找到了两种解决方法:

    1. 未将 xmlschema 设置为 marshaller。

    2. 将 ValidationEventHandler 设置为跳过 XOP 故障的编组器。

    这是一个将ValidationEventHandler 设置为跳过 XOP 故障的编组器的示例:

    抽象超类:

    import javax.xml.bind.ValidationEvent;
    import javax.xml.bind.ValidationEventHandler;
    
    abstract class XopAwareValidationEventHandler implements ValidationEventHandler {
    
      private static final String CVC_TYPE_3_1_2 = "cvc-type.3.1.2";
    
      private ValidationEventHandler realHandler;
    
      XopAwareValidationEventHandler(final ValidationEventHandler handler) {
        this.setRealHandler(handler);
      }
    
      @Override
      public boolean handleEvent(final ValidationEvent event) {
        final boolean result = this.getRealHandler().handleEvent(event);
        if (!result) {
          if (event.getMessage() != null && event.getMessage().startsWith(CVC_TYPE_3_1_2)) {
            return this.isXopEvent(event);
          }
        }
        return result;
      }
    
      abstract boolean isXopEvent(ValidationEvent validationEvent);
    
      private ValidationEventHandler getRealHandler() {
        return realHandler;
      }
    
      private void setRealHandler(final ValidationEventHandler realHandler) {
        this.realHandler = realHandler;
      }
    }
    

    解组器的具体类:

    import javax.xml.bind.ValidationEvent;
    import javax.xml.bind.ValidationEventHandler;
    
    class XopAwareUnmarshallingValidationEventHandler extends XopAwareValidationEventHandler {
    
      private static final String XOP_INCLUDE = "xop:Include";
    
      XopAwareUnmarshallingValidationEventHandler(final ValidationEventHandler handler) {
        super(handler);
      }
    
      @Override
      boolean isXopEvent(final ValidationEvent validationEvent) {
        final ValidationEventLocator locator = validationEvent.getLocator();
        return locator != null && locator.getNode() != null &&
            locator.getNode().getFirstChild() != null &&
            XOP_INCLUDE.equals(locator.getNode().getFirstChild().getNodeName());
      }
    }
    

    对于 marshaller,我正在搜索识别案例的条件,因为 ValidationEventLocator 只有 Object 集,它可以是任何东西。

    import javax.xml.bind.ValidationEvent;
    import javax.xml.bind.ValidationEventHandler;
    import javax.xml.bind.ValidationEventLocator;
    
    public class XopAwareMarshallingValidationEventHandler extends XopAwareValidationEventHandler {
    
      public XopAwareMarshallingValidationEventHandler(final ValidationEventHandler handler) {
        super(handler);
      }
    
      boolean isXopEvent(final ValidationEvent validationEvent) {
        final ValidationEventLocator locator = validationEvent.getLocator();
        return locator != null && locator.getNode() == null;
      }
    }
    

    org.springframework.oxm.jaxb.Jaxb2Marshaller 激活 MTOM 并添加两个事件处理程序的子类:

    import javax.xml.bind.JAXBException;
    import javax.xml.bind.Marshaller;
    import javax.xml.bind.Unmarshaller;
    
    import org.springframework.oxm.jaxb.Jaxb2Marshaller;
    
    import XopAwareMarshallingValidationEventHandler;
    import XopAwareUnmarshallingValidationEventHandler;
    
    public class XopAwareJaxb2Marshaller extends Jaxb2Marshaller {
    
      public XopAwareJaxb2Marshaller() {
        this.setMtomEnabled(true);
      }
    
      protected void initJaxbMarshaller(final Marshaller marshaller) throws JAXBException {
        super.initJaxbMarshaller(marshaller);
    
        marshaller.setEventHandler(new XopAwareMarshallingValidationEventHandler(marshaller.getEventHandler()));
      }
    
      protected void initJaxbUnmarshaller(final Unmarshaller unmarshaller) throws JAXBException {
        super.initJaxbUnmarshaller(unmarshaller);
    
        unmarshaller.setEventHandler(new XopAwareUnmarshallingValidationEventHandler(unmarshaller
            .getEventHandler()));
      }
    }
    

    【讨论】:

      【解决方案2】:

      这不是 SAAJ 的问题,而是 Spring-WS 的问题。这是因为 Spring-WS 将 XOP 编码的消息传递给不理解 XOP 的模式验证器。归根结底,问题在于 Spring-WS 没有明确定义的 XOP/MTOM 处理模型,正如我在 this article 中解释的那样。

      【讨论】:

      • 谢谢安德烈亚斯,我读过你的文章。令我惊讶的是,这在 Spring-WS 中不是一个开放的问题,在论坛中也没有太多评论。
      • 这仍然是当前日期的问题?
      • 我认为情况几乎没有变化。几个月前,我发送了几个拉取请求来开始修复一些问题,但我从未得到回复。我认为问题在于 Spring-WS 并不是真正的社区驱动项目:如果您与 Pivotal 签订了支持合同,那么您将能够对产品进行更改,否则祝您好运。
      猜你喜欢
      • 1970-01-01
      • 2023-03-12
      • 2012-01-23
      • 1970-01-01
      • 2014-08-02
      • 2017-08-09
      • 1970-01-01
      • 2013-08-11
      • 2020-03-16
      相关资源
      最近更新 更多