-
|
I intend to implement an audit-log for sensitive changes inside my play application, which is basically just logging but with included context information like "acting user", "remote ip", etc. I am creating a custom immutable context object that includes such values. Now the obvious way to do this with play is to instantiate the context within a Filter and add it to the request as a request attribute, and then pass the request (or just the audit-context) explicitly via method parameters to every method call. This is not really a feasible option for me, because I am not looking to change the method signatures of basically every method inside my codebase just to add an audit-context parameter. Is it an option to use the JDK25 feature ScopedValue for this? Or does play framework's stateless nature make this too error-prone? For example, inside a filter, after all the authn/authz checks have passed, I could do this: final var ctx = new AuditContext.Ctx(...);
return ScopedValue.where(AuditContext.CTX, ctx).call(() -> delegate.call(request));Then in controller methods, or other functions called within, I could access the context with: var ctx = AuditContext.CTX.get();I am not sure how Play Framework handles requests internally once they are flowing through the filters, will it use different threads for the same request if I do not explicitly run asynchronous code? I am aware that once I run asynchronous methods, that I have to pass on a copy of the context explicitly, the same goes for if I am sending messages to actors. In that case, I would of course include the context within the messages sent (if applicable). Btw. I am aware that Play has moved on from using a static request context (I think it was based on ThreadLocal) and instead instructs to pass the request explicitly via method parameters. But as mentioned above, changing all method signatures in my method call stack to include a context is something I want to work around if possible. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 4 replies
-
|
I just realized that this probably won't work inside a filter. But would it work if I was doing it inside the controller methods which handles the request? public Result foo(final Http.Request request) {
final var ctx = new AuditContext.Ctx(...);
return ScopedValue.where(AuditContext.CTX, ctx).call(() -> {
// some code handling the request and returning a result
return ok();
});
} |
Beta Was this translation helpful? Give feedback.
Yes, the code you posted, inside the action method, it's safe to use. It's just a block of code running and as long as you don't switch threads within the action method the code you posted is totally fine and "safe". Only after the action method exits Play takes over again and could internally switch threads. But when you exit the method you also already exited the scope as well. btw, you also need to take care to not switch threads in your
DomainLogicStuffand then try to access the ScopedValue from such a different thread as well of course (but I guess you know that ;)However, instead of writing that code in very a…