1

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

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

    ...
}

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

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

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

4

2 回答 2

0

以下是如何使用 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;
于 2013-04-15T13:28:22.900 回答
0

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

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")
于 2013-10-11T18:02:21.290 回答