带有大消息的 JAX-WS SoapHandler:OutOfMemoryError [英] JAX-WS SoapHandler with large messages: OutOfMemoryError

查看:14
本文介绍了带有大消息的 JAX-WS SoapHandler:OutOfMemoryError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Using JAX-WS 2, I see an issue that others have spoken about as well. The issue is that if a SOAP message is received inside a handler, and that SOAP message is large - whether due to inline SOAP body elements that happen to have lots of content, or due to MTOM attachments - then it is dangerously easy to get an OutOfMemoryError.

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

The reason is that the call to getMessage() seems to set off a chain of events that involve reading the entire SOAP message on the wire, and creating an object (or objects) representing what was on the wire.

例如:

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

我的问题是:是否有已知的机制/解决方法来处理这个问题?具体来说,最好在不强制清除附件(例如 MTOM)的情况下访问 SOAP 消息中的 SOAP 部分.

My question is: is there a known mechanism/workaround for dealing with this? Specifically, it would be nice to access the SOAP part in a SOAP message without forcing the attachments (if MTOM for example) to also be vacuumed up.

推荐答案

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

There's actually a JAX-WS RI (aka Metro) specific solution for this which is very effective.

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

See https://javaee.github.io/metro/doc/user-guide/ch02.html#efficient-handlers-in-jax-ws-ri. Unfortunately that link is now broken but you can find it on WayBack Machine. I'll give the highlights below:

Metro 人员于 2007 年 引入 额外的处理程序类型, MessageHandler,这是 Metro 专有的.它比 SOAPHandler 高效得多,因为它不尝试在内存中进行 DOM 表示.

The Metro folks back in 2007 introduced an additional handler type, MessageHandler<MessageHandlerContext>, which is proprietary to Metro. It is far more efficient than SOAPHandler<SOAPMessageContext> as it doesn't try to do in-memory DOM representation.

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

Here's the crucial text from the original blog article:

消息处理器:

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

Utilizing the extensible Handler framework provided by JAX-WS Specification and the better Message abstraction in RI, we introduced a new handler called MessageHandler to extend your Web Service applications. MessageHandler is similar to SOAPHandler, except that implementations of it gets access to MessageHandlerContext (an extension of MessageContext). Through MessageHandlerContext one can access the Message and process it using the Message API. As I put in the title of the blog, this handler lets you work on Message, which provides efficient ways to access/process the message not just a DOM based message. The programming model of the handlers is same and the Message handlers can be mixed with standard Logical and SOAP handlers. I have added a sample in JAX-WS RI 2.1.3 showing the use of MessageHandler to log messages and here is a snippet from the sample:

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 年博文的结尾)

(end quote from 2007 blog post)

你可以找到一个Metro GitHub 存储库中的 nofollow noreferrer">完整示例.

You can find a full example in the Metro GitHub repo.

这篇关于带有大消息的 JAX-WS SoapHandler:OutOfMemoryError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆