Guice Injection Across Modules for Sharing - java

I have three Modules in Guice:
ReflectionsModule, for providing Metadata (via Reflections)
PersistenceModule, for Data Access Objects and Others
WebModule, for Web Stuff
Simply put, both PersistenceModule and WebModule will fetch a object which is made from Reflections Module. I can not find a very friendly way to do this in guice.
I think PrivateModules will be a suitable way around, but I am not sure how to implement that. Any ideas?
Thank you.
Some additional details
I am using Reflections. It is basically a wrapper to load persistence metadata from a static resource. So basically supposed a parsed XML file into a JavaBean. Thats the concern of the ReflectionsModule.
From this metadata into the javabean, I need to setup the persistence (its a Google App Engine App, using Objectify) and load additional classes and bind them while reading some annotations within. I do not want to load the resource, so I'd like to refer to the resource loaded from the first example.
For now, the ReflectionsModule also binds the two subsequent modules, which I get (correctly) and apply them to the createChildInjector which came when building with just the first module. As os now, it works. I just would like to know which way would be the best one.

Simply speaking, PrivateModules expose only bindings that are explicitly exposed using #Exposed annotation of the .expose() method. Therefore, if PersistenceModule and WebModule are both PrivateModules, you can do the following:
public class WebModule extends PrivateModule {
#Override
public void configure() {
install(new ReflectionsModule());
// do stuff...
expose(SomeClassFromWebModule.class);
}
}
public class PersistenceModule extends PrivateModule {
#Override
public void configure() {
install(new ReflectionsModule());
// do stuff...
expose(SomeClassFromPersitenceModule.class);
}
}
In this way, the bindings from ReflectionsModule will not be exposed further than the two PrivateModules and will therefore not run into each other.
It is generally a good practice to only expose classes that can only be provided by one Module.

EDIT: better answer found: https://stackoverflow.com/a/5504903/105741 - basically use #Provides annotation to get method parameters in your module injected with your dependencies from other modules. Works much nicer. I.e. for the binding that requires the DependencyClass, I move that code into a method, expose it with the #Provides annotation, and add the DependencyClass as a method parameter.
#dyross - I don't think that's what he's asking.
It's not a good idea to create the ReflectionModule more than once, and PrivateModules don't have anything to do with the problem - that of sharing bindings to children modules (if I understand him correctly). I have the same need, and have used the technique of passing in the required object to the children modules ie.
Injector parentInjector = Guice.createInjector(new ParentModule());
DependencyClass dep = parentInjector.getInstance(DependencyClass);
injector = parentInjector.createChildInjector(new ChildModule(dep));
i.e.
Injector reflectionsModule = Guice.createInjector(new ReflectionsModule());
DependencyClass dep = parentInjector.getInstance(DependencyClass);
injector = parentInjector.createChildInjector(
new PersistenceModule(dep),
new WebModule(dep));
Not ideal, but serves the purpose.
It also just occured to me that you could pass in the injector to the child modules too, and getInstance() from directly inside the child modules.

Related

Use annotation to feed Google guice MapBinder

In a Java project, build with Gradle 5.2, using Google Guice.
I use the MapBinder (http://google.github.io/guice/api-docs/latest/javadoc/com/google/inject/multibindings/MapBinder.html):
MapBinder<String, Snack> mapbinder
= MapBinder.newMapBinder(binder(), String.class, Snack.class);
mapbinder.addBinding("twix").toInstance(new Twix());
mapbinder.addBinding("snickers").toProvider(SnickersProvider.class);
mapbinder.addBinding("skittles").to(Skittles.class);
This is working fine, but now, I want a "plugin architecture", so avoid to import all Snack classes, but rather declare it in the class directly, such as:
#SnackImpl("Twix")
class Twix extends Snack {
}
How?
This won't exactly be possible without some expensive classpath scanning: If the injector doesn't have any reference to your Twix class, it would not be able to bind it into a Map without scanning through every JAR on the classpath in search of #SnackImpl-annotated classes. You could try this with Guava's ClassPath, but if you use a network-based or custom classloader, this may not be tractable at all. In any case I wouldn't recommend it.
One alternative is to use Java's built-in ServiceLoader framework, which lets individual JARs list out the fully-qualified implementations for a given service (interface). You can even use Google's Auto framework to generate that service file for you based on annotations.
That takes care of listing the implementations, but you'll still need to bind them into the MapBinder. Luckily, MapBinder doesn't require a single definition, and will automatically merge multiple MapBinder definitions during module construction time:
Contributing mapbindings from different modules is supported. For example, it is okay to have both CandyModule and ChipsModule both create their own MapBinder, and to each contribute bindings to the snacks map. When that map is injected, it will contain entries from both modules.
(from the MapBinder docs)
With that in mind, I would recommend that each plugin bundle gets its own Guice module where it registers into a MapBinder, and then you add those Guice modules to the main injector using ServiceLoader to get those modules at injector creation time.
// Assume CandyPluginModule extends AbstractModule
#AutoService(CandyPluginModule.class)
public TwixPluginModule extends CandyPluginModule {
#Override public void configure() {
MapBinder<String, Snack> mapBinder
= MapBinder.newMapBinder(binder(), String.class, Snack.class);
mapBinder.addBinding("twix").to(Twix.class);
}
}
You could also take advantage of the superclass:
#AutoService(CandyPluginModule.class)
public TwixPluginModule extends CandyPluginModule {
#Override public void configureSnacks() { // defined on CandyPluginModule
bindSnack("twix").to(Twix.class);
}
}
Alternatively, you could list implementations like Twix directly with AutoService and then create a Module that reads all of the ServiceLoader implementations into your MapBinder, but that may restrict the flexibility of your plugins and doesn't gain you any decentralization of the bindings that MapBinder doesn't give you already.

How to inject a variable number of similar components that have dependencies themselves?

Background
I want to realize dependency injection in Python using injector (or pinject) which itself heavily borrows from guice. While an answer using Python/injector would be ideal, I'm also very happy about solutions/approaches that feature Java/guice.
Intention
I'll give you a quick summary of what I want to achieve: I have a component that depends on a list/sequence of other components that all implement the same interface. Those components have dependencies themselves which may vary amongst the different implementations. The concrete types (implementations) shall be configurable by the user (or using any mechanism of the DI framework).
Example
Yes, I've read Modules should be fast and side-effect free which suggests not to use an XML file for configuration, however as I don't know how to realize this within the framework I'll use one to demonstrate the dependency structure:
<RentingAgency>
<Vehicles>
<Car>
<DieselEngine></DieselEngine>
</Car>
<Car>
<PetrolEngine></PetrolEngine>
</Car>
<Bike></Bike>
</Vehicles>
</RentingAgency>
In this example there is a renting agency (the component that depends on a list of others) that rents out all kinds of vehicles (the interface). The specific vehicles in their fleet (in this case two cars and one bike) should be configurable but fixed during runtime. The vehicles themselves can have dependencies and they can be different depending on the type of vehicle (a car depends on a motor, a bike has no dependencies in this case).
Question
How can I construct the renting agency within the DI framework so that all required vehicles are injected and their dependencies resolved properly?
Maybe helpful
Multibinder
I've read about Multibinder (injector seems to have something similar with Binder.multibind) which allows for injecting a collection of objects that implement the same interface. However:
Can it be used to create multiple instances of the same class that need to receive different dependencies (the two cars (Class Car) in the example have different motors: Interface Motor, Class DieselEngine, class PetrolEngine)?
Using providers to accomplish that task seems to me like giving up the benefits of dependency injection: I could manually create the Car instances in the provider, passing the required Motor as argument, however because this pattern repeats further down the chain (i.e. multiple Motors of the same type are used and they also have dependencies) I want to use dependency injection for generating those objects too. But to manually use them in the provider it seems to me like I have to obtain the instances directly from the injector. The docs mention that injecting the injector is a rare case and from my understanding of dependency injection, the great benefit is that one can request a component and all dependencies are resolved by the framework automatically.
Also because I actually use Python I'm not sure if this approach is appropriate (as Python is quite flexible when it comes to dynamic code generation). Also injector.Injector.get.__doc__ mentions
Although this method is part of :class:Injector's public interface
it's meant to be used in limited set of circumstances.
For example, to create some kind of root object (application object)
of your application (note that only one get call is needed,
inside the Application class and any of its dependencies
:func:inject can and should be used):
Dependency injection frameworks are primarily for dependencies and because your Vehicles object is configured by the user at runtime it is more like application data than a dependency. It probably can't just be injected in one shot using MultiBinding unless you know it at compile time.
Likewise, you are right in saying that it would not be a good approach to construct your set of components by iterating and calling injector.getInstance(Bike.class) etc. For one, this is not good for testing.
However, because the objects contained in Vehicles have their own dependencies you can leverage the DI framework in the creation of your Vehicles object. Remember, also, that although you cannot bind a Provider to an implementation, when you bind a key Guice will inject that provider for you.
For the simple example in the post, consider creating a VehicleFactory. Inside, you could have something like the following:
public class VehicleModule implements Module {
#Override
public void configure(Binder binder) {
binder.bind(DieselEngine.class).toProvider(DieselEngineProvider.class);
binder.bind(PetrolEngine.class).toProvider(PetrolEngineProvider.class);
binder.bind(Bike.class).toProvider(BikeProvider.class);
}
}
public class DieselEngineProvider implements Provider<DieselEngine> {
#Inject
public DieselEngineProvider() {
//if DieselEngine has any dependencies, they can be injected in the constructor
//stored in a field in the class and used in the below get() method
}
#Override
public DieselEngine get() {
return new DieselEngine();
}
}
public class VehicleFactory {
private final CarFactory carFactory;
private final Provider<Bike> bikeProvider;
#Inject
public VehicleFactory(CarFactory carFactory, Provider<Bike> bikeProvider) {
this.carFactory = carFactory;
this.bikeProvider = bikeProvider;
}
public Bike createBike() {
return bikeProvider.get();
}
public Car createDieselCar() {
return carFactory.createDieselCar();
}
public Car createPetrolCar() {
return carFactory.createPetrolCar();
}
}
public class CarFactory {
private final Provider<DieselEngine> dieselEngineProvider;
private final Provider<PetrolEngine> petrolEngineProvider;
#Inject
public CarFactory(Provider<DieselEngine> dieselEngineProvider, Provider<PetrolEngine> petrolEngineProvider) {
this.dieselEngineProvider = dieselEngineProvider;
this.petrolEngineProvider = petrolEngineProvider;
}
public Car createDieselCar() {
return new Car(dieselEngineProvider.get());
}
public Car createPetrolCar() {
return new Car(petrolEngineProvider.get());
}
}
As you mention, there is the danger of this becoming 'factories all the way down', but Guice can help you here.
If the production of Engine becomes more complicated and involves a combination of different parameters, you can use tools like AssistedInject to auto-create the factories for you.
If you end up with a set of common dependencies and uncommon dependencies that you want to use to create different 'flavours' of an object then you have what is known as the robot legs problem then Guice can solve it using private modules.
Do note the following caveat from the Dagger 2 user guide:
Note: Injecting Provider has the possibility of creating confusing
code, and may be a design smell of mis-scoped or mis-structured
objects in your graph. Often you will want to use a factory or a
Lazy or re-organize the lifetimes and structure of your code to be
able to just inject a T.
If you follow this advice, it would seem that you would have to carefully balance using providers and using factories to create your Vehicle.

Dependency injection using guice for a client sdk/library design pattern

I am building a client SDK for a web API and trying to apply dependency injection via guice. This Java client will be used by third parties as a way of accessing our API.
I want to be able to inject my external dependencies(The HTTP client used etc.) and give a way for developers to inject different versions of those dependencies if they wanted or if I ever wanted to change the implementation myself (a good case for dependency injection right?).
However in order to wire the dependencies, I have to make the user of my library create an injector etc. something like so:
Injector injector = Guice.createInjector(new MyAPIClientModule(url, username, password));
this.service = injector.getInstance(MyAPIService.class);
I don't want to push this up to the user of my library, but I still want to give users the ability to choose a different implementation or underlying HTTP library etc.
Am I missing the point of guice or DI here somehow? Is this standard practice when using guice?
Or should I wrap this in another class that does the injection and present the third party user with just a sample Java object?
I want to be able to inject my external dependencies(The http client
used etc.) and give a way for developers to inject different versions
of those dependencies if they wanted or if I ever wanted to change the
implementation myself(a good case for dependency injection right?).
It is highly arguable that this is a good case for DI. External dependencies like HTTP clients usually have concrete interface that is implemented by no one except exactly that dependency. Personally I can't imagine how your program is written given that swapping underlying HTTP client won't affect its architecture, that is, unless you provide your own facade for it, something like
public interface HttpClient {
HttpResponse send(HttpRequest request);
}
where HttpRequest and HttpResponse are also custom classes/interfaces. But providing such kind of extension point to the end user is rarely appropriate, especially if you don't have some reference implementation (this means that the user will have to create this facade for the dependency he/she wants). It is appropriate in rare cases, but chances are this is not your situation.
Different versions of the same dependency is also usually not the case for DI because swapping versions can be done at build/assembly time.
If you want to expose an ability for the user to provide their own implementations of some of your library "moving parts", then first you have to define strict interface for all these moving parts. In other words, provide a set of interfaces which your user must extend and which are injected in your classes.
Then you create your "binding space" consisting of your Guice modules, and in these modules you declare requirements on these interfaces:
public class SomeModule extends AbstractModule {
#Override
protected void configure() {
requireBinding(SomeUserAPI.class);
// Other bindings which probably use SomeUserAPI in implementations
}
}
By stating required bindings you ensure that no one will be able to mix in your module unless they provide some implementation of the given class. Of course, Guice will fail anyway if it can't find the binding, but when you require it explicitly you obtain more concrete error message, as well as clear interface of your modules.
And then you create special "entry point" to your library, sole responsibility of which is to create the injector and provide the user with instances of your classes. This class accepts Guice module from the user and integrates it into the injector.
public class Library {
private final Injector injector;
private Library(Module userModule) {
// SomeModule and AnotherModule are modules defined in the library
// and they are not the part of public interface of your library
this.injector = Guice.createInjector(userModule, new SomeModule(), new AnotherModule());
}
public static Library create(Module userModule) {
return new Library(userModule);
}
public MyAPIService myAPIService() {
return injector.getInstance(MyAPIService.class);
}
}
Then the user uses it like this:
Library library = Library.create(new AbstractModule() {
#Override
protected void configure() {
// recall requireBinding(SomeUserAPI.class) statement we wrote previously,
// here we are "implementing" it
bind(SomeUserAPI.class).to(SomeUserAPIImpl.class);
// other bindings for your exposed interfaces
}
});
MyAPIService service = library.myAPIService();
In this approach you allow the user to extend your library using Guice DI in a neat and controlled way.
You still have to expose Guice to your users, however (because the users have to implement Module interface). I don't think you can avoid that completely unless you do something bizarre like
Library.create(SomeUserAPIImpl.class, SomeUserAPI2Impl.class, ...)
that is, accept class objects representing implementations of extension points (and then bind them in some internal module). But I don't think that eliminating Guice from the library interface really worth it.
You can do module override which is not suggested for production. You can find more here Overriding Binding in Guice
You can use #ImplementedBy which create binding but explicitly binding of the interface will override that annotation binding. So, you will create your framework with #ImplementeBy if is it possible and 3th parties devs will override it with explicitly binding in their module. Find more https://code.google.com/p/google-guice/wiki/JustInTimeBindings
Anyway I'm not familiar with any of these approach. I would suggest to create an abstract ApiClient and let 3th party devs to implement the open points. Maybe you should introduce some annotations like #Client which had to implement ClientApi. Then your module will search the classpath for implementation of ClientApi with #Client annotation. Lets say the annotation would contain a value #Client('apache-http') and you will introduce a configuration property 'api-client' which would be set to default for default implementation or apache-http if you want to use something different. Well, you should consider it because integrity of your ApiClient can be shattered easily with wrong bindings :).

Guice assisted injection deeper down the dependency hierarchy

I want to conduct a chain of processing elements and wire them together via Guice. Let's assume the following path:
interface A implemented by class AImpl needs some input
interface B implemented by class BImpl needs A
interface C implemented by class CImpl needs B
interface D implemented by class DImpl needs C
The dependency of A can only be resolved at runtime and not at configuration time. The usual approach would be to use Assisted Injection in this case to create a factory, that takes the missing instances as parameters, just like this:
public interface AFactory {
public A createA(String input);
}
But what I actually want is something like this:
public interface DFactory {
public D createD(String inputForA);
}
I don't want to manually pass AImpl-specific dependencies through the whole hierarchy.
Is it possible to achieve this with Guice? If not, what's the best way to circumvent this problem elegantly while still retaining benefits of injection?
Cheating way: Stick input in a static variable or singleton ThreadLocal. Set it before your pipeline starts and clear it after it ends. Bind everything else through DI.
Fancy way: In A, refer to a #PipelineInput String inputString but don't bind it in your main injector. Otherwise, bind dependencies as you normally would, including referring to #PipelineInput in other pipeline-related classes. When you do need a D, get it from your implementation of a DFactory, which I'm calling PipelineRunner.
public class PipelineRunner {
#Inject Injector injector; // rarely a good idea, but necessary here
public D createD(final String inputForA) {
Module module = new AbstractModule() {
#Override public void configure() {
bindConstant(inputForA).annotatedWith(PipelineInput.class);
}
};
return injector.createChildInjector(new PipelineModule(), module)
.getInstance(D.class);
}
}
Naturally, binding attempts for A, B, C, and D will fail outside of PipelineRunner for lack of a #PipelineInput String--you'll get a CreationException when you create the injector with those unsatisfied dependencies, as you discovered--but those pipeline-based dependencies should be easy to separate into a Module that you install into the child injector.
If this feels too hacky, remember that PrivateModules are also "implemented using parent injectors", and that the whole point of dependency injection is to make a dependency like inputForA available to the whole object graph in a decoupled way.
I see three options. They depend on how often you change the input for A .
1) Bind input as a constant in your module. This works only, if you know that value before you create the Injector and never want to change the value. See bindConstant
2) Use a private submodule which binds either A or the value for input inside that module. Basically you can have two or three instance graphs with different value. See newPrivateBinder.
3) Use a Scope ala RequestScope, SessionScope, ... This way you can change the input often but you must enter/leave the scope at some point to be defined. See Custom Scopes for an example.

How to use eclipse 4 DI in classes that are not attached to the application model?

I have created a OSGI service with declarative services to inject an object that implements an interface. If I inject the object in a class that is attached to the application model (handler,part,....) it is working fine. If I inject it in a class that is not attached to the application model it is always returning null.
Is it possible to use DI in classes that are not attached to the application model? I looked in the vogella tutorials but somehow I don't find a solution.
I know of three ways of how Eclipse 4 can inject objects in your classes:
During start-up the Eclipse runtime looks for relevant annotations in the classes it instantiates.
Objects injected in 1. are tracked and will be re-injected if changed.
Manually triggering injection using the ContextInjectionFactory and IEclipseContext.
What you want may be possible with the third option. Here is a code example:
ManipulateModelhandler man = new ManipulateModelhandler();
//inject the context into an object
//IEclipseContext iEclipseContext was injected into this class
ContextInjectionFactory.inject(man,iEclipseContext);
man.execute();
The problem is, however; that the IEclipseContext already needs to be injected into a class that can access the object that needs injection. Depending on the number of necessary injections, it might be more useful to use delegation instead (testability would be one argument).
#Inject
public void setFoo(Foo foo) {
//Bar is not attached to the e4 Application Model
bar.setFoo(foo);
}
Therefore, a better solution is probably using the #Creatable annotation.
Simply annotate your class, and give it a no-argument constructor.
#Creatable
public class Foo {
public Foo () {}
}
Using #Inject on that type as in the method above, will let Eclipse instantiate and inject it.
The disadvantage is that you cannot control the object creation anymore, as you would with ContextInjectionFactory.inject(..).
I refactored out some part of e(fx)clipse in order to achieve that. Have a look at this. Sorry for the shameless plug...

Categories

Resources