private void runChainAndResponseFilters(URI uri, HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
Optional<OneTimeRunnable> responseFilterInvoker =
Optional.ofNullable(jDiscContext.responseFilters.resolve(uri))
.map(responseFilter ->
new OneTimeRunnable(() ->
filterInvoker.invokeResponseFilterChain(responseFilter, uri, request, response)));
HttpServletResponse responseForServlet = responseFilterInvoker
.<HttpServletResponse>map(invoker ->
new FilterInvokingResponseWrapper(response, invoker))
.orElse(response);
HttpServletRequest requestForServlet = responseFilterInvoker
.<HttpServletRequest>map(invoker ->
new FilterInvokingRequestWrapper(request, invoker, responseForServlet))
.orElse(request);
chain.doFilter(requestForServlet, responseForServlet);
responseFilterInvoker.ifPresent(invoker -> {
boolean requestHandledSynchronously = !request.isAsyncStarted();
if (requestHandledSynchronously) {
invoker.runIfFirstInvocation();
}
});
}