If you read filter essentials, there is written:
Modifying the response headers and data. You do this by providing a customized version of the response.
and
A filter that modifies a response must usually capture the response before it is returned to the client. The way to do this is to pass the servlet that generates the response a stand-in stream. The stand-in stream prevents the servlet from closing the original response stream when it completes and allows the filter to modify the servlet's response.
So the explanation is easy:
When you do not call next item in the filter chain, your code will be written and returned to the browser. But when you pass control to the next filter, it will be replaced.
To achieve your effect, you need to:
- call filter chain
- grab final response to StringBuilder
- find the location of HTML table tag
- insert your HTML code
- write modified response
See the linked document for code samples.