Return-Path: X-Original-To: apmail-cxf-dev-archive@www.apache.org Delivered-To: apmail-cxf-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id B218544AC for ; Fri, 17 Jun 2011 22:47:20 +0000 (UTC) Received: (qmail 10866 invoked by uid 500); 17 Jun 2011 22:47:20 -0000 Delivered-To: apmail-cxf-dev-archive@cxf.apache.org Received: (qmail 10809 invoked by uid 500); 17 Jun 2011 22:47:20 -0000 Mailing-List: contact dev-help@cxf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cxf.apache.org Delivered-To: mailing list dev@cxf.apache.org Received: (qmail 10801 invoked by uid 99); 17 Jun 2011 22:47:20 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 17 Jun 2011 22:47:20 +0000 X-ASF-Spam-Status: No, hits=-0.7 required=5.0 tests=FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,RFC_ABUSE_POST,SPF_PASS,T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: apache.org Received-SPF: pass (nike.apache.org: domain of elakito@googlemail.com designates 209.85.213.169 as permitted sender) Received: from [209.85.213.169] (HELO mail-yx0-f169.google.com) (209.85.213.169) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 17 Jun 2011 22:47:13 +0000 Received: by yxp4 with SMTP id 4so2074979yxp.0 for ; Fri, 17 Jun 2011 15:46:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:mime-version:date:message-id:subject:from:to :content-type; bh=82c2yTGRgp6uiuj+YyhBW9WOcz9I2+Op/ZvXyKCBpHM=; b=fVERlEp5e9iLZoPgBROale0vfeWYKQKAXgizApTMh3OyvSPAlyGSUrH5R/6RZ+YiTw E3LEdwjYL48OkuvVtXV6yYlOVfqzutPXAb1FkhGCcSYAvKwnvMvw8DTCx/urhAV8+38x QQkCD57zsRj0L7r91cvKoS50+QdzNCSPiXMg4= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; b=ee8Mx/lEXgM3ZWYDmWiKLOGr2RWxXkT4eXunjLnMwaMDPEA169oPmqdEHwE5nYcH+2 x8p4TxqsLkYztWXccJZoCrn8L7Ki1jAq1G++p9euLI3Ek27lIKrLIQD+Z7FIiGBm9O9Q /OeVYS/CQPhebZrZO5F7WJBXaautFEi1YVGMM= MIME-Version: 1.0 Received: by 10.101.130.21 with SMTP id h21mr3061182ann.149.1308350812400; Fri, 17 Jun 2011 15:46:52 -0700 (PDT) Received: by 10.101.133.6 with HTTP; Fri, 17 Jun 2011 15:46:52 -0700 (PDT) Date: Sat, 18 Jun 2011 00:46:52 +0200 Message-ID: Subject: Oneway CXF service having problem with Gemini-Web/Tomcat-catalina From: Aki Yoshida To: dev@cxf.apache.org Content-Type: text/plain; charset=ISO-8859-1 X-Virus-Checked: Checked by ClamAV on apache.org Hi, There seems to be some IO handling problem in oneway CXF services on equinox with the latest gemini-web. It think I have identified the cause of the problem and that we could fix it in CXF. But I would like to get your comments. The problem happens sporadically for oneway services when the StaxInInterceptor tries to instantiate the XMLStreamReader from the InputStream object. In this test scenario, a series of oneway calls are sequentially sent to a CXF oneway service. And sporadically, some calls result in the following exception, that is indicating the input stream is already closed, even though the data should be available in the stream. Caused by: java.lang.RuntimeException: Couldn't parse stream. at org.apache.cxf.staxutils.StaxUtils.createXMLStreamReader(StaxUtils.java:1143) ~[na:na] at org.apache.cxf.interceptor.StaxInInterceptor.handleMessage(StaxInInterceptor.java:105) ~[na:na] ... 27 common frames omitted Caused by: com.ctc.wstx.exc.WstxIOException: Stream closed at com.ctc.wstx.stax.WstxInputFactory.doCreateSR(WstxInputFactory.java:536) ~[na:na] at com.ctc.wstx.stax.WstxInputFactory.createSR(WstxInputFactory.java:585) ~[na:na] at com.ctc.wstx.stax.WstxInputFactory.createSR(WstxInputFactory.java:610) ~[na:na] at com.ctc.wstx.stax.WstxInputFactory.createXMLStreamReader(WstxInputFactory.java:316) ~[na:na] at org.apache.cxf.staxutils.StaxUtils.createXMLStreamReader(StaxUtils.java:1141) ~[na:na] ... 28 common frames omitted Caused by: java.io.IOException: Stream closed at org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:308) ~[na:na] at org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:202) ~[na:na] at org.apache.cxf.transport.servlet.LogServletInputStream.read(LogServletInputStream.java:80) ~[na:na] at com.ctc.wstx.io.BaseReader.readBytes(BaseReader.java:155) ~[na:na] at com.ctc.wstx.io.UTF8Reader.loadMore(UTF8Reader.java:368) ~[na:na] at com.ctc.wstx.io.UTF8Reader.read(UTF8Reader.java:111) ~[na:na] at com.ctc.wstx.io.ReaderBootstrapper.initialLoad(ReaderBootstrapper.java:250) ~[na:na] at com.ctc.wstx.io.ReaderBootstrapper.bootstrapInput(ReaderBootstrapper.java:133) ~[na:na] at com.ctc.wstx.stax.WstxInputFactory.doCreateSR(WstxInputFactory.java:531) ~[na:na] I didn't see this problem with jetty before and started to see this problem sporadically right after switching to gemini-web. It seems that the error has something to do with the way in which its previous call is handled and how the servlet container manages the stream resources. To investigate this situation, I logged CXF's each method call into the HttpServletRequest, HttpServetResponse, ServletInputStream, and ServerOutputStream objects and noticed that the input stream was always closed by a web container's cleanup thread instead of the CXF's servlet thread. In contrast, the output stream was always closed by the CXF servlet thread at AbstractHTTPDestination's close(). In this method, there is an interesting code fragment that explains this particular handling for the oneway case: public void close(Message msg) throws IOException { super.close(msg); if (msg.getExchange() == null) { return; } Message m = msg.getExchange().getInMessage(); if (m == null || msg.getExchange().isOneWay()) { return; } InputStream is = m.getContent(InputStream.class); if (is != null) { try { is.close(); ... The intention of the above code was probably to asynchronously read the input stream later than this point. But if the output stream is closed and the servlet is returned, there is no guarantee that the input stream remains available. So, I think we can close the input stream there. Besides, OneWayProcessorInterceptor is supposed to be pulling in the entire stream data. if (Boolean.FALSE.equals(o)) { //need to suck in all the data from the input stream as //the transport might discard any data on the stream when this //thread unwinds or when the empty response is sent back DelegatingInputStream in = message.get(DelegatingInputStream.class); if (in != null) { in.cacheInput(); } } So, I modified the AbstractHTTPDestination's close method to also close the input stream upon closing the output stream. And it seems that the problem is gone. But I am not 100% sure that this might not be introducing another problem. My hypothesis is that Gemini-web (tomcat-catalina) closes the input stream with some non-deterministic behavior that sporadically causes the input stream of the subsequent call to become closed. I think if tomcat-cataline always closes the input stream right away after the call comes back, it will probably also solve this problem. Should I go ahead to put this change in 2.5 and 2.4.x? Or do you think we should discuss this issue with the tomcat-cataline people? Thanks. Regards, aki