Social Groups

You may use request and response wrappers to extend the functionality of request or response objects. For instance, we can provide an extra layer of buffer using a wrapper with its own internal buffer independent of the output stream supplied by the container. We can pass this to other components and once we finally verify the content, then we can write it into containers output stream and thus actually committing the response.

Using filters you can pass a wrapper to a servlet without modifying the servlet. We can also add and remove the filter without touching the target servlet at all. You can also pass in our custom wrapper to a RequestDispatcher forward and include, as you seen in a previous demo. However then you will have to modify the target servlet also as you have seen. Wrappers were used along with RequestDispatcher before the addition of filters to the Java EE specification. After the addition of filters to the servlet specification, wrappers should be now used with filters than directly with servlets using RequestDispatcher mechanism.

Setting up the basic servlet

We will reuse the same FirstServlet and ForwardedServlet from our RequestDispatcher basic demo. We will rename our FirstServlet to FirstServletV2. We will also need to change the url-pattern, the java file name, constructor name.

In FirstServletV2, we will remove the initial getWriter part as we will be using an outputstream later and we cannot call both getWriter and getOutputStream.

In FirstServletV2, you may remove or comment out the RD for include, and uncomment both the forwards. We will also add a request attribute to keep a count of the number of forwards we do.

Similarly we will ForwardedServlet to ForwardedServletV2 to get and print the value of the new request attribute.

The doGet of FirstServletV2 will now look like:

System.out.println("FirstServletV2.doGet");

RequestDispatcher rd2 = getServletContext().getRequestDispatcher(

"/ForwardedServletV2");

request.setAttribute("CallNumber", "1");

rd2.forward(request, response);

request.setAttribute("CallNumber", "2");

rd2.forward(request, response);

The doGet of ForwardedServletV2 will now look like:

System.out.println("ForwardedServletV2.doGet");

PrintWriter out = response.getWriter();

out.println("<br>ForwardedServlet.doGet"

+ request.getAttribute("CallNumber"));

Now try deploying and executing the class. We are trying to forward twice and we will get the exception in the console log:

java.lang.IllegalStateException: Cannot forward after response has been committed

Creating our wrapper class

We will now create a wrapper class to override the default buffer with one of our own. We will override the below methods in our custom wrapper:

void flushBuffer() – We will not provide any implementation and hence the next component will not be able to write any data to the client.

PrintWriter getWriter() – We will create and return our own writer object and hence the next component will not be able to write directly to the response stream.

OutputStream getOutputStream() – We will create and return our own output stream.

We will also extend ServletOutputStream to create our own ServletOutputStream so that we can instantiate it within the getOutputStream above to provide our own output stream. We will override only its abstract write method to write to our own output stream.

ServletOutputStream has added two new methods isReady() and setWriteListener(WriteListener) servlet spec 3.1 (Java EE 7). We will simply implement them and provide no code. However if you are using a lower version of servlet spec, then you don’t need to implement these.

The code is very similar to the demo using RD that we seen before. We will create an instance of our wrapper class and pass it instead of original response. Since a filter's doFilter() method signature has ServletResponse, you will first need to cast it to an HttpServletResponse before you create the wrapper instance. You will also need this casted reference later to get the output stream. After calling chain.doFilter, we are adding code to actually write it to the client along with some error handling.

Now deploy and execute our servlet and you will get the output in the browser as:

Previously this would have been thrown an error in the console. We can also now decide to send an error to client even after data is written to output. Previously exception would have been thrown only in the console after sending some data as after the data was written to the original output stream, there was no way to tell the client about the error.

You are here

This is a personal technical blog where we share our understanding on various concepts and is neither an official page or documentation for the products described here, nor the official views of the companies we work with.

Keywords used in this website are trademarks of their respective owners. This website is not affiliated with Oracle™ and/or any of the JEE frameworks like Spring™, Struts™, Hibernate™ and JSF™.

All contents and materials are provided freely without any warranty or liability and nothing within the site should be considered as professional advice. In any doubt, please ask, and we will try to help you based on our knowledge. Please let us know if you feel anything is not right here (including any copyright violation) and we will act upon it as fast as we can.