Sometimes we have a set of variables attached to the request. For example userId or requestId. We need these variables very often, at the API level, at the service level, at the repository level or at the logging service. It is not practical to pass these variables as method parameters.
It is a good idea to create UserContext bean. What variables can be stored there?
- userId – The unique identification of the user after authentication. If the userId is present, we trust this value.
- requestId – Each request gets a unique identification. Then we can easily track all calls, from API level to final error with the stacktrace.
- authorizationMethod – We can distinguish if the request comes from API or it is our internal call.
- testMode – We can distinguish if it is a normal call, or call from automated tests. We can behave differently – for example, we do not send emails during performance tests.
- and others you need..
Someone might consider using SpringBoot request Bean with SCOPE_REQUEST. Do not use it. Firstly, it’s magic how it works. There is a hidden proxy bean and you can run into troubles. Secondly, you will not be able to use this bean outside of web requests – for example in the asynchronous processing or network calls.
In asynchronous processing, we need to have access to the original UserContext. This is very important – all backend code can run in the same way – as a direct call from API, or indirect from the queue.
The UserContext is created when a new request comes to our backend. Then we can attach UserContext to the current thread and use it in our backend. If there is some asynchronous processing, we can serialize the user context. When needed, we can deserialize UserContext back and attach it to the thread that is different than the original one.