I have noticed that when I create a new thread using the request thread factory provided by GAE then the new thread has the same Environment as the parent thread. (The identityHashCode of the current environment is the same in both threads.)
On the one hand, this is nice because the newly created thread starts with the same context as the parent. The problem is that the Environment is not immutable. It contains the ".currentNamespace" attribute which is used in namespace handling. If one of the threads changes the current namespace it is applied on all threads which is clearly not what I want.
My idea to fix this was that I created an own Environment implementation and when a new thread is created I copy the content of the current environment into this new environment and set this environment as current on the new thread. So the new thread starts with the same context but it can independently change later.
This solution worked during initial testing but then I run into a problem
Caused by: java.lang.ClassCastException: MyEnvironmentImplementation cannot be cast to com.google.apphosting.runtime.ApiProxyImpl$EnvironmentImpl
at com.google.apphosting.runtime.ApiProxyImpl.log(ApiProxyImpl.java:67)
I have no access to the code of com.google.apphosting.runtime.ApiProxyImpl but it is clear that this method tries to cast the interface it received into its own implementation class without checking the type.
I find this strange because there is a void setEnvironmentFactory(ApiProxy.EnvironmentFactory factory) in the ApiProxy so it is expected that someone might use a different implementation of the Environment interface than the default one.
Is there another way to use different namespaces in different request threads?
Is this unchecked casting considered a bug or is it fundamentally wrong to use my own Environment implementation?
I use app engine standard with 1.9.84 of the java sdk.
Edit: It is actually documented that "This should not be used from user-code." on the ApiProxy.setEnvironmentForCurrentThread() and ApiProxy.setEnvironmentFactory() methods. So my suggested workaround is not expected to work. You shouldn't try something like it either.