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

Reply via email to