tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Michael Ludwig <mil...@gmx.de>
Subject Filter and ServletResponseWrapper obligations
Date Mon, 24 Nov 2008 03:35:29 GMT
This is both Tomcat 5.5.27 and 6.0.18. (And also Jetty 6.1.18.)

Consider the following servlet code:

  PrintWriter out = res.getWriter();
  ...
  out.println( "<p>before include</p>");
  rd = context.getRequestDispatcher( "/include.html");
  // contains <p>included HTML</p>
  rd.include( req, res);
  out.println( "<p>after include</p>");
  out.flush();
  out.close();

This displays alright.

  before include
  included HTML
  after include

But then, this is without any filters. Let's add a filter.

  included HTML
  before include
  after include

This is wrong. The output order is mangled. What happened?

In this case the included file "/include.html" is processed by Tomcat's
DefaultServlet. Let's try the same code with a JSP, "/include.jsp".

  before include
  included JSP
  after include

This works correctly, with or without the filter. Why does it work
with a JSP and not with an HTML page? Obviously, these are processed
differently. But how exactly?

I can make the included HTML page display correctly even in the face
of my filter by adding the following statement directly before the
include();

  out.flush();

But is it the servlet's obligation to flush() the buffer before doing an
include? The documentation for RequestDispatcher doesn't say anything to
that effect.

I can also make the included HTML page display correctly despite the
filter by resorting to res.getOutputStream() instead of res.getWriter()
in my servlet code. But it should work either way, shouldn't it?

Let's scroll back a little. What filter did I set up that provoked
this odd behaviour? The filter is trivial, I don't think it matters.
The decisive issue seems to be what's going on in the subclass of
HttpServletResponseWrapper which is a helper to the filter.

 public ServletOutputStream getOutputStream() throws IOException {
  // getResponse().getOutputStream();
  return this.stream;
 }

 public PrintWriter getWriter() throws IOException {
  // getResponse().getWriter();
  return this.writer;
 }

You see there are calls to the underlying response object, which are
commented out. When I comment these lines back in, everything works
fine. No need to flush the buffer before the include, to resort to SOS
instead of PW, or to JSP instead of HTML.

So these calls on the underlying object seem to have something to do
with the behaviour observed. Can anyone explain what's going on?

Note the problem is manifest only for all of the following conditions:

* include() of a static HTML file via DefaultServlet;
* output done using the PrintWriter;
* no flush() on the buffer prior to the include();
* addition of a filter lacking calls to the underlying response
  object in getOutputStream() and getWriter().

Another way of putting this is probably: What is the contract the
Filter and the ServletResponseWrapper have to fulfill in order to be
well-behaved Tomcat citizens? Or, for that matter, web container
citizens? What are their obligations?

Is this contract documented? Alright, I found the spec.

http://jcp.org/aboutJava/communityprocess/mrel/jsr154/index2.html

But I haven't read it yet :-) So if anyone wants to comment ...

Thanks,

Michael Ludwig

---------------------------------------------------------------------
To start a new topic, e-mail: users@tomcat.apache.org
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Mime
View raw message