【问题标题】:Saving outbound messages in CXF interceptor在 CXF 拦截器中保存出站消息
【发布时间】:2023-03-26 20:31:01
【问题描述】:

我在 CXF 方面遇到了一个非常棘手的问题,我试图解决(不成功)一个多月。我读过很多类似的问题,但没有任何帮助。

首先介绍一下我用来保存出站消息的部分代码:

  public void handleMessage(SoapMessage message) throws Fault {
        OutputStream os = message.getContent(OutputStream.class);
        CacheAndWriteOutputStream cwos = new CacheAndWriteOutputStream(os);
        message.setContent(OutputStream.class, cwos);
        cwos.registerCallback(new LoggingOutCallBack());
    }

    class LoggingOutCallBack implements CachedOutputStreamCallback
    {
        public void onClose (CachedOutputStream cos)
        {
            try
            {
                String result = IOUtils.toString(cos.getInputStream());
            }
            catch (Exception e)
            {
                LogFactory.getLog(SwcFinalResponseInterceptor.class).error(ExceptionUtils.getStackTrace(e));
            }
        }

        public void onFlush (CachedOutputStream arg)
        {
        }
    }

我使用 PRE_STREAM 阶段。很多地方都提到了这种方法(例如,here),但它会导致一些罕见的错误。我每天大约有 20000 个请求,所以,比如说,对于 200 个大请求,这种方法失败了 - 对于进一步的请求之一,我得到 Stream closed 错误。

2013-12-19 15:37:47,902 [WARN ] org.apache.cxf.common.logging.LogUtils.doLog(LogUtils.java:400)
5880162-Interceptor for {http://service.ws.swc.comtech/}FrequentFlyerServiceWsService has thrown exception, unwinding now
5880163-org.apache.cxf.interceptor.Fault: Stream closed
5880164-        at org.apache.cxf.interceptor.LoggingInInterceptor.logging(LoggingInInterceptor.java:144)
5880165-        at org.apache.cxf.interceptor.LoggingInInterceptor.handleMessage(LoggingInInterceptor.java:73)

我绝对确定这是因为我的代码中的这一行:

cos.getInputStream()

我已经测试了很多次,没有这一行,一切正常,但是当我添加这一行时,错误立即出现。 我想这是因为 CXF 不是在内存中而是在某个临时文件中存储大流的流数据。它被描述为here

有趣的一点是,当我尝试自己加载测试服务器时,使用 curl 发送数千个繁重的请求,没有错误,但是当有很多客户端时,几乎立即开始出现问题。

我还找到了another solution,乍一看,它似乎工作正常,我不再收到
Stream closed错误,但服务器开始跳过一些响应。

请帮帮我,我真的不知道我还能读什么或做什么,我不擅长流和 CXF,但我需要一个可行的解决方案,如果你能解释我做错了什么,那就太好了。

如果您不能直接回答这个问题,请至少回答以下一些问题:

  1. 为什么需要这一行message.setContent(OutputStream.class, cwos);? 我不想修改流内容,只是获取里面的内容,那我为什么要读取然后再次发送内容?

  2. 可能有比这个 message.getContent(OutputStream.class); 更合适的格式(要获取的类)?

  3. 我应该使用另一个拦截器阶段吗?

  4. 有一个方法onClose,在流关闭之前或之后触发?这什么时候发生?我不希望在它的内容作为请求发送给客户端之前关闭它。

提前致谢!

【问题讨论】:

  • 你是用spring来配置cxf的吗
  • 嗯,我不知道,因为项目是在我之前编写的。据我判断,它使用名为 appContext.xml 的 XML 文件进行配置。

标签: java io cxf


【解决方案1】:

我理解你的问题的方式:

  1. 如果您只想记录 SOAP 请求响应信封,您甚至不应该使用 StreamInterceptor。最好使用 LoggingInterceptor。回答你的第一个问题 message.setContent(OutputStream.class, cwos);拦截传出的soap消息并更改其中的内容。

  2. 如果您想继续使用 StreamInterceptor,您最终将使用相同的方法来获取 OutputStream 的内容。另一种方法是使用 LoggingInterceptor。 有关这方面的更多信息 How to log Apache CXF Soap Request and Soap Response using Log4j

  3. 您可以继续使用预流。但如果目的只是阅读消息内容,则可以使用 pre_invoke。使用一个比另一个没有优势。 这是一个链接,它可以让您了解如何扩展一个简单的类来实现 LoggingInterceptor。 http://cxf.apache.org/docs/interceptors.html

    How to get incoming & outgoing soap xml in a simple way using Apache CXF?

【讨论】:

  • 最好使用 LoggingInterceptor 好吧,我的任务是将 xml 响应保存到数据库,所以日志记录是不够的。 拦截传出的soap消息并更改其中的内容我理解,但我不想更改任何内容,只想阅读和保存。 您最终会使用相同的方法来获取 OutputStream 的内容 正如我所提到的,这会导致一些罕见的错误导致巨大的响应(几兆字节)我将尝试使用您上一个链接中的方法,希望对我有帮助。
  • 我也在寻找解决方案。我必须将拦截器故障保存到数据库中。我能够以 json/soap 的形式获取有效负载。如何使用我用于 camel-sql 组件的相同数据源?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-02
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多