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.


Reply via email to