2

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

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

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

我正在使用:

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

提前致谢

4

2 回答 2

2

我为我的情况找到了两种解决方法:

  1. 未将 xmlschema 设置为编组器。

  2. 将 a 设置为ValidationEventHandler跳过 XOP 失败的编组器。

这是一个将 a 设置为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()));
  }
}
于 2016-07-28T14:29:19.633 回答
0

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

于 2016-07-26T21:33:36.943 回答