JAXWS Soap Handler大型MTOM附件

IBM SOAP 7和8中的JAXWS实现在肥皂处理程序和大型MTOM附件方面似乎存在一些问题。 当在SOAPMessageContext对象上调用getMessage()时,似乎将整个消息(包括所有附件二进制内容)读入内存。 这很容易导致JVM耗尽可用内存。

@Override public boolean handleMessage(SOAPMessageContext context) { SOAPMessage soapMsg = context.getMessage(); ... } 

在上面的代码片段中,如果传入的请求附件大于JVM中可用的可用内存量,则context.getMessage()可能导致内存不足exception。

如何在不触发此不良function的情况下访问SoapHeader元素? 我看到SOAPMessageContext类有一个getHeaders(…)方法,但我不确定如何使用它。 我特别不确定要为JAXBContext传递什么。 任何人都可以提供一个例子或解释如何使用这种方法吗?

这是另一个相关的stackoverflow文章: 带有大消息的JAX-WS SoapHandler:OutOfMemoryError

以下是如何在不使用WebSphere内置JAX-WS实现读取整个消息的情况下访问头文件。

 public boolean handleMessage(SOAPMessageContext context) { AttributedURI messageIdURI = (AttributedURI)context.get("com.ibm.wsspi.wsaddressing.inbound.MessageID"); String messageId = ""; if (messageIdURI != null && messageIdURI.getURI() != null) { messageId = messageIdURI.getURI().toString(); } EndpointReference fromApplicationEPR = (EndpointReference)context.get("com.ibm.wsspi.wsaddressing.inbound.FromEPR"); String fromApplication = ""; if (fromApplicationEPR != null && fromApplicationEPR.getAddress() != null && fromApplicationEPR.getAddress().getURI() != null) { fromApplication = fromApplicationEPR.getAddress().getURI().toString(); } ... return true; } 

请注意,这基于精确的JAX-WS实现而有所不同。 当我有机会时,我将通过Apache CXF发布如何做到这一点。 以下是上述代码所需的导入:

 import com.ibm.ws.wsaddressing.AttributedURI; import com.ibm.ws.wsaddressing.EndpointReference; 

对于Apache CXF,最好的方法是使用特定于CXF实现的Interceptor。 下面是一个示例自定义拦截器类。

 package com.company.app.interceptor; import javax.xml.namespace.QName; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor; import org.apache.cxf.headers.Header; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.phase.Phase; import org.apache.log4j.Logger; import org.w3c.dom.Element; public class SOAPHeaderInterceptor extends AbstractSoapInterceptor { private static Logger logger = Logger.getLogger(SOAPHeaderInterceptor.class); public SOAPHeaderInterceptor() { super(Phase.USER_PROTOCOL); } @Override public void handleMessage(SoapMessage message) throws Fault { try { Header fromHeader = message.getHeader(new QName("http://www.w3.org/2005/08/addressing", "From")); Header messageIdHeader = message.getHeader(new QName("http://www.w3.org/2005/08/addressing", "MessageID")); String from = null; if (fromHeader != null && fromHeader.getObject() != null) { from = ((Element)fromHeader.getObject()).getTextContent(); } String messageId = null; if (messageIdHeader != null && messageIdHeader.getObject() != null) { messageId = ((Element)messageIdHeader.getObject()).getTextContent(); } } catch (Exception e) { logger.error("Unable to read SOAP Headers", e); } } } 

然后,在JAX-WS服务实现类中指定@InInterceptors批注。

 @InInterceptors(interceptors ="com.company.app.interceptor.SOAPHeaderInterceptor")