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

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

问题描述

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

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

例如:

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

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

解决方案

实际上,有一个针对JAX-WS RI(aka Metro)的解决方案非常有效.

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

Metro员工早在2007年引入了另一个处理程序类型,MessageHandler<MessageHandlerContext>,这是Metro专有的.它比SOAPHandler<SOAPMessageContext>效率更高,因为它没有尝试执行内存中的DOM表示.

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

MessageHandler:

利用JAX-WS提供的可扩展Handler框架 我们介绍了RI中的规范和更好的消息抽象 一个名为MessageHandler的新处理程序,以扩展您的Web服务 应用程序. MessageHandler与SOAPHandler类似,不同之处在于: 它的实现可以访问MessageHandlerContext( MessageContext的扩展名).通过MessageHandlerContext一个可以 访问消息并使用消息API对其进行处理.正如我所说的 博客的标题,此处理程序可让您处理Message, 提供有效的方法来访问/处理消息,而不仅仅是DOM 基于消息.处理程序的编程模型是相同的,并且 消息处理程序可以与标准Logical和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存储库中的nofollow noreferrer>完整示例. /p>

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.

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.

For example:

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

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.

解决方案

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

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:

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:

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;
    }
}

(end quote from 2007 blog post)

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

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

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