Search code examples
javaplayframework

Before and After request in Play


I am working on an application in Play Framework (2.8) and I am trying to intercept the request to persist some information on the ThreadContext before the request is handled and cleaned up after. To be more precise, I want to read from the session the NDC, put it in the ThreadContext (generate a new one if it does not exist and store it in the session), and after the request is handled clean up.

In Spring I would do this with a HandlerInterceptor that has a preHandle() and postHandle(), however I could not find something similar in Play.

I was looking over HttpRequestHandler and the example provided, but could not really make it work. Is there a correct way of doing this?


Solution

  • Managed to solve the problem using the ActionCreator. I implemented an action creator where I read the cookie from the request. If it is not present, I generate a new NDC. I store the NDC (regardless if it was read from the cookie or generated) in the ThreadContext. I store the result from the delegate call in a seperate variable and, since it is a COmpletionStage, if use thenApply() to add the NDC to the cookie, if it was rpeviously generated. Otherwise I simply return the result. A more detailed article on this here: https://petrepopescu.tech/2021/09/intercepting-and-manipulating-requests-in-play-framework/

    public Action createAction(Http.Request request, Method actionMethod) {
        return new Action.Simple() {
            @Override
            public CompletionStage<Result> call(Http.Request req) {
                CompletionStage<Result> resultCompletionStage;
                boolean ndcWasGenerated = false;
                String ndcStr = null;
    
    
    
                // Get the NDC cookie from the session
                Optional<String> ndc = req.session().get("NDC");
                if (ndc.isPresent()) {
                    ndcStr = ndc.get();
                } else {
                    // Generate a new NDC since no cookie was in the session. This means that it is the first request from this user
                    ndcStr = UUID.randomUUID().toString().replace("-", "");
                    ndcWasGenerated = true;
                }
    
                // Push the NDC in the Thread context
                ThreadContext.push(ndcStr);
    
    
    
                // Go down the call chain and pass the request. Eventually it will reach our controller
                resultCompletionStage = delegate.call(req);
    
    
                // Clean up the ThreadContext
                ThreadContext.pop();
                ThreadContext.clearAll();
    
                if (ndcWasGenerated) {
                    // If we generated the NDC, store it in a session cookie so we can use it for the next calls
                    String finalNdcStr = ndcStr;
                    return resultCompletionStage.thenApply(result -> result.addingToSession(req, "NDC", finalNdcStr));
                }
                return resultCompletionStage;
            }
        };
    }