Re: setHeader after DoFilter delegation in filter?
Thanks for the responses. The reason we need to look at the response before setting a header value is to support a dynamic caching behavior, where the caching determination is made after examining the response and what database interactions are made as a result of building the response. So, I took your advice and implemented a responsewrapper object. This worked in buffering the response, however a new problem cropped up. I think it's mine--but I found out that I need to also buffer the header values and commit these to the response as well. Still looking at my source though. Thanks all! Pid-2 wrote: André Warnier wrote: Hi. I found an approximative example for you, here : http://www.javafaq.nu/java-example-code-237.html (searching Google for HttpServletResponseWrapper example If I remember well, what you want to achieve is : depending on the response content that the webapp generates, you would like to set a response header. This response header has to be set of course, before the first byte of output content is sent to the browser. Before your webapp is going to send this first byte, it will need to get some form of output stream to write the byte to. It will do that using one of the methods available to webapps to get such an output stream, which I identify as either getOutputStream or getWriter. I suspect it will rather depend on the type of processing the OP is trying to do on the output, maybe he can enlighten us? So what you probably need to do in your wrapper, is to override these two methods, so that when the servlet calls one of them, you can return your own version of it instead of the regular one. In this way, later your wrapper can sit in the middle when the webapp starts writing to its output, and you can examine this output before forwarding it to the real servlet output stream. Of course before you forward the output there, you will have determined which header you want to add and sent it out. Andre is making the point that the processing could be done inside the wrapper, rather than in the filter - which is only there to allow you to wrap the response. Not very easy, and over my current capacities. As above, depends on the type of processing required... the use of a ByteArrayOutputStream may be a simple way of buffering the response for example. p Unfortunately the example I provided above is a bit of a cheat, because all it has to do is replace the original stream by a compressed one, for which there is apparently already a convenient class available. One of the important elements maybe, is how much of the output you need to see in order to determine which header to add. If it is just the first few bytes, then I suppose you could buffer this in memory until you have enough, send out your header, and then set a flag so that subsequent servlet writes happen as transparently as possible. If it is the whole response and it can be big, then you might have to buffer the entire response to disk before setting your header, and then re-read the original response and sending it out yourself. slioch wrote: Sorry all--I'm still stumped. Tried the suggestions and here's what I found. I've subclass HttpServletResponseWrapper and overloaded the following methods: public void flushBuffer(); public void sendRedirect(String str); public void sendError(int sc); public void sendError(int sc, String msg); in my new response wrapper. These methods have been disabled while processing is in the scope of my filter (I also record if these methods are called). I've replaced the response object with my new wrapper: public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws java.io.IOException, javax.servlet.ServletException { ResponseWrapper resp = new ResponseWrapper((HttpServletResponse)(res)); And I've found that sendError(), sendRedirect(), and flushBuffer() are not being called while in the processing is in the scope of my filter. In other words the filter looks something like: dofilter(ServletRequest req, ServletResponse res, FilterChain fc) { ResponseWrapper resp = new ResponseWrapper((HttpServletResponse)(res)); //resp.isCommitted() returns false //some processing work //resp.isCommitted() returns false; fc.doFilter(req,resp); //resp.isCommitted() returns TRUE //some more process work return; } If I know that sendError(), sendRedirect(), and flushBuffer() are not being called how would response be sent (provided autoflush is false and the buffer size is large enough for the print writer). Thanks for the help (and patience)! mike Caldarale, Charles R wrote: From: André Warnier [mailto:[EMAIL PROTECTED] Subject: Re: setHeader after DoFilter delegation in filter? To create output for the client, the application calls something, right? (I mean a method of HttpRequest). Not quite - you're confusing
Re: setHeader after DoFilter delegation in filter?
Thanks much for the responses. I understand. It makes sense to use HttpServletRequestWrapper, but there are no methods in HttpServletRequestWrapper or HttpServletRequest that initiates the sending of the response back to the client. So, by subclassing HttpServletRequest there doesn't appear to be any way to suppress the sending on the response back to the client (until I've completed processing). What I would like to do is to prevent the response from being sent back to the client until my filter has completed it's processing (and this is after my filter delegates the doFilter() call to the other filters). Mike Pid-2 wrote: André Warnier wrote: slioch wrote: [...] I'll risk an explanation here.. I think maybe the issue is a misunderstanding of how a servlet filter works. It took me a while too, but I think I've got it in the end. Sorry if this is level 101, that's my own level. What was confusing to me at first, is that this is different from, for instance, Apache input and output filters. There there is a clear distinction between an input filter, which sees all the data on the way in to the application, and an output filter, which sees all the data that the application produces, before it goes out to the browser. An input filter and and output filter are two separate pieces of code, and you can install them independently. In the Java servlet view of things, a filter is a wrapper, within which the other filters and the webapp run. It's like an onion : your filter is the outer layer, within which there are possibly further layers (other filters), and at the center is the webapp. When your filter calls doFilter(), it executes all its inner layers in one go. The bummer is that, unless you take pains to change that, each of these layers has a direct access to the output buffers, which live outside the onion. So unless you prevent them from doing that, they will start putting bytes there, and by the time your doFilter() returns, it's too late to change that. When you execute doFilter(), in fact you execute, at that point, all the further filters that are in the chain, and the webapp at the deepest level. If any of these starts sending output, then by the time the doFilter() returns, that output is already past your filter, and there is nothing you can do anymore to modify it. If you want something else to happen, then you have to do something like this : - in your filter, subclass the HttpRequest, say as myHttpRequest. In this subclass, redefine the methods that the underlying filters and webapp will (presumably) use to send output to the buffer. In these redefined methods, you can then do whatever you want to transform what the application sends out via these methods. - then, instead of passing the original HttpRequest to the doFilter(), pass your own myHttpRequest instance of it. Close enough; the spec has some stuff that covers this type of problem, so I'd recommend investigating: javax.servlet.http.HttpServletRequestWrapper javax.servlet.http.HttpServletResponseWrapper (hereafter HSRsW) Using the latter should allow you to modify the appropriate header. HSRsW wrappedHres = new HttpServletResponseWrapper(hres); chain.doFilter(hreq, wrappedHres); Where your HSRsW contains appropriate code to modify the header, perhaps in the construction phase. p This way, whenever the application thinks it is just using the (say) HttpRequest.setHeader() method, it is in fact using *your* myHttpRequest.setHeader() method, in which you can catch and pervert whatever you want, before passing it on to the real HttpRequest.setHeader() method. The point is, if you let any underlying (from the point of your filter) other filter or webapp call i.e. the original setHeader(), then that's it : that line of output is now already in the HTTP output buffer queue, and by the time your doFilter() returns, it no longer can claw it back. - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] -- View this message in context: http://www.nabble.com/setHeader-after-DoFilter-delegation-in-filter--tp19862960p19925786.html Sent from the Tomcat - User mailing list archive at Nabble.com. - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: setHeader after DoFilter delegation in filter?
Sorry all--I'm still stumped. Tried the suggestions and here's what I found. I've subclass HttpServletResponseWrapper and overloaded the following methods: public void flushBuffer(); public void sendRedirect(String str); public void sendError(int sc); public void sendError(int sc, String msg); in my new response wrapper. These methods have been disabled while processing is in the scope of my filter (I also record if these methods are called). I've replaced the response object with my new wrapper: public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws java.io.IOException, javax.servlet.ServletException { ResponseWrapper resp = new ResponseWrapper((HttpServletResponse)(res)); And I've found that sendError(), sendRedirect(), and flushBuffer() are not being called while in the processing is in the scope of my filter. In other words the filter looks something like: dofilter(ServletRequest req, ServletResponse res, FilterChain fc) { ResponseWrapper resp = new ResponseWrapper((HttpServletResponse)(res)); //resp.isCommitted() returns false //some processing work //resp.isCommitted() returns false; fc.doFilter(req,resp); //resp.isCommitted() returns TRUE //some more process work return; } If I know that sendError(), sendRedirect(), and flushBuffer() are not being called how would response be sent (provided autoflush is false and the buffer size is large enough for the print writer). Thanks for the help (and patience)! mike Caldarale, Charles R wrote: From: André Warnier [mailto:[EMAIL PROTECTED] Subject: Re: setHeader after DoFilter delegation in filter? To create output for the client, the application calls something, right? (I mean a method of HttpRequest). Not quite - you're confusing request with response. There are methods in HttpServletResponse - an Interface, not a class - to obtain a PrintWriter or ServletOutputStream that the webapp uses to generate data to be sent to the client at some point in the future. The data isn't sent until flushBuffer(), sendError(), or sendRedirect() are called. Since the HttpServletResponseWrapper class implements the interface, those methods are available via the wrapper. The filter needs to subclass the wrapper in order to subvert anything else in the filter/servlet chain. - Chuck THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers. - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] -- View this message in context: http://www.nabble.com/setHeader-after-DoFilter-delegation-in-filter--tp19862960p19929361.html Sent from the Tomcat - User mailing list archive at Nabble.com. - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: setHeader after DoFilter delegation in filter?
Thanks for the response Christopher. Unfortunately I need to set a value in the header after the doFilter() delegation. The reason is that header valuedepends on the result of the page rendering. So, if autoflush is disabled and the buffer size is not exceeded for the page shouldn't a setHeader() call made after the doFilter() call be able to set the value in the response header? Or, to put it another way, does the j2ee spec (or tomcat design) always start sending the response to the client when the page is rendered (after the last filter has been executed in a filter chain), or after the filterchain has completed its processing? Mike Christopher Schultz-2 wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Michael, Michael Larson wrote: I'm debugging a tomcat filter. The filter has been designed as follows: MyFilter::DoFilter(ServletRequest request, ServletResponse response, FilterChain chain) { do_some_stuff(); //now delegate the call the chain chain.DoFilter(); //the header value below doesn't always show up at the client response.setHeader(post-filter,true); } This might not work because the response could have been committed. If the response buffer is filled, then the headers will be sent back to the client. If you come along later and try to set a header, you'll get an exception. For the jsp page being accessed I've turned off AutoFlush (via a server side directive). However, I'm still seeing this page (if it exceeds a certain size but well below the jspwriter buffer size) will be sent back to the client before the response header has been modified. I'm not sure about autoFlush, but it may be that you're hitting a hard buffer limit and the data is being sent, anyway. If AutoFlush is turned off for the jsp page and the page doesn't exceed the buffer size can it still send the response back to the client before the filter chain has completed (and in this example before the header has been modified)? Is it a bad idea to modify the response header after the call to chain.DoFilter()? It's much better to do it up front if you can. Why do you need the header to be set after the fact? If you really must do this, you can always do your own buffering by wrapping the request along with your own OutputStream/Writer that buffers itself. The version of tomcat is v5.5.23, and no exceptions are thrown when the setHeader call is made. That's interesting that no exceptions are thrown. :( - -chris -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.9 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkjrrxwACgkQ9CaO5/Lv0PAKdwCfbEXaoIj5cnMLIYZciiEXcAL8 0TMAn0CWqgdA8qQNsZwDabIQHbRHPoqY =Gqzj -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] -- View this message in context: http://www.nabble.com/setHeader-after-DoFilter-delegation-in-filter--tp19862960p19912296.html Sent from the Tomcat - User mailing list archive at Nabble.com. - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]