当前位置: 首页 > 面试题库 >

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

阚亮
2023-03-14
问题内容

使用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部分。


问题答案:

实际上,有一个针对此的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 handlercontext> ,它是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;
    }
}


 类似资料:
  • 我使用hikaricp作为我的数据库连接池。当我完成我的SQL语句时,我将关闭连接,在连接上调用关闭,我相信您应该将连接代理返回到池。然而,我看到以下警告(不是错误)消息,我不得不怀疑这是否是一个需要解决的问题,因为我没有正确清理我的连接资源。我不是使用资源尝试,而是使用尝试捕获最后(我在最后关闭连接

  • 因此,我们计划使用Avro在融合的Kafka生态系统上进行交流。我目前对Avro的理解是,每条消息都有自己的模式。如果是这样的话,我们需要模式注册表来解决版本更新吗? 我问,因为在每条消息中携带模式可以防止需要像模式注册表这样的东西来将消息ID映射到模式。还是我在这里错过了什么?

  • 我正在尝试编写一条路由,将消息转发到这样的sedaendpoint 还有另一个从seda终结点消耗的路由: JMS连接工厂的JMS确认模式是CLIENT_ACKNOWLEDGE,我已经使用spring boot配置了该项目。根据配置,一旦第一个驼峰路由结束,它就应该提交事务并将确认发送给message broker。 但是,这种行为是消息确认只在第二条路由完成后发生。我可以在第一个路由中配置什么来

  • 但是附件总是空的。有什么建议吗?提前谢了。

  • 我创建了项目Spring Boot项目并实施了Restful服务,如下所示: AngularJS方法: 在执行添加用户的操作之前,管理员必须通过身份验证才能访问我的应用程序。我做了如下配置: -类MvcConfig.java: 我对网页使用JSP框架,因此我拒绝使用控制器返回JSP页面: -当我添加一个新用户后,我遇到以下问题: 错误:“未找到”消息:“无可用消息”路径:“/App/Users/A

  • 我试图用Spring Cloud Stream创建一个kafka使用者,以便监听在任何Spring上下文之外构建的kafka消息,并使用自定义头(operationType)。 我使用的是Spring Boot 1.5.x/Spring Cloud egdware.sr5和1.1.1版本的kafka-client和Kafka2.11。 我的侦听器类包含此方法 而operationType标头是存在