SAAJ 与 MTOM + XOP 兼容吗?
Is SAAJ compatible with MTOM + XOP?
我正在尝试使用 MTOM + XOP 在 Spring Web 服务中 return 一个字节 [] 但是当编组结果时它抛出一个 SAXParseException 消息:
cvc-type.3.1.2: 元素'dataHandler'是简单类型,所以一定没有元素信息项[children].
似乎在写入 XOP 标记后,验证器遇到了它,而不是它期望的 byte[] 内容,并抛出了一个 FATAL 级别的 SAXParseException 来停止进程。
我正在使用:
- JDK1.7
- SAAJ 1.3
- SOAP 1.1
- Spring 4.1.4.RELEASE
- Spring WS 2.2.0.RELEASE
提前致谢
这不是 SAAJ 的问题,而是 Spring-WS 的问题。这是因为 Spring-WS 将 XOP 编码的消息传递给不理解 XOP 的模式验证器。最终问题是 Spring-WS 没有针对 XOP/MTOM 定义明确的处理模型,正如我在 this article.
中解释的那样
我找到了两个适合我的情况的解决方法:
没有将 xmlschema 设置为编组器。
将 ValidationEventHandler
设置为跳过 XOP 失败的编组器。
这是将 ValidationEventHandler
设置为跳过 XOP 失败的编组器的示例:
摘要超级class:
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;
}
}
解组器的具体 class:
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
subclass 激活 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()));
}
}
我正在尝试使用 MTOM + XOP 在 Spring Web 服务中 return 一个字节 [] 但是当编组结果时它抛出一个 SAXParseException 消息:
cvc-type.3.1.2: 元素'dataHandler'是简单类型,所以一定没有元素信息项[children].
似乎在写入 XOP 标记后,验证器遇到了它,而不是它期望的 byte[] 内容,并抛出了一个 FATAL 级别的 SAXParseException 来停止进程。
我正在使用:
- JDK1.7
- SAAJ 1.3
- SOAP 1.1
- Spring 4.1.4.RELEASE
- Spring WS 2.2.0.RELEASE
提前致谢
这不是 SAAJ 的问题,而是 Spring-WS 的问题。这是因为 Spring-WS 将 XOP 编码的消息传递给不理解 XOP 的模式验证器。最终问题是 Spring-WS 没有针对 XOP/MTOM 定义明确的处理模型,正如我在 this article.
中解释的那样我找到了两个适合我的情况的解决方法:
没有将 xmlschema 设置为编组器。
将
ValidationEventHandler
设置为跳过 XOP 失败的编组器。
这是将 ValidationEventHandler
设置为跳过 XOP 失败的编组器的示例:
摘要超级class:
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;
}
}
解组器的具体 class:
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
subclass 激活 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()));
}
}