I also had the same problem the first time, then I understood. Thanks to filter, it's possible to create a 'wrapper' around a request/response objects. Filters use wrappers but it's not the other way round. Think of a filter to compress the response. The filter uses the HttpServletResponseWrapper class to actually pass behind the scenes a custom response object whose getOutputStream() method returns a custom output stream in gzip format. It's the filter which knows about the wrapper and not the other way round.