Ad

How To Handle Response Before Commit In Spring Boot FilterHandlerFunction

- 1 answer

We are in the process of migrating an old spring application to spring boot 2.0.

Currently we have an interceptor which executes as first in the chain and does followings:

  • Sets a unique id in ThreadLocal
  • Before response is committed, the unique id is removed from the thread local.

I am trying to figure out a way to implement this in Spring WebFlux. I am able to do it using WebFilter implementation; however, since I am using RouterFunction as controller, I was trying to check if there's a way to achieve this through HandlerFilterFunction.

public class TxIdFilter implements HandlerFilterFunction<ServerResponse, ServerResponse> {
  /**
   * {@inheritDoc}
   */
  @Override
  public Mono<ServerResponse> filter(ServerRequest request, HandlerFunction<ServerResponse> next) {
    /*
     * How to achieve following (which can be done
     * using WebFilter)
     * 
     * exchange.getResponse().beforeCommit(() -> {
     *   logger.debug("Cleaning up the tx id...");
     *   AppTransactionContext.removeAll();
     *   return Mono.empty();
     * });
     */
    return next.handle(request);
  }
}
Ad

Answer

Here is how you can do it, although I'm here using a request attribute for that:

public class SampleFilterFunction implements HandlerFilterFunction {

    @Override
    public Mono filter(ServerRequest request, HandlerFunction next) {
        request.attributes().put("key", "value");
        return next.handle(request)
                .doOnSuccessOrError((value, error) -> request.attributes().remove("key"));
    }
}

You should not rely on ThreadLocal here, because unlike with the Servlet Spring MVC model, a request is not tied to a particular thread. Request processing can hop to a different thread at any given time.

Reactor provides a Context API for those uses cases.

Depending on your actual use case (I'm not sure what this transaction ID might mean here), you can also take a look at Spring Cloud Sleuth and Micrometer and how they solve that problem in their own respective use case.

Ad
source: stackoverflow.com
Ad