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?
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;
}
};
}