After couple of hours of struggling, I’ve finally found the solution.
In short, ContentCachingResponseWrapper.copyBodyToResponse()
should be called in the end of the filter method.
ContentCachingResponseWrapper
caches the response body by reading it from response output stream. So, the stream becomes empty. To write response back to the output stream ContentCachingResponseWrapper.copyBodyToResponse()
should be used.