I am using Guice\'s RequestScoped and Provider in order to get instances of some classes during a user request. This works fine currently. Now I want to do some job in a bac
I recently solved this exact problem. There are a few things you can do. First, read up on ServletScopes.continueRequest(), which wraps a callable so it will execute as if it is within the current request. However, that's not a complete solution because it won't forward @RequestScoped objects, only basic things like the HttpServletResponse. That's because @RequestScoped objects are not expected to be thread safe. You have some options:
If your entire @RequestScoped hierarchy is computable from just the HTTP response, you're done! You will get new instances of these objects in the other thread though.
You can use the code snippet below to explicitly forward all RequestScoped objects, with the caveat that they will all be eagerly instantiated.
Some of my @RequestScoped objects couldn't handle being eagerly instantiated because they only work for certain requests. I extended the below solution with my own scope, @ThreadSafeRequestScoped, and only forwarded those ones.
Code sample:
public class RequestScopePropagator {
private final Map, Provider>> requestScopedValues = new HashMap<>();
@Inject
RequestScopePropagator(Injector injector) {
for (Map.Entry, Binding>> entry : injector.getAllBindings().entrySet()) {
Key> key = entry.getKey();
Binding> binding = entry.getValue();
// This is like Scopes.isSingleton() but we don't have to follow linked bindings
if (binding.acceptScopingVisitor(IS_REQUEST_SCOPED)) {
requestScopedValues.put(key, binding.getProvider());
}
}
}
private final BindingScopingVisitor IS_REQUEST_SCOPED = new BindingScopingVisitor() {
@Override
public Boolean visitScopeAnnotation(Class extends Annotation> scopeAnnotation) {
return scopeAnnotation == RequestScoped.class;
}
@Override
public Boolean visitScope(Scope scope) {
return scope == ServletScopes.REQUEST;
}
@Override
public Boolean visitNoScoping() {
return false;
}
@Override
public Boolean visitEagerSingleton() {
return false;
}
};
public Callable continueRequest(Callable callable) {
Map, Object> seedMap = new HashMap<>();
for (Map.Entry, Provider>> entry : requestScopedValues.entrySet()) {
// This instantiates objects eagerly
seedMap.put(entry.getKey(), entry.getValue().get());
}
return ServletScopes.continueRequest(callable, seedMap);
}
}