You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@myfaces.apache.org by Claudio Tasso <ta...@libero.it> on 2006/02/19 10:09:13 UTC

ExtensionsFilter does not seem to be THREAD SAFE

Hi,
using Tomahawk I experimented some problems with the ExtensionFilter, in 
particular some errors occur when the MyFaces javascript is written 
inside the body of the response.
This is the typical error message:

java.lang.StringIndexOutOfBoundsException
    at java.lang.StringBuffer.insert(StringBuffer.java:905)
    at 
org.apache.myfaces.renderkit.html.util.DefaultAddResource.writeMyFacesJavascriptBeforeBodyEnd(DefaultAddResource.java:658)
    at 
org.apache.myfaces.component.html.util.ExtensionsFilter.doFilter(ExtensionsFilter.java:138)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) - 
Developer Preview 
4].server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:699)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) - 
Developer Preview 
4].server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:397)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) - 
Developer Preview 
4].server.http.HttpRequestHandler.doProcessRequest(HttpRequestHandler.java:833)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) - 
Developer Preview 
4].server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:430)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) - 
Developer Preview 
4].server.http.HttpRequestHandler.serveOneRequest(HttpRequestHandler.java:216)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) - 
Developer Preview 
4].server.http.HttpRequestHandler.run(HttpRequestHandler.java:119)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) - 
Developer Preview 
4].server.http.HttpRequestHandler.run(HttpRequestHandler.java:112)
    at 
oracle.oc4j.network.ServerSocketReadHandler$SafeRunnable.run(ServerSocketReadHandler.java:215)
    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) - 
Developer Preview 
4].util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:303)
    at java.lang.Thread.run(Thread.java:534)

This error occurs randomly. Looking at the AddResourceFactory code, I 
see that only one AddResource instace exists and this instance is shared 
among  the servlet threads.
The ExtensionFilter calulates the beforeBodyEndPosition value  (which is 
a DefaultAddResource property) and then this value is used for writing 
inside a StringBuffer which should contain the response body.
This is the code in ExtensionFilter the I'm talking about:

 addResource.parseResponse(extendedRequest, extendedResponse.toString(),
                    servletResponse);

addResource.writeMyFacesJavascriptBeforeBodyEnd(extendedRequest,
                    servletResponse);


The problem is that a typical race condition seems to happen.
The beforeBodyEndPosition value is calulated for Thread1, which is 
suspended. Then, Thread 2 starts and it modifies the 
beforeBodyEndPosition value. When Thread2 terminates, Thread1 resumes 
and it tries to write inside its body response at an index which is no 
more valid.

The reason of this behaviour is (according to me) the following: there 
is just one instance of DefaultAddResource,  so the execution of  
AddResource.parseResponse and 
AddResource.writeMyFacesJavascriptBeforeBodyEnd should be atomic.

Please, let me know your opinions.





Re: ExtensionsFilter does not seem to be THREAD SAFE

Posted by Claudio Tasso <ta...@libero.it>.
Ok, I'm going to create a JIRA issue.

Martin Marinschek ha scritto:

>Yes, that is true.
>
>Bruno?
>
>regards,
>
>Martin
>
>On 2/19/06, Claudio Tasso <ta...@libero.it> wrote:
>  
>
>>Hi,
>>using Tomahawk I experimented some problems with the ExtensionFilter, in
>>particular some errors occur when the MyFaces javascript is written
>>inside the body of the response.
>>This is the typical error message:
>>
>>java.lang.StringIndexOutOfBoundsException
>>    at java.lang.StringBuffer.insert(StringBuffer.java:905)
>>    at
>>org.apache.myfaces.renderkit.html.util.DefaultAddResource.writeMyFacesJavascriptBeforeBodyEnd(DefaultAddResource.java:658)
>>    at
>>org.apache.myfaces.component.html.util.ExtensionsFilter.doFilter(ExtensionsFilter.java:138)
>>    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) -
>>Developer Preview
>>4].server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:699)
>>    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) -
>>Developer Preview
>>4].server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:397)
>>    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) -
>>Developer Preview
>>4].server.http.HttpRequestHandler.doProcessRequest(HttpRequestHandler.java:833)
>>    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) -
>>Developer Preview
>>4].server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:430)
>>    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) -
>>Developer Preview
>>4].server.http.HttpRequestHandler.serveOneRequest(HttpRequestHandler.java:216)
>>    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) -
>>Developer Preview
>>4].server.http.HttpRequestHandler.run(HttpRequestHandler.java:119)
>>    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) -
>>Developer Preview
>>4].server.http.HttpRequestHandler.run(HttpRequestHandler.java:112)
>>    at
>>oracle.oc4j.network.ServerSocketReadHandler$SafeRunnable.run(ServerSocketReadHandler.java:215)
>>    at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) -
>>Developer Preview
>>4].util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:303)
>>    at java.lang.Thread.run(Thread.java:534)
>>
>>This error occurs randomly. Looking at the AddResourceFactory code, I
>>see that only one AddResource instace exists and this instance is shared
>>among  the servlet threads.
>>The ExtensionFilter calulates the beforeBodyEndPosition value  (which is
>>a DefaultAddResource property) and then this value is used for writing
>>inside a StringBuffer which should contain the response body.
>>This is the code in ExtensionFilter the I'm talking about:
>>
>> addResource.parseResponse(extendedRequest, extendedResponse.toString(),
>>                    servletResponse);
>>
>>addResource.writeMyFacesJavascriptBeforeBodyEnd(extendedRequest,
>>                    servletResponse);
>>
>>
>>The problem is that a typical race condition seems to happen.
>>The beforeBodyEndPosition value is calulated for Thread1, which is
>>suspended. Then, Thread 2 starts and it modifies the
>>beforeBodyEndPosition value. When Thread2 terminates, Thread1 resumes
>>and it tries to write inside its body response at an index which is no
>>more valid.
>>
>>The reason of this behaviour is (according to me) the following: there
>>is just one instance of DefaultAddResource,  so the execution of
>>AddResource.parseResponse and
>>AddResource.writeMyFacesJavascriptBeforeBodyEnd should be atomic.
>>
>>Please, let me know your opinions.
>>
>>
>>
>>
>>
>>    
>>
>
>
>--
>
>http://www.irian.at
>
>Your JSF powerhouse -
>JSF Consulting, Development and
>Courses in English and German
>
>Professional Support for Apache MyFaces
>
>  
>


Re: ExtensionsFilter does not seem to be THREAD SAFE (Again Urgent!!)

Posted by Martin Marinschek <ma...@gmail.com>.
+1

regards,

Martin

On 2/23/06, Mario Ivankovits <ma...@ops.co.at> wrote:
> Hi!
>
> Sorry for all my "urgent" mails, but I address them so only if I really
> think it IS urgent. ;-)
>
> > Yes, that is true.
> >
> This turned out to be a serious problem here.
>
> Not only the java.lang.StringIndexOutOfBoundsException problem, but also
> that it might deliver the content of another request in another session.
>
> This is due to the fact that the response buffer will be passed into
> DefaultAddResource which stores it in a member "originalResponse".
> At this moment it is possible that another request for the same context
> will pick up this content.
>
> And guess what, this is what we have here 3-5 times the day.
>
> Looking in DefaultAddResource makes me wonder why it has to be a context
> singleton?
> It is a rather lightweight class and it should be not that a performance
> loss if we simple instantiate it per request.
> Also we can get rid of the request attributes like HEADER_BEGIN_INFO....
> as then the whole class is request scoped.
>
> If it is due to the fact that it is hard to find the correct constructor
> I'll propose to add a setContextPath(String) to the AddResource interface.
> That way we can use the default constructor and simply set the context path.
>
> After "green light" from you I'll do it that way.
>
> Ciao,
> Mario
>
>


--

http://www.irian.at

Your JSF powerhouse -
JSF Consulting, Development and
Courses in English and German

Professional Support for Apache MyFaces

Re: ExtensionsFilter does not seem to be THREAD SAFE (Again Urgent!!)

Posted by Mario Ivankovits <ma...@ops.co.at>.
Hi!

Sorry for all my "urgent" mails, but I address them so only if I really
think it IS urgent. ;-)

> Yes, that is true.
>   
This turned out to be a serious problem here.

Not only the java.lang.StringIndexOutOfBoundsException problem, but also
that it might deliver the content of another request in another session.

This is due to the fact that the response buffer will be passed into
DefaultAddResource which stores it in a member "originalResponse".
At this moment it is possible that another request for the same context
will pick up this content.

And guess what, this is what we have here 3-5 times the day.

Looking in DefaultAddResource makes me wonder why it has to be a context
singleton?
It is a rather lightweight class and it should be not that a performance
loss if we simple instantiate it per request.
Also we can get rid of the request attributes like HEADER_BEGIN_INFO....
as then the whole class is request scoped.

If it is due to the fact that it is hard to find the correct constructor
I'll propose to add a setContextPath(String) to the AddResource interface.
That way we can use the default constructor and simply set the context path.

After "green light" from you I'll do it that way.

Ciao,
Mario


Re: ExtensionsFilter does not seem to be THREAD SAFE

Posted by Martin Marinschek <ma...@gmail.com>.
Yes, that is true.

Bruno?

regards,

Martin

On 2/19/06, Claudio Tasso <ta...@libero.it> wrote:
> Hi,
> using Tomahawk I experimented some problems with the ExtensionFilter, in
> particular some errors occur when the MyFaces javascript is written
> inside the body of the response.
> This is the typical error message:
>
> java.lang.StringIndexOutOfBoundsException
>     at java.lang.StringBuffer.insert(StringBuffer.java:905)
>     at
> org.apache.myfaces.renderkit.html.util.DefaultAddResource.writeMyFacesJavascriptBeforeBodyEnd(DefaultAddResource.java:658)
>     at
> org.apache.myfaces.component.html.util.ExtensionsFilter.doFilter(ExtensionsFilter.java:138)
>     at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) -
> Developer Preview
> 4].server.http.ServletRequestDispatcher.invoke(ServletRequestDispatcher.java:699)
>     at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) -
> Developer Preview
> 4].server.http.ServletRequestDispatcher.forwardInternal(ServletRequestDispatcher.java:397)
>     at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) -
> Developer Preview
> 4].server.http.HttpRequestHandler.doProcessRequest(HttpRequestHandler.java:833)
>     at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) -
> Developer Preview
> 4].server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:430)
>     at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) -
> Developer Preview
> 4].server.http.HttpRequestHandler.serveOneRequest(HttpRequestHandler.java:216)
>     at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) -
> Developer Preview
> 4].server.http.HttpRequestHandler.run(HttpRequestHandler.java:119)
>     at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) -
> Developer Preview
> 4].server.http.HttpRequestHandler.run(HttpRequestHandler.java:112)
>     at
> oracle.oc4j.network.ServerSocketReadHandler$SafeRunnable.run(ServerSocketReadHandler.java:215)
>     at com.evermind[Oracle Containers for J2EE 10g (10.1.3.0.0) -
> Developer Preview
> 4].util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:303)
>     at java.lang.Thread.run(Thread.java:534)
>
> This error occurs randomly. Looking at the AddResourceFactory code, I
> see that only one AddResource instace exists and this instance is shared
> among  the servlet threads.
> The ExtensionFilter calulates the beforeBodyEndPosition value  (which is
> a DefaultAddResource property) and then this value is used for writing
> inside a StringBuffer which should contain the response body.
> This is the code in ExtensionFilter the I'm talking about:
>
>  addResource.parseResponse(extendedRequest, extendedResponse.toString(),
>                     servletResponse);
>
> addResource.writeMyFacesJavascriptBeforeBodyEnd(extendedRequest,
>                     servletResponse);
>
>
> The problem is that a typical race condition seems to happen.
> The beforeBodyEndPosition value is calulated for Thread1, which is
> suspended. Then, Thread 2 starts and it modifies the
> beforeBodyEndPosition value. When Thread2 terminates, Thread1 resumes
> and it tries to write inside its body response at an index which is no
> more valid.
>
> The reason of this behaviour is (according to me) the following: there
> is just one instance of DefaultAddResource,  so the execution of
> AddResource.parseResponse and
> AddResource.writeMyFacesJavascriptBeforeBodyEnd should be atomic.
>
> Please, let me know your opinions.
>
>
>
>
>


--

http://www.irian.at

Your JSF powerhouse -
JSF Consulting, Development and
Courses in English and German

Professional Support for Apache MyFaces