Hi Andrea, all Created STANBOL-898 [1] for this and provided a fix with revision 1436798 [2]. With the fix the finalize method was removed. Also the StreamSource#getStream() method now returns an wrapper over the parsed stream that ensures that the returned stream can not be closed.
best Rupert [1] https://issues.apache.org/jira/browse/STANBOL-898 [2] http://svn.apache.org/viewvc?rev=1436798&view=rev On Tue, Jan 22, 2013 at 6:03 AM, Rupert Westenthaler <[email protected]> wrote: > Hi Andrea, > > If the ServletContainer does in fact reuse the same InputStream, than > this is absolutely possible. Very good catch! > > > > On Mon, Jan 21, 2013 at 5:13 PM, Andrea Di Menna <[email protected]> wrote: >> Hi, >> >> after commenting out those IOUtils.closeQuietly the problem is not showing >> up (probably not 100% correct - should close the InputStream in getData in >> case of ByteArrayInputStream). > > close() on an ByteArrayInputStream does not have any effect. So this > is not a problem. I am more concerned about users that directly use > the Java API of the Enhancer, because they need to know when they can > safely close the parsed Stream. Because of that I suggest to add the > requirement that the ContentItemFactory needs to fully consume parsed > streams in the create** methods. That ensures that callers can close > the stream after calling the Factory. > >> I am trying to stress the server with some requests (hundreds), but I am >> not getting any exception yet. >> >> regards >> Andrea >> >> 2013/1/21 Andrea Di Menna <[email protected]> >> >>> Hi Rupert, >>> >>> I have been trying to debug the problem a bit. >>> From what I can see the servlet container is recycling the InputStream >>> between requests. >>> To me the problem is in the StreamSource#finalize method and in the >>> StreamSource#getData method. >>> I don't think the stream should be closed since this is a reference to the >>> InputStream provided by the servlet container in ContentItemReader. >>> >>> As per the MessageBodyReader#readFrom contract: >>> >>> entityStream - the InputStream of the HTTP entity. The caller is >>> responsible for ensuring that the input stream ends when the entity has >>> been consumed. The implementation should not close the input stream. >>> >>> When the JVM triggers a GC for an old StreamSource object the InputStream >>> is closed while it is potentially used in another StreamSource object. >>> > > This text indicates that the Server (or Jersey) checks if the stream > is closed after execution. If closed the stream is closed (what might > affect performance). If not closed it can be reused. If this is the > case than the finalise() method would in fact screw up the whole > system as it could result in calls to close after such a check. > >>> What do you think? >>> > > Sounds very reasonable to me. Thanks for looking into that! > best > Rupert > >>> Regards >>> Andrea >>> >>> 2013/1/21 Rupert Westenthaler <[email protected]> >>> >>>> Hi, >>>> >>>> Same here. I only got those when running Stanbol in Tomcat7 (together >>>> with the LMF [1] in my case). Never had such exception when running >>>> the standalone version that uses Jetty (even with the bugs mentioned >>>> above). However I was never able to reproduce this with curl. But if >>>> this is possible it would be great (for debugging). Maybe a Bug in >>>> Jersey with very short texts? I will need to try this myself. >>>> >>>> best >>>> Rupert >>>> >>>> On Mon, Jan 21, 2013 at 12:48 PM, Andrea Di Menna <[email protected]> >>>> wrote: >>>> > Hi Rupert, >>>> > >>>> > thank you very much for your response. >>>> > >>>> > The problem is I am also able to reproduce the error using curl. >>>> > Usually some of those requests fail and then some succeed. >>>> > >>>> > Have you ever reproduced this with Jetty using curl, i.e. not using any >>>> > intermediate client? >>>> > >>>> >> curl -X POST -H "Content-type: text/plain" --data "Paris " >>>> > http://localhost:8080/stanbol/enhancer/chain/dbpedia-keyword >>>> > >>>> > <html><head><title>Apache Tomcat/7.0.21 - Error >>>> report</title><style><!--H1 >>>> > >>>> {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} >>>> > H2 >>>> > >>>> {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} >>>> > H3 >>>> > >>>> {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} >>>> > BODY >>>> > >>>> {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B >>>> > >>>> {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} >>>> > P >>>> > >>>> {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A >>>> > {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> >>>> > </head><body><h1>HTTP Status 500 - </h1><HR size="1" >>>> > noshade="noshade"><p><b>type</b> Exception report</p><p><b>message</b> >>>> > <u></u></p><p><b>description</b> <u>The server encountered an internal >>>> > error () that prevented it from fulfilling this >>>> > request.</u></p><p><b>exception</b> <pre>javax.servlet.ServletException: >>>> > java.io.IOException: Stream closed >>>> > >>>> com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:418) >>>> > >>>> com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537) >>>> > >>>> com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:708) >>>> > javax.servlet.http.HttpServlet.service(HttpServlet.java:722) >>>> > >>>> org.apache.felix.http.base.internal.handler.ServletHandler.doHandle(ServletHandler.java:96) >>>> > >>>> org.apache.felix.http.base.internal.handler.ServletHandler.handle(ServletHandler.java:79) >>>> > >>>> org.apache.felix.http.base.internal.dispatch.ServletPipeline.handle(ServletPipeline.java:42) >>>> > >>>> org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:49) >>>> > >>>> org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:33) >>>> > >>>> org.apache.stanbol.commons.security.auth.AuthenticatingFilter$1.run(AuthenticatingFilter.java:159) >>>> > java.security.AccessController.doPrivileged(Native Method) >>>> > javax.security.auth.Subject.doAsPrivileged(Subject.java:536) >>>> > >>>> org.apache.stanbol.commons.security.auth.AuthenticatingFilter.doFilter(AuthenticatingFilter.java:155) >>>> > >>>> org.apache.felix.http.base.internal.handler.FilterHandler.doHandle(FilterHandler.java:88) >>>> > >>>> org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:76) >>>> > >>>> org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:47) >>>> > >>>> org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:33) >>>> > >>>> org.apache.stanbol.commons.httpqueryheaders.impl.QueryHeadersFilter.doFilter(QueryHeadersFilter.java:75) >>>> > >>>> org.apache.felix.http.base.internal.handler.FilterHandler.doHandle(FilterHandler.java:88) >>>> > >>>> org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:76) >>>> > >>>> org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:47) >>>> > >>>> org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:33) >>>> > >>>> org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:78) >>>> > >>>> org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:47) >>>> > >>>> org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:33) >>>> > >>>> org.apache.felix.http.base.internal.dispatch.FilterPipeline.dispatch(FilterPipeline.java:48) >>>> > >>>> org.apache.felix.http.base.internal.dispatch.Dispatcher.dispatch(Dispatcher.java:39) >>>> > >>>> org.apache.felix.http.base.internal.DispatcherServlet.service(DispatcherServlet.java:67) >>>> > javax.servlet.http.HttpServlet.service(HttpServlet.java:722) >>>> > org.apache.felix.http.proxy.ProxyServlet.service(ProxyServlet.java:60) >>>> > javax.servlet.http.HttpServlet.service(HttpServlet.java:722) >>>> > >>>> org.apache.sling.launchpad.base.webapp.SlingServletDelegate.service(SlingServletDelegate.java:278) >>>> > >>>> org.apache.sling.launchpad.webapp.SlingServlet.service(SlingServlet.java:174) >>>> > </pre></p><p><b>root cause</b> <pre>java.io.IOException: Stream closed >>>> > org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:308) >>>> > >>>> org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:169) >>>> > org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1025) >>>> > org.apache.commons.io.IOUtils.copy(IOUtils.java:999) >>>> > org.apache.commons.io.IOUtils.toByteArray(IOUtils.java:218) >>>> > >>>> org.apache.stanbol.enhancer.servicesapi.impl.StreamSource.getData(StreamSource.java:136) >>>> > >>>> org.apache.stanbol.enhancer.contentitem.inmemory.InMemoryContentItemFactory.createBlob(InMemoryContentItemFactory.java:80) >>>> > >>>> org.apache.stanbol.enhancer.servicesapi.impl.AbstractContentItemFactory.createContentItem(AbstractContentItemFactory.java:121) >>>> > >>>> org.apache.stanbol.enhancer.servicesapi.impl.AbstractContentItemFactory.createContentItem(AbstractContentItemFactory.java:90) >>>> > >>>> org.apache.stanbol.enhancer.jersey.reader.ContentItemReader.readFrom(ContentItemReader.java:261) >>>> > >>>> org.apache.stanbol.enhancer.jersey.reader.ContentItemReader.readFrom(ContentItemReader.java:69) >>>> > >>>> com.sun.jersey.spi.container.ContainerRequest.getEntity(ContainerRequest.java:474) >>>> > >>>> > >>>> > 2013/1/21 Rupert Westenthaler <[email protected]> >>>> > >>>> >> Hi, >>>> >> >>>> >> I think the stacktrace originates from an Stanbol Enhancer request. I >>>> >> know this trace very well, as I have seen it several times. However in >>>> >> all those cases the exceptions where caused by problems with the >>>> >> client side application. Once this was caused by bad Exception >>>> >> Handling on the client side causing the Apache HttpClient to re-use >>>> >> still referenced connections of the ConnectionPool. An other time it >>>> >> was because of wrong "Content-Length" header information causing the >>>> >> server to close the stream early (e.g. if the Bytes written by >>>> >> Charset1 are not the one sent by the client because he uses Charset2). >>>> >> In addition such exceptions might also happen if the client simple >>>> >> cancels the request before all data where sent. >>>> >> >>>> >> This does not mean that there is no problem with Stanbol, but it is >>>> >> very unlikely, as the only think that Stanbol does up to the point >>>> >> where the Exception is thrown is to call 'IOUtils.toByteArray(in)' on >>>> >> the InputStream prased by the JAX-RS MessageBodyReader#readFrom(..) >>>> >> method. >>>> >> >>>> >> best >>>> >> Rupert >>>> >> >>>> >> >>>> >> On Mon, Jan 21, 2013 at 11:52 AM, Andrea Di Menna <[email protected]> >>>> >> wrote: >>>> >> > Hi all, >>>> >> > >>>> >> > I have an issue with the enhancer engine on Tomcat7. >>>> >> > Trying to access a dbpedia entityhub I randomly get error 500 from a >>>> >> > Stanbol instance. >>>> >> > >>>> >> > The tomcat7 error log reports: >>>> >> > >>>> >> > java.io.IOException: Stream closed >>>> >> > at >>>> org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:308) >>>> >> > at >>>> >> > >>>> >> >>>> org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:169) >>>> >> > at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1025) >>>> >> > at org.apache.commons.io.IOUtils.copy(IOUtils.java:999) >>>> >> > at org.apache.commons.io.IOUtils.toByteArray(IOUtils.java:218) >>>> >> > at >>>> >> > >>>> >> >>>> org.apache.stanbol.enhancer.servicesapi.impl.StreamSource.getData(StreamSource.java:136) >>>> >> > at >>>> >> > >>>> >> >>>> org.apache.stanbol.enhancer.contentitem.inmemory.InMemoryContentItemFactory.createBlob(InMemoryContentItemFactory.java:80) >>>> >> > at >>>> >> > >>>> >> >>>> org.apache.stanbol.enhancer.servicesapi.impl.AbstractContentItemFactory.createContentItem(AbstractContentItemFactory.java:121) >>>> >> > at >>>> >> > >>>> >> >>>> org.apache.stanbol.enhancer.servicesapi.impl.AbstractContentItemFactory.createContentItem(AbstractContentItemFactory.java:90) >>>> >> > at >>>> >> > >>>> >> >>>> org.apache.stanbol.enhancer.jersey.reader.ContentItemReader.readFrom(ContentItemReader.java:261) >>>> >> > at >>>> >> > >>>> >> >>>> org.apache.stanbol.enhancer.jersey.reader.ContentItemReader.readFrom(ContentItemReader.java:69) >>>> >> > at >>>> >> > >>>> >> >>>> com.sun.jersey.spi.container.ContainerRequest.getEntity(ContainerRequest.java:474) >>>> >> > >>>> >> > It looks like the InputStream gets closed when Stanbol is trying to >>>> >> create >>>> >> > the ContentItem from the request. >>>> >> > The input text is a very short string. >>>> >> > >>>> >> > My feeling is that the request's InputStream is closed when the >>>> >> > ContentItemFactory is reading it. >>>> >> > >>>> >> > Any suggestion? >>>> >> > >>>> >> > Regards >>>> >> > Andrea >>>> >> >>>> >> >>>> >> >>>> >> -- >>>> >> | Rupert Westenthaler [email protected] >>>> >> | Bodenlehenstraße 11 ++43-699-11108907 >>>> >> | A-5500 Bischofshofen >>>> >> >>>> >>>> >>>> >>>> -- >>>> | Rupert Westenthaler [email protected] >>>> | Bodenlehenstraße 11 ++43-699-11108907 >>>> | A-5500 Bischofshofen >>>> >>> >>> > > > > -- > | Rupert Westenthaler [email protected] > | Bodenlehenstraße 11 ++43-699-11108907 > | A-5500 Bischofshofen -- | Rupert Westenthaler [email protected] | Bodenlehenstraße 11 ++43-699-11108907 | A-5500 Bischofshofen
