Using a servlet filter to modify output of a jsp?

H

Harry Bosch

I was wondering if anyone had implemented some sort of filter that
could alter the generated contents of a JSP. What I want to do is
grab the the results of a jsp before it is sent back to the client so
that I can add something to the dom tree. Is this possible?

Thanks,

Harry.
 
O

Oliver Wong

Harry Bosch said:
I was wondering if anyone had implemented some sort of filter that
could alter the generated contents of a JSP. What I want to do is
grab the the results of a jsp before it is sent back to the client so
that I can add something to the dom tree. Is this possible?

Yes.

One simple way to do it is to have the your code fetch the JSP as if it
were a web browser, connecting via HTTP to the local loopbrack address and
everything, and then do whatever modifications you want, and then send that
to the user.

It's sort of like writing a proxy.

- Oliver
 
K

kiranmalla.in

Hi Harry

I think this should be perfectly possible. Haven't tried it though. You
can implement a filter to do such type of stuff. I have implemented a
filter which gives me log information about when the modeler (can be
used to provide the info abt jsp as well) is executed.

A filter would provide you callback methods which you can use to alter
request or response object. So i would assume you want to add some
attribute to the response object before serving it to the client which
should be perfectly possible using a filter. I have used filter to
explicitly set the character encoding to UTF-8 before serving the
response..

Hope this helps!

-Kiran
 
A

Abhijat Vatsyayan

Harry said:
I was wondering if anyone had implemented some sort of filter that
could alter the generated contents of a JSP. What I want to do is
grab the the results of a jsp before it is sent back to the client so
that I can add something to the dom tree. Is this possible?

Thanks,

Harry.
Yes, it will be painful but you should be able to achieve this.

I would suggest following approach (which I have not tried of course
since it is painful).

* Create a proxy implementation of HttpServletResponse interface which
should delegate all method invocations to the underlying
HttpServletResponse object provided by the container. You can write this
using a brute force approach or use java's proxying capability (see
java.lang.reflet.Proxy).

class ProxyHttpServletResponse implements HttpServletResponse
{
private HttpServletResponse proxiedObject ;
// some buffer ..
private ServletOutputStream buffer= new MyServletOutputStream(...) ;
private PrintWriter writer ;
ProxyHttpServletResponse (HttpServletResponse proxiedObject)
{
this.proxiedObject = proxiedObject ;
// You will have to do a better job with encoding!
this.writer = new ......(create using the buffer)
}
public void addCookie(Cookie cookie)
{
this.proxiedObject.addCookie(cookie) ;
}
...
...

}

* Change the implementation of getOutputStream and getWriter methods in
your proxy to return a stream/writer that keeps all the written content
in memory (or cache, file etc. ) and does not send it out.
public PrintWriter getWriter( )
{
return this.writer ;
}
public ServletOutputStream getOutputStream()
{
return buffer;
}

* Make sure you do the appropriate things with methods like
"flushBuffer", "reset" and "resetBuffer" . There may be more
stream/writer handling methods in HttpServletResponse interface.

* When forwarding call from the filter (doFilter method), create a new
HttpServletRequest object using your implementation and use your
implementation in place of container provided object.

doFilter(... )
{
//check and ensure that the types are all OK ..
ProxyHttpServletResponse bufferedResponse = new
ProxyHttpServletResponse ((HttpServletResponse) response) ;
filterChain.doFilter(... , bufferedResponse,...) ;
bufferedResponse.processJSPOutputAndFlush() ;
}

* Finally when the control gets back to you in the filter, you may want
to signal (send a message to) your proxy (servlet response object) to
manipulate the buffered output. Then write the contents to the proxied
HttpServletResponse object that was provided by the container.

void processJSPOutputAndFlush()
{
//do the processing ...
// write the contents to the original HttpServletResponse
objects stream and flush ..
}
 
H

Harry Bosch

Thanks for the reply Abhijat (and everyone else), I think I will go
with your solution. I'll start coding now and see how it goes. FYI,
the reason I am doing this is so I can set up environments for
development, testing, integeration (and production, but this will be
disabled there) and have the contents of the returned HTML altered
based on those configurations. Doing this allows up to have a simple
environment variable set and have the page altered based on that
variable so that developers/testers etc. know which environment they
are working on. This way I don't have to have every page, or what-not,
contain code for this environment aware feature. Hope that explains
it.

If anyone has tackled this issue more easily, let me know. Perhaps I
am making this a bit too complicated, but when it's running, it seems
like it could work nicely. Though, a bit of processing, but that is
only in the non-production environments.
 
H

Harry Bosch

After looking through the API docs I did find a convenient decorator
for wrapping a servlet response:
javax.servlet.http.HttpServletResponseWrapper. This way I only need to
override a couple methods to handle what I needed to do. It's
basically the pattern that you, Abhijat, were pointing me at. I was
going the actual java.lang.reflect.Proxy route but I came across this
and figured I would just "get it over with".

Thanks again.
 

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

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top