-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Micheal,

Your comment about calling getResponse().getOutputStream() and ignoring
the result got me to thinking...

You know what? I just realized that I've been leading you down the wrong
path: you must manage the buffers separately because of the "you can
only call either getOutputStream OR getWriter" rule.

I think you can still make it work with a unified buffer, but you have
to be more careful. Let's be less careful and more straightforward.

Basically, you'll have to duplicate your efforts to wrap the Writer the
same way you did the OutputStream: create a WriterWrapper and cache that
information. I'd recommend using a StringWriter as a backing class,
since you don't have to worry too much about the character encoding at
that point (because Writers always use characters, not bytes).

Anyhow, you definitely /should/ call getResponse().getOutputStream() (or
getWriter(), whichever the case may be) when your getOutputStream()
method is invoked: you definitely want the state handling to be done by
the wrapped request, because you never know what has happened to the
request before your filters gets its hands on it.

Keep reading for more.

Michael Ludwig wrote:
>> So, when this code is called from an "include" call to the request
>> dispatcher, it doesn't appear in your filter's captured output? Or, it
>> doesn't appear in the final response sent to the browser (or both)?
> 
> Both.

Okay, but only when using Writer, right? OutputStream works properly?

>> You might want to flush() before close() but that shouldn't matter too
>> much.
> 
> Closing the stream would flush it, wouldn't it?

It should, but it doesn't hurt to be tidy. I seem to remember C library
routines that would truncate output if you didn't explicitly flush the
buffers.

>> You could even add a method to your wrapper that will tell you which
>> style of output is being used on the response: output stream versus
>> writer. Then, you could avoid the try/catch which will make your code
>> run a bit faster. Faster filters are always better than slow ones ;)
> 
> Try/catch can't be that much of a problem, can it? Isn't it just a fancy
> way of conditional branching with information attached? As a language
> feature, I assume it doesn't entail a performance hit?

See Chuck's response for performance considerations. IMO, since you have
the opportunity to avoid the exception, you may as well take it.

>>>  // http://marc.info/?l=tomcat-user&m=109913615025298
>>>  public void flushBuffer() throws IOException {
>>>   this.buffer.flush();
>>>  }
>> Flushing a ByteArrayOutputStream doesn't do anything. What you really
>> want to do is flush all the OutputStream and Writer objects you've
>> created when calls to getOutputStream and getWriter come in.
> 
> Okay.

Oh, and then call getResponse().flushBuffer(), too. The caller expects
that the flush goes all the way back to the real client response.

>>>  public void write( byte[] b) throws IOException {
>>>   new Throwable().printStackTrace();
>>>   this.buffer.write( b);
>>>  }
>> Do you get stack traces printing from this method?
> 
> No.
> 
>>>  public void write( byte[] b, int off, int len) throws IOException {
>>>   new Throwable().printStackTrace();
>>>   this.buffer.write( b, off, len);
>>>  }
>> How about this one?
> 
> Yes.

That's good. I guess the caller is preferring to use sections of a byte
buffer instead of just a bare one. That's not surprising, and shouldn't
itself be an indication of a problem. If you look at the code for
DefaultServlet, you probably will see calls to write(byte[], int, int)
and none to write(byte[]).

> Thanks for this suggestion [of using TeeOutputStream]. My intent is simply to 
> understand servlets.
> On hitting this include oddity, I just decided to track it down,
> thinking I would learn from it. (Which I'm doing thanks to your help.)

Learning is always good. Hopefully you'll lurk on the list from here on
out. :)

>> So, can you walk me through what actually happens when you use this,
>> again? I think we've become lost in the details.
> 
> Yes, a lot of details. I'm going to report back with a revised version
> based on your suggestions, and probably further investigation.
> 
> The problem is manifest in that the file included via
> RequestDispatcher.include() and then processed by Tomcat's
> DefaultServlet does not appear in either the buffer substituted
> in my response wrapper nor the output when the output method
> chosen is PrintWriter rather than ServletOutputStream. With SOS,
> everything seems to work fine.

Okay, good. I think my first suggestion (stop using a unified buffer) is
the right way to do things: you'll handle each type of output strategy
separately and I believe you'll have better results. You should post
your entire filter next time, if only so André can see it ;)

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkklfMwACgkQ9CaO5/Lv0PC9jACgrgIZad3hhYirKE2UsSQOmU09
U9MAnjpquAJb5pXh3ehBvVBtMOgYGlqC
=840h
-----END PGP SIGNATURE-----

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

Reply via email to