I'm having some problems following the Guice wiki documentation for using RequestScope (https://code.google.com/p/google-guice/wiki/ServletModule#Using_RequestScope).
I am trying to set up an application where I have a request-scoped ExecutorService. My use case is patterned off the example in the documentation - I've tried to include other relevant classes for completeness.
The main difference is that I am instantiating an instance of ExecutorService within the Filter rather than pulling a literal value out of the request parameters:
@Singleton
public class ExecutorServiceScopingFilter implements Filter {
public ExecutorService getExecutor() {
return Executors.newFixedThreadPool(10, ThreadManager.currentRequestThreadFactory());
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
ExecutorService executor = getExecutor();
HttpServletRequest httpRequest = (HttpServletRequest) req;
httpRequest.setAttribute(Key.get(ExecutorService.class).toString(), executor);
chain.doFilter(req, resp);
}
...
}
In my servlet module I bind the filter:
public class MyServletModule extends ServletModule {
@Override
protected void configureServlets() {
filter("/*").through(ExecutorServiceScopingFilter.class);
...
}
}
And I install the module as normal in my servlet context listener (I've set up the web.xml to use the guice filter and the below listener):
public class MyServletContextListener extends GuiceServletContextListener {
@Override
protected Injector getInjector() {
Injector injector = Guice.createInjector(
Stage.PRODUCTION,
new MyServletModule(),
new MyExampleModule(),
...
);
}
}
I declare the provider in an un-scoped POJO:
class MyExampleImpl implements IMyExample
{
@Inject
protected Provider<ExecutorService> executorProvider;
...
}
Which I bind in a module (and is a parameter of the createInjector call in my listener above):
public class MyExampleModule extends AbstractModule {
@Override
protected void configure() {
bind(IMyExample.class).to(MyExampleImpl.class);
}
}
When I start my web app, I get the following exception:
com.google.inject.CreationException: Guice creation errors:
1) No implementation for java.util.concurrent.ExecutorService was bound. while locating com.google.inject.Provider for field at com.example.MyExampleImpl.executorProvider(MyExampleImpl.java:12) at com.example.ExampleModule.configure(ExampleModule.java:23)
1 error
I have found a related question that indicates the use of a bogus binding (Guice: Cannot inject annotated type in Request scope). The example given is:
bind(String.class)
.annotatedWith(Names.named("name"))
.toProvider(Providers.<String>of(null));
I tried this for binding the ExecutorService and get a null for the provider (so the injector is returning the declared binding instead of using the binding defined by the filter). The use of a bogus binding is never mentioned in the official documentation.
So a few questions to try and solve this problem and understand a bit more about how Guice operates:
Do I need an explicit binding other than setting the attribute (in contrast to the Guice documentation)?
If so, do I need to bind anything using the @RequestScope annotation?
Do I need to make a provider that implements Provider?
Inspecting an @Inject Injector object, I do not see the request-scoped binding for ExecutorService in the binding maps. Should I see this binding?
Inspecting the requestScopeContext thread local variable in the ServletScope class at runtime, I do see the ExecutorService binding. This indicates that the binding is working, so I am not doing something (or doing something incorrectly) to access it.
You don't need any values from the request to create the executor service, so you don't need a filter. Just create a provider method in one of your modules
@Provides @RequestScoped
ExecutorService provideExecutor() {
return Executors.newFixedThreadPool(
10, ThreadManager.currentRequestThreadFactory());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With