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.