Looks like you could just use Modules.override [1]: install(Modules.override(new BlueModule()).with(new MyExecutorServiceModule()));
[1] http://google-guice.googlecode.com/svn/trunk/javadoc/com/google/inject/util/Modules.html#override(com.google.inject.Module...) Though, it would have been nice if BlueModule's author hadn't so rudely bound ExecutorService, since that makes it hard on users of his library. When releasing code externally I apply annotations to bindings of common classes from the JDK or other libraries so that users don't get these unpleasant surprises. -Marshall On Apr 26, 2013, at 11:54 AM, Matthew Madson <[email protected]> wrote: > Let's say I'm developing an application which uses a service to do something > totally awesome. > > public class MyAppModule extends PrivateModule { > bind(AwesomeService.class).to(AwesomeServiceImpl.class); > expose(AwesomeService.class); > } > > Now the particular implementation of my AwesomeService needs a few things to > be as awesome as it is: > > class AwesomeServiceImpl implements AwesomeService { > @Inject > AwesomeServiceImpl(BlueService blue, RedService red, ExecutorService > executor) { ... } > } > > It just so happens that some upstanding internet denizen has created a > standalone jar with guice modules that provide both Red and Blue Services. So > I'll add the jar to my classpath and modify MyAppModule so that my > AwesomeService can use the third pary Red and Blue Services: > > public class MyAppModule extends PrivateModule { > install(new RedModule()); > install(new BlueModule()); > bind(AwesomeService.class).to(AwesomeServiceImpl.class); > expose(AwesomeService.class); > } > > I also need an ExecutorService for my AwesomeService, so I'll go ahead and > bind to an explicit instance for now: > > public class MyAppModule extends PrivateModule { > install(new RedModule()); > install(new BlueModule()); > bind(ExecutorService.class).toInstance(Executors.newSingleThreadExecutor()); > bind(AwesomeService.class).to(AwesomeServiceImpl.class); > expose(AwesomeService.class); > } > > Ah, but damn, apparently my good internet friend decided to expose not only > the RedService and BlueService bindings that my AwesomeService needs, but > also an ExecutorService that I don't want: > > public final class BlueModule extends PrivateModule { > bind(ExecutorService.class).toInstance(Executors.newCachedThreadPool()); > bind(BlueService.class).to(BlueServiceImpl.class); > > expose(ExecutorService.class); > expose(BlueService.class); > } > > public final class RedModule extends PrivateModule { > bind(ExecutorService.class).toInstance(Executors.newCachedThreadPool()); > bind(RedService.class).to(RedServiceImpl.class); > > expose(ExecutorService.class); > expose(RedService.class); > } > > No problem, I'll just wrap his modules in a private module and expose only > the services I care about: > > public class MyAppModule extends PrivateModule { > install(new PrivateModule() { > install(new RedModule()); > expose(RedService.class); > }); > install(new PrivateModule() { > install(new BlueModule()); > expose(BlueService.class); > }); > bind(ExecutorService.class).toInstance(Executors.newSingleThreadExecutor()); > bind(AwesomeService.class).to(AwesomeServiceImpl.class); > expose(AwesomeService.class); > } > > Ahh, but damn again, my ExecutorService binding is inherited by my private > wrapper modules and is conflicting with the internal bindings defined in the > RedModule and BlueModule. I guess I could annotate or Name my ExecutorService > in my AwesomeService constructor, but what if I want that ExecutorService to > be a singleton shared all over my app, by 20, 30 or 40 different services. > I'll have to pollute all my ExecutorService injections with this annotation. > > Or I suppose I could do some trickery, staggering the bindings and hiding the > ExecutorService so it doesn't conflict with the ExecutorService that > RedModule and BlueModule need, but this just seems wrong: > > public class MyAppModule extends PrivateModule { > install(new PrivateModule() { > install(new RedModule()); > expose(RedService.class); > }); > install(new PrivateModule() { > install(new BlueModule()); > expose(BlueService.class); > }); > > final Module myAppExecutorService = new PrivateModule() { > > bind(ExecutorService.class).toInstance(Executors.newSingleThreadExecutor()); > expose(ExecutorService.class); > }; > install(new PrivateModule() { > install(myAppExecutorService); > bind(AwesomeService.class).to(AwesomeServiceImpl.class); > expose(AwesomeService.class); > }); > expose(AwesomeService.class); > } > > This seems like a common problem one would have using guice. Am I missing > something here? What is the best practice for this use case? > > Any assistance would be greatly appreciated! > > Minor Notes: > > - the configure method declaration was elided in all modules shown > - BlueModule and RedModule are intentionally marked final, so extending and > overriding the expose method is not a viable solution to the problem > > > -- > You received this message because you are subscribed to the Google Groups > "google-guice" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > Visit this group at http://groups.google.com/group/google-guice?hl=en. > For more options, visit https://groups.google.com/groups/opt_out. > > -- You received this message because you are subscribed to the Google Groups "google-guice" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/google-guice?hl=en. For more options, visit https://groups.google.com/groups/opt_out.
