I have an application that has a form control hit a servlet and then the servlet does some unit of work which then forwards the request to a JSP with a JavaBean carried over in the request. This works fine when I am manually doing things to my application but the minute I use a stress tool to push some "real" work through the application I get a lot of IllegalStateExceptions. I don't understand why this would happen. I have tested this in a servlet which looks to a database for data as well as a servlet that concatenates two strings together and passes the resultant string along with the request. I am using WebSphere on WAS/390 as well as testing on WSAD and I get the same results. Could this be attributed to anything you guys have seen in code? [ January 02, 2003: Message edited by: Mitan Chandihok ]
According to the RequestDispatcher docs, this exception is due to calling forward when some output has already been committed. This could happen if your servlet writes more than the buffer capacity in the response. One solution would be for your servlet to not write anything to the response. Another would be to increase the response buffer size (which must be done before anything is written). Bill
I don't do anything within the servlet, rather I add a bean to the request via request.setAttribute and then call the RequestDispatcher to forward that to a JSP. The buffer size problem could be the thing making my problems occur, but I think I am not understanding the fundamentals of this. When a servlet is being called and it is NOT implementing single thread model, multiple instances of this servlet are used to handle multiple requests simulataneosly. If the servlet forwards responses to a JSP, are multiple instances of the JSP called as well? If so, do these multiple instances share the same buffer? I did try to force the JSP to use single thread by adding <%@ page isThreadSafe="false" %>, but I still get the same IllegalStateException problems when I run load through my application. Just to reiterate, the application works pretty well when I am just clicking through from my browser, but when I run a fairly heavy load I get IllegalStateException's every few times. I also sycronized the method where request.setAttribute is called as to clear all bases.
This is happening because some part of a response has already been sent to the client (i.e. committed) before you attempt to do the forward. This is specifically disallowed by the Servlets spec.
Usually, this comes up because some output has been generated by a JSP page before the <jsp:forward> tag is encountered. Often, the fix is to modify the JSP so that there is no inadvertent whitespace. For example, the following:
<% some scriptlet code %> <% some more scriptlet code %>
contains a blank line, which will be sent to the client, whereas this:
<% some scriptlet code %><% some more scriptlet code %>
I think you may be mistaken, I go from the servlet and use RequestDispatcher to forward the response to a JSP. I don't use jsp:forward tag at all, unless I should be using that in which case can you explain in a little more detail. I understand that nothing should be commited as a response to a request to the client if I am going to forward my request, do you know of anyways that a response is committed? I don't set any header types or even instantiate printwriter. I am trying to adhere to an MVC style of programming and only contain "work related" code in servlets (like number crunching etc. etc.) Thanks.
Here is a stack trace of the errors occurred when running a load: [1/2/03 12:41:52:634 EST] 11c7b616 WebGroup X Servlet Error: Context has not been prepared for next connection: java.lang.IllegalStateException: Context has not been prepared for next connection at com.ibm.servlet.engine.srt.NilSRPConnection.getAttribute(SRTConnectionContext.java:454) at com.ibm.servlet.engine.srt.SRTServletRequest.getAttribute(SRTServletRequest.java(Compiled Code)) at com.ibm.servlet.engine.srt.SRTServletRequest.getAttribute(SRTServletRequest.java(Compiled Code)) at com.ibm.servlet.engine.webapp.HttpServletRequestProxy.getAttribute(HttpServletRequestProxy.java(Compiled Code)) at com.ibm.servlet.engine.webapp.HttpServletRequestProxy.getAttribute(HttpServletRequestProxy.java(Compiled Code)) at com.ibm.servlet.engine.webapp.WebAppRequestDispatcher.dispatch(WebAppRequestDispatcher.java(Compiled Code)) at com.ibm.servlet.engine.webapp.WebAppRequestDispatcher.include(WebAppRequestDispatcher.java:119) at com.bank.ControlServlet.doPost(ControlServlet.java:121) at javax.servlet.http.HttpServlet.service(HttpServlet.java:760) at javax.servlet.http.HttpServlet.service(HttpServlet.java(Compiled Code)) at com.ibm.servlet.engine.webapp.StrictServletInstance.doService(ServletManager.java(Compiled Code)) at com.ibm.servlet.engine.webapp.StrictLifecycleServlet._service(StrictLifecycleServlet.java(Compiled Code)) at com.ibm.servlet.engine.webapp.IdleServletState.service(StrictLifecycleServlet.java(Compiled Code)) at com.ibm.servlet.engine.webapp.StrictLifecycleServlet.service(StrictLifecycleServlet.java(Compiled Code)) at com.ibm.servlet.engine.webapp.ServletInstance.service(ServletManager.java(Compiled Code)) at com.ibm.servlet.engine.webapp.ValidServletReferenceState.dispatch(ServletManager.java(Compiled Code)) at com.ibm.servlet.engine.webapp.ServletInstanceReference.dispatch(ServletManager.java(Compiled Code)) at com.ibm.servlet.engine.webapp.WebAppRequestDispatcher.handleWebAppDispatch(WebAppRequestDispatcher.java(Compiled Code)) at com.ibm.servlet.engine.webapp.WebAppRequestDispatcher.dispatch(WebAppRequestDispatcher.java(Compiled Code)) at com.ibm.servlet.engine.webapp.WebAppRequestDispatcher.forward(WebAppRequestDispatcher.java(Compiled Code)) at com.ibm.servlet.engine.srt.WebAppInvoker.doForward(WebAppInvoker.java:91) at com.ibm.servlet.engine.srt.WebAppInvoker.handleInvocationHook(WebAppInvoker.java:184) at com.ibm.servlet.engine.invocation.CachedInvocation.handleInvocation(CachedInvocation.java:67) at com.ibm.servlet.engine.invocation.CacheableInvocationContext.invoke(CacheableInvocationContext.java:106) at com.ibm.servlet.engine.srp.ServletRequestProcessor.dispatchByURI(ServletRequestProcessor.java:125) at com.ibm.servlet.engine.oselistener.OSEListenerDispatcher.service(OSEListener.java:315) at com.ibm.servlet.engine.http11.HttpConnection.handleRequest(HttpConnection.java:60) at com.ibm.ws.http.HttpConnection.readAndHandleRequest(HttpConnection.java:323) at com.ibm.ws.http.HttpConnection.run(HttpConnection.java(Compiled Code)) at com.ibm.ws.util.CachedThread.run(ThreadPool.java:122)
I had a similar problem and I had to first locate where the problem was (in the servlet or the JSP).
What I would suggest doing is forward to a "Hello World" JSP page from the servlet. I am not sure how complex your JSP is (are you doing includes in it?, forwards..). So to rule out the number of variables I would forward to a Hello World JSP page and go from there.. If that rules out your problem then your JSP is the culprit.
I would also remove any synchronization blocks around request.setAttribute. I am hoping websphere instantiates a thread per httprequest. I know Resin does. If that is the case, then you would not have to synchronize anything which is in the request scope.
I think your going to hate me now. I had private global variables in my servlet to have a global version of request, response, and session variables. I used these throughtout my servlet, and I have used this before. The thing I forgot (its been a while since I have done servlet programming) is that I didn't implement single thread model, wow do I feel dumb. Thanks for your help!
Thanks for the understanding. I have reworked my entire servlet to get rid of "global" request, response, and session objects and pass them all throughtout my doPost method. Maybe you can offer some expertise, but when using a Datasource what I do is do the lookup within the init() method of my servlet and open and close a connection again in my doPost method. Does that sounds like it will take advantage of connection pooling and things of that type?
Yes I did. Basically what I have done is not make Request and Response objects global, anything added or removed from the session is now within a synchronized method and all database access is open'd and closed in the doPost method. Works quite well too. My application wasn't really a useful app, but more to test out our infrastrcuture setup.
A tiny monkey bit me and I got tiny ads:
a bit of art, as a gift, that will fit in a stocking