Совместим ли SAAJ с MTOM + XOP?

Я пытаюсь использовать MTOM + XOP для возврата байта [] в веб-службе Spring, но при сортировке результата он выдает SAXParseException с сообщением:

cvc-type.3.1.2: Элемент dataHandler является простым типом, поэтому он не должен иметь элемент информации элемента [children].

Кажется, что после написания тега XOP валидатор встречается с ним вместо ожидаемого содержимого byte[] и выдает исключение SAXParseException с уровнем FATAL, который останавливает процесс.

Я использую:

  • JDK 1,7
  • SAAJ 1.3
  • SOAP 1.1
  • Весна 4.1.4. РЕЛИЗ
  • Spring WS 2.2.0.RELEASE

заранее спасибо

2 ответа

Решение

Я нашел два обходных пути для моей ситуации:

  1. Не устанавливая xmlschema маршаллеру.

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

Класс бетона для unmarshaller:

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

Для маршаллера я ищу условие, которое идентифицирует случай, потому что ValidationEventLocator только установить объект, и это может быть что угодно.

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

Это не проблема с SAAJ, но с Spring-WS. Это связано с тем, что Spring-WS передает сообщение, закодированное в XOP, в средство проверки схемы, которое не понимает XOP. В конечном итоге проблема заключается в том, что Spring-WS не имеет четко определенной модели обработки для XOP/MTOM, как я объяснил в этой статье.

Другие вопросы по тегам