How to implement the "robot legs" use case with Google Guice? - java

I'm learning Google Guice. Do you know how to implement the "robot legs" problem? Let me explain this with an example.
Let's say that I have some class called Service:
#Singleton
public class Service {
#Inject
Source source;
}
The interface Source has two implementations:
public class SourceDatabase implements Source {
}
public class SourceFileSystem implements Source {
}
My module is implemented like this:
public class MyModule extends AbstractModule {
#Override
protected void configure() {
bind(Service.class).asEagerSingleton();
}
}
Well, I would like to know if this is possible:
public class MainClass {
#Inject #SomeAnnotation("database")
Service serviceWithADatabaseSource;
#Inject #SomeAnnotation("file-system")
Service serviceWithAFileSystemSource;
}
Does exist some annotation or binding that let me do that, let me annotate a member like serviceWithADatabaseSource, and this helps Guice to know that the internal member source should be injected with the SourceDatabase implementation?
Edit: Thanks to Daniel Martin, for give us the name of this kind of problem on his comment.

As documented in the Guice Wiki, you need to install two PrivateModules, each of which exposes a Service with the right annotation for you.
public class MyModule extends AbstractModule {
#Override
protected void configure() {
install(new PrivateModule() {
#Override public void configure() {
// Bind Source to SourceDatabase.
bind(Source.class).to(SourceDatabase.class);
// Bind #Named("database") Service to Service.
bind(Service.class).annotatedWith(Names.named("database"))
.to(Service.class);
// Now expose #Named("database") Service without exposing
// either of the other two conflicting bindings.
expose(Service.class).annotatedWith(Names.named("database"));
}
});
install(new PrivateModule() {
#Override public void configure() {
// Same as above.
bind(Source.class).to(SourceFileSystem.class);
bind(Service.class).annotatedWith(Names.named("file-system"))
.to(Service.class);
expose(Service.class).annotatedWith(Names.named("file-system"));
}
});
}
}
If the modules were not PrivateModule instances, those bindings to Source and Service would conflict with one another. However, instead, each binding inherits all the public bindings from the Injector but only exposes the #Named(...) Service to the outside world. This way the same Service implementation can inject the same non-annotated Source but have it return different fully-injected types.
Also note that you will not be able to ask for a Source or Service (without an annotation) outside of the PrivateModules, because you haven't established a binding in any non-private Module. This should be expected: The PrivateModule bindings shouldn't conflict with any public bindings, and without entering through one of the PrivateModule's exposed bindings, Guice won't know which Source or Service to return.
Finally, given that Module instances can take constructor parameters, it may be a good idea to extract the two anonymous inner PrivateModules into a named equivalent:
public class MyModule extends AbstractModule {
#Override
protected void configure() {
install(new SourcePrivateModule(SourceDatabase.class, "database"));
install(new SourcePrivateModule(SourceFileSystem.class, "file-system"));
}
}

Related

Guice specify modules to use for injection

In my application there are multiple modules binding something to a specific name or class. Is there a way to tell Guice, which modules it should use when resolving the dependencies to inject.
My simplified dependency graph looks something like this where blue indicates classes from module 1 and red indicates classes from module 2. Now I want to create two instances from the A class, but with different classes bound to some dependencies.
public class Module1 extends AbstractModule {
#Override
protected void configure() {
bind(C.class).to(C_Impl1.class)
bind(D.class).to(D_Impl1.class)
}
}
public class Module2 extends AbstractModule {
#Override
protected void configure() {
bind(C.class).to(C_Impl2.class)
bind(D.class).to(D_Impl2.class)
}
}
public class Application {
#Inject #UseModules(Module1, ...) private final A someClassUsingImpl1;
#Inject #UseModules(Module2, ...) private final A someClassUsingImpl2;
public void doSomethingWithImpl1() {
someClassUsingImpl1.doSomething()
}
public void doSomethingWithImpl2() {
someClassUsingImpl2.doSomething()
}
}
This is the problem private modules were built for. You will still need to use a binding annotation to differentiate whether you're asking for the Impl1 version of A or the Impl2 version of A.
/** Marks Impl1 classes. Inject #Impl1 A to get A using C_Impl1 and D_Impl1. */
#BindingAnnotation
#Retention(RetentionPolicy.RUNTIME)
#interface Impl1 {}
/** Marks Impl2 classes. Inject #Impl2 A to get A using C_Impl2 and D_Impl2. */
#BindingAnnotation
#Retention(RetentionPolicy.RUNTIME)
#interface Impl2 {}
/** This is now a PrivateModule. Only exposed bindings can be used outside. */
public class Module1 extends PrivateModule {
#Override
protected void configure() {
// Bind C and D as you had before.
bind(C.class).to(C_Impl1.class);
bind(D.class).to(D_Impl1.class);
// Here's the tricky part: You're binding "#Impl1 A" to
// "A" without a binding annotation, but only in here.
bind(A.class).annotatedWith(Impl1.class).to(A.class);
// Now you expose #Impl1 A, so it can be used outside.
// As long as A, C, and D are only bound within private modules,
// they won't conflict with one another, and #Impl1 A is unique.
expose(A.class).annotatedWith(Impl1.class);
}
}
/** Treat Module2 the same way, as a private module. */
public class Application {
#Inject #Impl1 private final A someClassUsingImpl1;
#Inject #Impl2 private final A someClassUsingImpl2;
// ...
}
If this is a common pattern for you, create a general PrivateModule that takes in the classes that vary as constructor parameters, so you don't need to repeat yourself. These can be added to the top-level injector, or installed within other modules.
Injector injector = Guice.createInjector(new YourMainModule(),
new ImplModule(Impl1.class, C_Impl1.class, D_Impl1.class),
new ImplModule(Impl2.class, C_Impl2.class, D_Impl2.class));

In guice is there a difference between #provides and bind()?

I am wondering what the difference is between using #provides on a method and using bind() in my guice modules.
I usually override AbstractModule.configure() and bind all my implementations to my interfaces like this:
public class MyModule extends AbstractModule
{
#Override
protected void configure()
{
this.bind(myIface.class).to(myIfaceImpl.class);
this.bind(myOtherIface.class).to(myOtherIfaceImpl.class).asEagerSingleton();
}
...
}
However, I have noticed a pattern in the codebase I'm currently working with where implementations aren't bound explicitly they are being returned from providers like this:
public class MyModule extends AbstractModule
{
#Provides
#Singleton
myIface iFaceProvider()
{
return new myIfaceImpl();
}
...
}
Is there a reason to prefer one over the other? Are there cases that force a particular method?
If you do
bind(MyInterface.class).to(MyImplementation.class)
Guice creates the instance for you. This enables certiain things like AOP. If you do
#Provides
MyInterface provideMyInterface() {
return new MyImplementation();
}
then Guice didn't create the instance so AOP won't work. Also, it requires an accessible constructor for MyImplementation. Generally, this form is only used when you can't edit MyImplementation to make it Guice-compatible.
There's a third form:
#Provides
MyInterface provideMyInterface(MyImplementation impl) {
return impl;
}
which is almost totally equivalent to the bind(...).to(...) form. It is commonly used in frameworks like Dagger that do not have the bind syntax.

how can I make Google Guice to automatically detect a binding?

I understand how to inject a single dependency using Google Guice.
The following snippets are from the Guice site.
To code a configuration the code would be
public class BillingModule extends AbstractModule {
#Override
protected void configure() {
bind(TransactionLog.class).to(DatabaseTransactionLog.class);
bind(CreditCardProcessor.class).to(PaypalCreditCardProcessor.class);
}
}
The component which use the dependencies to be injected shuold looks like the following:
class BillingService {
private final CreditCardProcessor processor;
private final TransactionLog transactionLog;
#Inject
BillingService(CreditCardProcessor processor,
TransactionLog transactionLog) {
this.processor = processor;
this.transactionLog = transactionLog;
}
public Receipt chargeOrder(PizzaOrder order, CreditCard creditCard) {
...
}
}
FInally, the client code would use Guice to inject the dependencies where needed:
public static void main(String[] args) {
Injector injector = Guice.createInjector(new BillingModule());
BillingService billingService = injector.getInstance(BillingService.class);
...
}
My question is:
Is there a built-in feature in Guice to inject not only -for example- BillingService.class but another different implementation in runtime?
I think I can implement the variation of the different classes to be injected thru reflection or some manual mechanism like reading a configuration file to indicate which class to inject but I still want to know if this can be done from Guice itself.
You can make BillingService an interface and bind a different implementation of it decided in runtime in Module's configure method.

Jersey 2.*. How to replace InjectableProvider and AbstractHttpContextInjectable of Jersey 1.*

I would like to create a class whose objects can be injected using the #Context annotation (or better yet a custom annotation for cases where I need to pass an argument to the annotation) into resource methods. In Jersey 1.* I would have used InjectableProvider (in my case together with AbstractHttpContextInjectable). What I'm trying to achieve is something like #Auth [1] from dropwizard (which uses Jersey 1.7).
The injection capabilities of Jersey were replaced by HK2 as far as I know and I could not find any example of what I'm describing.
Edit: See this question for further problems I have encountered while trying to follow Michal's guide.
You need to implement InjectionResolver<T> interface from HK2. Take a look at existing implementations that are present in Jersey workspace:
ContextInjectionResolver handling #Context
ParamInjectionResolver handling #PathParam, #QueryParam, ... (via it's subclasses)
AutowiredInjectResolver handling #Autowired
Once you have this, you need to extend AbstractBinder from HK2 and bind your InjectionResolver via it's #configure() method:
public class MyResolverBinder extends AbstractBinder {
#Override
protected void configure() {
bind(MyInjectionResolver.class)
.to(new TypeLiteral<InjectionResolver<MyAnnotation>>() {})
.in(Singleton.class);
}
}
... and register an instance of this binder in your application class (or via feature):
Feature:
public class MyFeature implements Feature {
#Override
public boolean configure(final FeatureContext context) {
context.register(new MyResolverBinder());
return true;
}
}
register MyFeature into Application:
public class JaxRsApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
final HashSet<Class<?>> classes = new HashSet<Class<?>>();
classes.add(MyFeature.class);
// Register other providers or resources.
return classes;
}
}
register MyResolverBinder or Feature in the ResourceConfig
new ResourceConfig()
// Register either MyFeature
.register(MyFeature.class)
// or MyResolverBinder
.register(new MyResolverBinder())
// Register other providers or resources
.packages("my.package");
Providing an implementation of InjectionResolver only helps with injection, not when resolving values for the parameters of a resource method.
At least with Jersey 2.11, you need to define a ValueFactoryProvider annotated with #Provider.
#Provider
public class MyValueFactoryProvider implements ValueFactoryProvider {
#Inject
private MyFactory factory;
#Override
public Factory<?> getValueFactory(Parameter parameter) {
if (parameter.getAnnotation(MyAnnotationParam.class) != null) {
return factory;
}
return null;
}
#Override
public PriorityType getPriority() {
return Priority.NORMAL;
}
}
If you also want to get the value injected in, e.g., members and constructor parameters, then InjectionResolver works well.

Dependencies injection in MethodInterceptor

I have MethodInterceptor with dependencies. How could I inject them?
Here, in 2007, Bob Lee said that this possibility should be included in next release, but I can't find API for this.
bindInterceptor method requires instances instead of classes.
From the Guice FAQ:
In order to inject dependencies in an AOP MethodInterceptor, use requestInjection() alongside the standard bindInterceptor() call.
public class NotOnWeekendsModule extends AbstractModule {
protected void configure() {
MethodInterceptor interceptor = new WeekendBlocker();
requestInjection(interceptor);
bindInterceptor(any(), annotatedWith(NotOnWeekends.class), interceptor);
}
}
Another option is to use Binder.getProvider and pass the dependency in the constructor of the interceptor.
public class NotOnWeekendsModule extends AbstractModule {
protected void configure() {
bindInterceptor(any(),
annotatedWith(NotOnWeekends.class),
new WeekendBlocker(getProvider(Calendar.class)));
}
}

Categories