May 17

request.getInputStream(): Tomcat vs. Weblogic

At work I had a weird problem the other day. The product I am working on is a web application - deployed as a .war archive. We usually use a Tomcat (5.5 or 6.0) servlet container and everything works fine: We have POST requests and append byte data to it. We keep a request open and put as many bytes in it as we want (of course this depends on the use case). Now for a client we had to deploy the application on an Oracle Weblogic Server (version 10.3) and found an interesting problem. I will only be talking about the server side code and can't publish the whole application, sorry about that.

  1. How it works using Tomcat

    So on the server side we use the ServletInputStream of a HttpServletRequest of a standard servlet. On that InputStream we receive data using request.getParameter("param1"); and keep calling the is.read(target, transferred , size - transferred); method to read the appended data from InputStream. Once that data was read into a byte[] we write this array to an OutputStream.

  2. What happens using Weblogic

    Everything is done using the standard javax.servlet.* classes, no Tomcat specific classes so we thought this should work on Weblogic, too. But we were wrong. After I spent a (long) while debugging the problem I found that on Weblogic, once you have accessed some methods (not quite sure which ones) request object you can no longer read from the InputStream. It seems to me that Weblogic marks the request as totally processed after reading a request, parameter for example: request.getParameter("param1"); (this one is for sure causing the not readability of the InputStream). So once we read the parameter that we needed for further processing we weren't able to read the data appended to the POST request using is.read(target, transferred , size - transferred); anymore.

  3. How we got it to work using Weblogic

    To solve this problem we now don't put the "param1" value as a parameter, we now put it in the request header. Accessing the header value request.getHeader("param1"); leaves the InputStream the way we expected it so we are able to read the appended data.

  4. Question

    Maybe someone can answer the question, why are Weblogic and Tomcat handling this differently?

But hey, we got it working. Not even Weblogic was able to stop us. If anything in this post is not clear and you would like to help clarify this but need more information please feel free to contact me or post a comment here.

Update:

Thanks to @royvanrijn I got an explanation for the behaviour described above:

The description for the ServletRequest.getParameter(String) method in the Servlet Specification 2.5 contains the following paragraph:

...If the parameter data was sent in the request body, such as occurs with an HTTP POST request, then reading the body directly via getInputStream() or getReader() can interfere with the execution of this method...

Knowing this, it makes perfectly sense that the two servlet containers act differently on the same method. What does this mean for us? We'll probably use a header to get the required parameter and not read it from the request body.