I have an extremely hard problem for me with CXF, which I'm trying to solve (unsuccessfully) for more than a month. I'd read lots of similar questions, but nothing could help me.
First of all, let me introduce part of the code, which I use to save the outbound messages:
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)
{
}
}
I use the PRE_STREAM phase. This approach is mentioned in lots of places (for example, here), but it causes some rare errors. I have approximately 20000 requests a day, so, say, for 200 large requests this approach fails - for one of the further requests I get Stream closed error.
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)
I'm absolutely sure that is because of this line in my code:
cos.getInputStream()
I've tested lots of times without this only line, and everything worked correct, but when I add this line, errors appear immediately. I suppose that's because CXF stores stream data for large streams not in memory but in some temporary file. It was described here.
An interesting point is that when I try to load the testing server by myself, sending thousands of heavy requests with curl, there are no errors, but when there are lots of clients, problems start to appear practically immediately.
I also found another solution and, at first glance, it seemed to work fine, I get no more
Stream closed errors, but server starts to skip some responses.
Please, help me, I really don't know what else can I read or do, I'm not good at streams and CXF, but I need a working solution and it would be great if you could explain what I'm doing wrong.
If you can't answer this question directly, please, at least, answer some of these questions:
Why this line is required message.setContent(OutputStream.class, cwos);? I don't want to modify stream content, just get what's inside, so why should I read and then send contents again?
May be there is more appropriate format (class to get) than this message.getContent(OutputStream.class);?
May be I should use another interceptor phase?
There is a method onClose, which is triggered BEFORE stream is closed or AFTER? And when does this happen? I don't want the strem to be closed before it's content is sent as a request to the client.
Thanks in advance!