tangguo

带有大消息的JAX-WS SoapHandler:OutOfMemoryError

java

使用JAX-WS 2,我也看到了其他人也谈到过的一个问题。问题是,如果在处理程序内部接收到SOAP消息,并且该SOAP消息很大(无论是由于恰好具有很多内容的内联SOAP正文元素,还是由于MTOM附件),那么很容易获得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部分。


阅读 222

收藏
2020-11-15

共1个答案

小编典典

实际上,有一个针对此的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,它是Metro专有的。它比SOAPHandler不尝试在内存中进行DOM表示要高效得多。

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

MessageHandler:

利用JAX-WS规范提供的可扩展处理程序框架和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;
    }
}
2020-11-15