Совместим ли 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 ответа
Я нашел два обходных пути для моей ситуации:
Не устанавливая xmlschema маршаллеру.
Настройка
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, как я объяснил в этой статье.