4

Suddenly stuck on generating custom servlet response. I want to replace servlet response with predefined one:

public class MyCustomResponse extends HttpServletResponseWrapper {
  private String customOutput;
  public MyCustomResponse(String customOutput, HttpServletResponse response) {
    super(response);
    // PrintWriter and Outputstream should stream this variable as output
    this.customOutput = customOutput;
  }

  //
  // Below I need to override something
  //
}

and filter code snipped as follows:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  //
  //
  MyCustomResponse customResponse = new MyCustomResponse("Hello world!", (HttpServletResponse) response);
  chain.doFilter(request, customResponse);
}

Shame on me, but i'm really stuck on coding this simple task :(

Any help would be appreciated.

UPDATE:

All I want is to implement custom response wrapper which, once it's put into filter chain, would always respond with some predefined text. I know how to write custom data from within doFilter() method, but I want MyCustomResponse to be responsible for that - just instantiate and put in chain. Any well-reasoned responses "You cant do that because..." are also welcome.

4 Answers 4

2

As quoted in one of your comments :

"I want my custom response to return a string in response to getWriter or getOutputStream method invocation"

For that, you have to provide your own implementation for getWriter() & getOutputStream() by overriding them.

//---

    private PrintWriter printWriter = null;
    private ServletOutputStream outputStream = null;

    public PrintWriter getWriter( ) throws IOException {

        if (this.outputStream != null) {
            throw new IllegalStateException(
                    "Cannot call getWriter( ) after getOutputStream( )");
        }

        if (this.printWriter == null) {
            // initialize printWriter
        }
        return this.printWriter;
    }

    public ServletOutputStream getOutputStream( ) throws IOException {

        if (this.printWriter != null) {
            throw new IllegalStateException(
                "Cannot call getOutputStream( ) after getWriter( )");
        }

        if (this.outputStream == null) {
            // initialize outputStream
        }
        return this.outputStream;
    }

//---
2
  • sorry, but neither ByteArrayOutputStream nor PrintWriter initializations with predefined String are possible that way, they just do not get compiled.
    – andbi
    Commented Jan 17, 2011 at 14:44
  • @Osw : yes, but I have provided sample-code so it definitely needs some modification, but the idea behind it remains same. Commented Jan 17, 2011 at 15:08
1

I am sorry, but

  1. it is not clear what is your problem. You code is written, so? It does not work? what exactly does not work?
  2. Why do you want to do this? The "right" solution is to pass information as session attribute.
  3. I do not believe this can work. Really, you do not call directly the next filter in chain. You are kindly asking the app. server to do this. And you are not expected to replace the servlet request/response by your own. Use method explained above (#2)
2
  • code is not written, I want my custom response to return a string in response to getWriter or getOutputStream method invocation.
    – andbi
    Commented Jan 17, 2011 at 12:22
  • and, actually I AM EXPECTED to replace requests/responses with my own implementations, that's the reason why servlet filters and wrappers classes exist.
    – andbi
    Commented Jan 17, 2011 at 12:32
1

Your response wrapper is useless as is, since it only stores a string in the Java object used to model the actual HTTP response.

The actual HTTP response that the client receives is the stream of bytes (resp. characters) sent via the output stream (resp. writer) of the HttpServletResponse object (and the headers, cookies, etc. stored in the HttpServletResponse object). If you want to send a custom output string to the client, just use response.getWriter().print("Hello worlds!").

Passing the response to the rest of the filter chain is questionable, since the rest of the chain will probably want to add its own data to the response stream.

If you want to hard-code the response to send to the client to your custom output, but be able to still pass the response to the chain and ignore whatever the rest of the chain puts in the response, you could try to add the following to your wrapper :

private ServletOutputStream fakeOutputStream = 
    new ServletOutputStream() {

        @Override
        public void write(int b) throws IOException {
            // do nothing. Everything written to this stream is ignored
        }
    }

private PrintWriter fakeWriter = new PrintWriter(fakeOutputStream);

public MyCustomResponse(String customOutput, HttpServletResponse response) {
    super(response);
    response.getWriter().print(customOutput);
}

@Override
public ServletOutputStream getOutputStream() {
    return fakeOutputStream;
}

@Override
public PrintWriter getWriter() {
    return fakeWriter;
}
4
  • Actually there are many other things I do in doFilter, so it's not useless. Why can't I code my own wrapper, override getServletOutputStream() so it'd automatically return that string as response without doing it in doFilter method?
    – andbi
    Commented Jan 17, 2011 at 12:28
  • I didn't say that your filer was useless. I said that your response wrapper was. You didn't override neither getOutputStream(), nor getWriter(). So could you explain what you really want to do with this wrapper? Why don't you simply write your custom output to the stream writer?
    – JB Nizet
    Commented Jan 17, 2011 at 13:10
  • agree, my question might seem a bit vague or misleading, overriding these methods was the real problem, question updated.
    – andbi
    Commented Jan 17, 2011 at 14:17
  • If I understand correctly, you want the response sent to the client to be your custom string, but you want to be able to pass the response to the chain and make sure that whatever is written to the response by the rest of the chain is completely ignored. If that's right, then I'll update my answer to tell you how I think you could do that.
    – JB Nizet
    Commented Jan 17, 2011 at 15:54
0

I don't see the reason of what you want to do, but if you want to use your wrapper, my suggestion would be:

Create your own servlet that uses your wrapper and register it in web.xml, in something like this:

  • Extend javax.servlet.GenericServlet and override the service(ServletRequest, ServletResponse) method. Then you use the Template Method pattern to create a service(ServletRequest, ServletResponseWrapper). OR
  • Extend javax.servlet.HttpServlet and override service(HttpServletRequest, HttpServletResponse) method. Use the Template Method pattern to create a service(HttpServletRequest, HttpServletResponseWrapper). This will require that you don't use the doGet, doPost, doPut, doTrace methods already provided by HttpServlet but, instead create your own that uses your wrapper.

Hope this helps.

Not the answer you're looking for? Browse other questions tagged or ask your own question.