2

使用 JAX-WS 2,我看到了其他人也谈到的一个问题。问题是,如果在处理程序中接收到 SOAP 消息,并且该 SOAP 消息很大——无论是由于内联 SOAP 正文元素碰巧有很多内容,还是由于 MTOM 附件——那么很容易获得内存不足错误。

原因是对 getMessage() 的调用似乎引发了一系列事件,这些事件涉及读取线路上的整个 SOAP 消息,并创建一个对象(或多个对象)来表示线路上的内容。

例如:

...
public boolean handleMessage(SOAPMessageContext context)
{
    // for a large message, this will cause an OutOfMemoryError
    System.out.println( context.getMessage().countAttachments() );
...

我的问题是:是否有已知的机制/解决方法来处理这个问题?具体来说,最好访问 SOAP 消息中的 SOAP 部分而不强制附件(例如,如果 MTOM)也被清理掉。

4

4 回答 4

2

For those who run their app on JBoss 6 & 7 (with Apache CXF)... I was able to troubleshoot the problem by implementing my handler from the LogicalHandler interface instead of the SOAPHandler. In this case your handleMessage() method would get the LogicalMessageContext context (instead of SOAPMessageContext) in the arguments that has no issues with the context.getMessage() call

于 2019-07-13T20:37:29.083 回答
1

实际上有一个 JAX-WS RI(又名 Metro)特定的解决方案,它非常有效。

请参阅https://javaee.github.io/metro/doc/user-guide/ch02.html#efficient-handlers-in-jax-ws-ri。不幸的是,该链接现在已损坏,但您可以在 WayBack Machine 上找到它。我将在下面给出重点:

早在 2007 年,Metro 就引入了一种额外的处理程序类型MessageHandler<MessageHandlerContext>,它是 Metro 专有的。SOAPHandler<SOAPMessageContext>它比不尝试在内存中进行 DOM 表示要高效得多。

这是原始博客文章中的关键文本:

消息处理程序:

利用 JAX-WS 规范提供的可扩展处理程序框架和 RI 中更好的消息抽象,我们引入了一个新的处理程序,称为MessageHandler扩展您的 Web 服务应用程序。MessageHandler 类似于 SOAPHandler,除了它的实现可以访问MessageHandlerContext(MessageContext 的扩展)。通过 MessageHandlerContext 可以访问 Message 并使用 Message API 处理它。正如我在博客标题中提到的,这个处理程序允许您处理消息,它提供了访问/处理消息的有效方法,而不仅仅是基于 DOM 的消息。处理程序的编程模型是相同的,消息处理程序可以与标准逻辑和 SOAP 处理程序混合使用。我在 JAX-WS RI 2.1.3 中添加了一个示例,显示了使用 MessageHandler 来记录消息,这里是示例中的一个片段:

public class LoggingHandler implements MessageHandler<MessageHandlerContext> {
    public boolean handleMessage(MessageHandlerContext mhc) {
        Message m = mhc.getMessage().copy();
        XMLStreamWriter writer = XMLStreamWriterFactory.create(System.out);
        try {
            m.writeTo(writer);
        } catch (XMLStreamException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public boolean handleFault(MessageHandlerContext mhc) {
        ..... 
        return true;
    }

    public void close(MessageContext messageContext) {    }

    public Set getHeaders() {
        return null;
    }
}

(引自 2007 年博文)

您可以在Metro GitHub 存储库中找到完整示例

于 2017-10-02T10:21:58.577 回答
0

您使用的是什么 JAX-WS 实现运行时?如果有办法使用内置于 WebSphere 中的运行时执行此操作,我确信在其他运行时(如 Axis2(正确)、Apache CXF 和 Metro/RI)中可以干净地执行此操作。

于 2013-09-06T20:28:49.847 回答
0

我正在使用另一种方法来降低内存成本,即Message Accessor.

我没有使用context.getMessage(),而是将其更改为:

Object accessor = context.get("jaxws.message.accessor");

if (accessor != null) {
                baosInString = accessor.toString();
                }

Base on advice from IBM website. http://www-01.ibm.com/support/docview.wss?uid=swg1PM21151

于 2018-03-29T03:03:42.450 回答