tomcat: possible to write a copy of the response to a file

E

eunever32

For the purposes of remembering what was browsed,

is it possible to have a servlet/jsp write a copy

of its response to a file? (as well as to the browser)

In other words the HttpServletResponse would write to

both a file and the browser!
 
?

=?ISO-8859-1?Q?Karl_=D8ie?=

Well yes, you can write to a buffer and afterwards write that buffer
both to the httpresponse and to file.

// make buffer
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintWriter pw = new PrintWriter(out);

// write content
pw.println("<blink><font size=1000>hey</font></blink>");

//output to file
OutputStream file_pw = new FileOutputStream(new File(""));
file_pw.write(out.toByteArray());

//output to http response
httpResponse.getWriter(out.toByteArray());

Karl Øie
 
E

eunever32

Not bad idea but that would require knowing the entire servlet output
in advance.

Not really possible with jsp?
 
R

Robert Klemme

For the purposes of remembering what was browsed,

is it possible to have a servlet/jsp write a copy

of its response to a file? (as well as to the browser)

In other words the HttpServletResponse would write to

both a file and the browser!

This is a genuine case for a filter. That filter creates a proxy of the
response and hands it down the processing chain. This proxy object then is
responsible for writing to the file and writing to the original response.
You may need to also create a proxy for the ServletOutputStream or the
Writer.

See
http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/Filter.html
http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/ServletResponse.html

Kind regards

robert
 
R

Roedy Green

so how do you do it

A servlet is just java. It can do pretty well anything a normal java
program can do, so long as it is quick about it, and the security
manager has not been programmed to interfere. There are several
plausible ways:

1. it writes it to a database as a character blob.

2. it creates a file and writes it.

3. it hands it to a static method of a logging class that enqueues it
for dumping to disk by a separate low-priority thread. see
http://mindprod.com/jgloss/queue.html
 
E

eunever32

Based on your suggestion I tried the code below.

But what seems to be happening is that response.<n> is written as hoped
but the response to the browser fails with
java.lang.IllegalStateException: Cannot forward after response has been
committed

So it's as if the response is used up and unavailable a second time?


class CharResponseWrapper extends
HttpServletResponseWrapper {
private CharArrayWriter output;
public String toString() {
return output.toString();
}
public CharResponseWrapper(HttpServletResponse response){
super(response);
output = new CharArrayWriter();
}
public PrintWriter getWriter(){
return new PrintWriter(output);
}
}

public class MyFilter
implements Filter
{
private FilterConfig filterConfig = null;
private String authorisedGroup = null;

private static int count = 0;
public void doFilter(ServletRequest request, ServletResponse
response, FilterChain chain)
throws IOException, ServletException
{

String sRequest =
((HttpServletRequest)request).getRequestURI();
this.count++;


try{

CharResponseWrapper wrapper = new
CharResponseWrapper((HttpServletResponse)response);
chain.doFilter(request, wrapper);
CharArrayWriter caw = new CharArrayWriter();
caw.write(wrapper.toString());
FileWriter fOut = new FileWriter("d://tmp//response." +
count);
fOut.write(caw.toString());
fOut.close();
chain.doFilter(request, response);
}
catch(IOException e)
{
System.out.println("Exception");
}
}
 
R

Robert Klemme

Based on your suggestion I tried the code below.

But what seems to be happening is that response.<n> is written as
hoped but the response to the browser fails with
java.lang.IllegalStateException: Cannot forward after response has
been committed

So it's as if the response is used up and unavailable a second time?

Your code has these problems:

- you invoke the filter chain twice while you should only once

- you don't deal with binary output (there are two streams available via
ServletResponse)

- (minor) you do a lot of conversions to String - this is inefficient.

Regards

robert
 
E

eunever32

I took out type typo "chain.doFilter()" in the previous so that there
is just one ie

CharResponseWrapper wrapper = new
CharResponseWrapper((HttpServletResponse)response);
CharArrayWriter caw = new CharArrayWriter();
caw.write(wrapper.toString());
FileWriter fOut = new FileWriter("d://tmp//response." +
count);
fOut.write(caw.toString());
fOut.close();
chain.doFilter(request, response);

Now however I get a browser response but nothing is written to the disk
(?)

I don't really understand the point about two streams: I would have
thought there was just
one stream which could contain both character and binary data.

An attempt to write binary data to a char file might result in
incorrect data but should
still work I would have thought.

It looks to me that until the response is closed we don't have anything
in "caw"
which brings me back to my first point: can we write a response stream
more than once?
 
R

Robert Klemme

I took out type typo "chain.doFilter()" in the previous so that there
is just one ie

CharResponseWrapper wrapper = new
CharResponseWrapper((HttpServletResponse)response);
CharArrayWriter caw = new CharArrayWriter();
caw.write(wrapper.toString());
FileWriter fOut = new FileWriter("d://tmp//response." +
count);
fOut.write(caw.toString());
fOut.close();
chain.doFilter(request, response);

Now however I get a browser response but nothing is written to the
disk (?)

I don't really understand the point about two streams: I would have
thought there was just
one stream which could contain both character and binary data.

Look at the interface of ServletResponse. You have to deal with both cases.
An attempt to write binary data to a char file might result in
incorrect data but should
still work I would have thought.

It looks to me that until the response is closed we don't have
anything in "caw"
which brings me back to my first point: can we write a response stream
more than once?

Looks like you threw out the wrong filter chain invocation. Try a little
harder. You'll also have to take into consideration that there are
response headers etc. which in your case will be written directly to the
original output stream. You need to override a lot more methods than you
did to handle all these cases. Read the docs and invest more time. You'll
almost certainly learn a lot useful stuff about how Java web applications
work.

Kind regards

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,444
Messages
2,571,709
Members
48,796
Latest member
Greg L.
Top