Override binding or child module in Guice - java

Im writing a component using Google Guice that lives next to a web application that does not use any dependency injection tool.
The Guice Module in the component has a few "fixed" bindings that will not change and a couple that are dynamic since they change in every request from the web application.
The easy (and bad) way that I solved this is that everytime that the web application asks the component to do something for the first time, the component builds the new Guice Module, creates the instance and returns it to the web app:
public static X init(#NotNull final Foo perRequestObject, #NotNull final Bar perRequestObject2)
{
final Injector injector = Guice.createInjector(new AbstractModule()
{
#Override
protected void configure()
{
install(new NonChanging Module());
bind(Foo.class).toInstance(perRequestObject);
bind(Bar.class).toInstance(perRequestObject2);
}
});
return return injector.getInstance(X.class);
}
I think that this is a bad approach since building the Injector per request is expensive. What I would like to have is an injector already created that I can override at runtime. I found some stuff around:
1- Override the dynamic bindings (answer https://stackoverflow.com/a/531110/1587864). This still needs to create a new injector so I would have the same problem.
2- Implement some kind of Factory that is already binded in the Injector and has the ability to access the "dynamic" properties that come from the web application and are per request.
I'm not sure how to implement the second one, does this concept exist in Guice?
Thanks

As the comments say, the full proper solution is a Scope. Assuming you've copied the implementation of SimpleScope from this article into your project, then here's what I'd do in your component. As you do above, I assume Foo and Bar are the objects you need created on a per-request basis, and X is the class of the thing you ultimately need Guice to create. I assume further that X has on it a method called doTheActualRequestLogic that is the method you wish to call to ultimately return back to the servlet:
public class MyWebComponent
{
private final Provider<X> theGuiceCreatedObject;
private final SimpleScope perRequestScope;
public MyWebComponent() {
perRequestScope = new SimpleScope();
Injector injector = Guice.createInjector(new AbstractModule()
{
#Override
protected void configure()
{
install(new NonChangingModule());
bind(Foo.class).toProvider(SimpleScope.seededKeyProvider())
.in(perRequestScope);
bind(Bar.class).toProvider(SimpleScope.seededKeyProvider())
.in(perRequestScope);
}
});
theGuiceCreatedObject = injector.getProvider(X.class);
}
// I assume methods called makeFoo and makeBar that can make
// a Foo or Bar for a request
// called by the web service to say "handle this request"
public RequestResult handleRequest(DataToMakeFooAndBarWith requestData) {
try {
perRequestScope.enter();
perRequestScope.seed(Foo.class, makeFoo(requestData));
perRequestScope.seed(Bar.class, makeBar(requestData));
return theGuiceCreatedObject.get().doTheActualRequestLogic(requestData);
} finally {
perRequestScope.exit();
}
}
}

Related

Guice Request-scoped injection without a servlet (in an RPC server)

For background, I'm processing RPC requests in a Thrift service (though my question isn't Thrift-specific). What I want seems like it should be simple, but I can find no examples: how do I reuse com.google.inject.servlet.RequestScoped bindings without starting from scratch?
Clearly I could follow the instructions for creating a custom Scope. But that seems overly complicated. What I want to do: when processing an incoming (Thrift) RPC, create a new RequestContext for each incoming call; then, use standard RequestScoped injection while processing it.
Basically, it seems my code should look (loosely) like this:
void main() {
// Configure appropriate bindings, create injector
Injector injector = Guice.createInjector(new ServerHandlerModule());
ThriftServer server = new ThriftServer.ThriftServerBuilder("MyService", port).withThreadCount(threads).build();`
server.start(new MyService.Processor(new MyHandler()));
// For each incoming request, Thrift will call the appropriate method on the (singleton) instance of MyHandler.
// Let's say MyHandler exposes a method void ProcessInput()
}
class MyHandler {
#Override
void ProcessInput(Input myInput) { // myInput was constructed by Thrift
// I want the following instance of RequestContext to be injected
// (provided by Guice) as (say) a constructor arg to any constructor
// needing one when that construction happens in this thread.
RequestContext rc = new RequestContext(myInput);
doWork();
}
Guice provides a utility class for doing just that: ServletScopes.
If you are using Java 7+:
void ProcessInput(Input myInput) {
RequestScoper scope = ServletScopes.scopeRequest(Collections.emptyMap());
try ( RequestScoper.CloseableScope ignored = scope.open() ) {
doWork();
}
}

Creating Guice singleton that's not tied to an Injector

Our project is setup as follows:
1) Main module: Contains a driver program which starts a Spark streaming server. It has its own Guice injector.
2) When message comes in, it goes to another module, which creates it's own Guice injector.
3) This module uses classes in other modules which themselves use dependent modules. Each of these modules creates its own Guice injector so that it can work independently, tested individually etc.
Here's a problem: Now we need a Singleton, but an object created as #Singleton is bound to an injector (Not to a ClassLoader), so when the Injector goes away the object goes away.
Questions:
1) Is our architecture bad? Should we not be creating an injector in every module?
2) How do we create a Singleton that will remain in a ClassLoader even when injector goes away?
BTW, we use Netflix Governator on top on Guice.
Note: Answer for the question which is supposedly duplicate of this question doesn't answer how a 'single' injector created on the top level module can be passed to the sub-modules. Also, if the sub-modules themselves don't have an injector, can we write standalone unit tests for them?
An idea for question 2 would be to use a provider that you can bind in all your different Modules. This provider would access a singleton that that exists 'outside' of Guice.
I have crafted a simple example where I provide access to a static field. You can change that to use the implementation of the Singleton pattern that suits your needs.
public class SingletonProvider implements Provider<TheSingleton> {
private static final TheSingleton instance = new TheSingleton();
#Override
public TheSingleton get() {
return instance;
}
}
Then we bind this to our different modules
public class Module1 extends AbstractModule {
#Override
protected void configure() {
bind(TheSingleton.class).toProvider( SingletonProvider.class);
}
}
public class Module2 extends AbstractModule {
#Override
protected void configure() {
bind(TheSingleton.class).toProvider( SingletonProvider.class);
}
}
And then I create two different injectors that return this same instance
public class Test {
public static void main(String[] args) {
Injector injector1 = Guice.createInjector(new Module1());
TheSingleton instance = injector1.getInstance(TheSingleton.class);
System.out.println("instance = " + instance);
Injector injector2 = Guice.createInjector(new Module2());
TheSingleton instance2 = injector2.getInstance(TheSingleton.class);
System.out.println("instance2 = " + instance2);
}
}

Multiple implementations to a service using Guice using providers

I need a suggestion for how to code for multiple implementations for a service using Google-guice. Below is the example
TestService testService =new TestServiceImplOne();
TestService testService =new TestServiceImplTwo();
As Guice doesn't allow binding a type to more than one implementations as the below code results in error
binderObject.bind(SomeType.class).to(ImplemenationOne.class);
binderObject.bind(SomeType.class).to(ImplemenationTwo.class);
we can solve this with named annotations as below
binder.bind(Player.class).annotatedWith(Names.named("Good")).to(GoodPlayer.class);
binder.bind(Player.class).annotatedWith(Names.named("Bad")).to(BadPlayer.class);
#Named("Good") Player goodPlayer = (Player)injector.getInstance(Player.class);
#Named("Bad") Player badPlayer = (Player)injector.getInstance(Player.class);
But the application which iam working is something like this. We are binding all the modules in the init() method and creating the injector modules:
//separate method to bind
protected void configure() {
bind(new TypeLiteral<List<Service>>() {}).toInstance(serviceSets);
}
//separate method to inject
Injector i = Guice.createInjector(modules);
But with the above process I can just bind one implementation class to the interface (service class)
Could you please provide me a way to do this with providers. I would like to do something like this below
class TestServiceProvider extends Provider{
// some code where it returns the instance of impl class needed. In my case TestServiceImplOne and TestServiceImplTwo and provider returns the corresponding instance of service class
}
and bind service class with provider class. Something like this
bind(TestService.class).toProvider(TestServiceProvider.class);
I would appreciate if someone suggests a good example using providers or some other way that I can inject whatever implementation I want in the client.
Note: I am using webservices and I am not sure how I can inject different implementations when a webservice is called to a service class.
First of all thanks very much for responding . Coming straight to the point
Iam working on webservices . Heres's the Flow
// GET URI
GET http://www.google.com:8182/indi/provide/organizations/{ou}
OrganizationsResource -------->OrganizationService------>OrganizationServiceImpl
Iam binding OrganizationService with OrganizationServiceImpl and injecting the OrganizationService in OrganizationsResource
#Inject
public void setOrganizationService(OrganizationService orgService) {
this.orgService= orgService;
}
Its fine till here but i have two implementations for OrganizationService ------>OrgDeatilsServiceImpl which does some other job
Now i want to bind both OrganizationServiceImpl and OrgDeatilsServiceImpl to OrganizationService
Confusions:
1) What procedure i have to use in Guice to bind two implementaions?
2) How exactly i can code in OrganizationsResource to dynamically decide which implementation to call.
I would appreciate if you give a sample example for the above requirement.
As Vladimir noted, you can use binding annotations with Providers...
// in YourModule.configure():
bind(TestService.class)
.annotatedWith(Names.named("foo")
.toProvider(TestServiceProvider.class);
...and generic types using TypeLiterals...
bind(new TypeLiteral<List<Service>>() {})
.annotatedWith(Names.named("bar")
.toInstance(serviceSets);
...as long as you ask for an annotated instance using getInstance(Key<T>)...
List<Service> servicesOne = injector.getInstance(
new Key<List<Service>>(Names.named("bar")) {});
// or
List<Service> servicesTwo = injector.getInstance(
Key.get(new TypeLiteral<List<Service>>() {}, Names.named("bar"));
...or, preferably, keep them as fields and let Guice do the injecting, because Guice can't inject local variables. Remember that Guice can only inject classes that it creates, or that you request specifically.
class MyInjectorCreator {
#Inject #Named("foo") Provider<TestService> fooServiceProvider;
#Inject #Named("bar") List<Service> barServices;
// Guice will also wrap/unwrap Providers automatically.
#Inject #Named("foo") TestService fooService;
#Inject #Named("bar") Provider<List<Service>> barServicesProvider;
public void createInjector() {
Injector injector = Guice.createInjector(getListOfModules());
injector.injectMembers(this);
}
}
Now, that answers the question as you phrased it in the title. That said, it sounds like you actually want to choose between implementations at runtime, which is a slightly different but easy-to-solve problem:
class TestServiceProvider extends Provider<TestService> {
// Injection is allowed here!
#Inject ApplicationSettings settings;
#Inject Provider<TestServiceImplOne> oneProvider;
#Inject Provider<TestServiceImplTwo> twoProvider;
#Override public TestService get() {
if (settings.isInTestMode()) {
return new TestTestServiceImplImpl(); // without injection!
} else if (settings.useNewService()) {
return twoProvider.get(); // with injection!
} else {
return oneProvider.get(); // also with injection!
}
}
}
But I should warn you that if you know at injector creation time which service to use, you should probably just bind it correctly then for the sake of code cleanliness and ease of readability:
// in YourModule.configure():
if (settings.isInTestMode()) {
bind(TestService.class).toInstance(new TestTestServiceImplImpl());
} else if (settings.useNewService()) {
bind(TestService.class).to(TestServiceImplTwo.class);
} else {
bind(TestService.class).to(TestServiceImplOne.class);
}

Guice: is it possible to inject modules?

I have a Module that requires some Depedency. Is there a way Modules themselves can be injected? I realize this is a bit of a chicken and egg situation...
Example:
public class MyModule implements Module {
private final Dependency d_;
#Inject public MyModule(Dependency d) {
d_ = d;
}
public void configure(Binder b) { }
#Provides Something provideSomething() {
// this requires d_
}
}
I suppose in this case the solution would be to turn the #Provides method into a full-fledged Provider<Something> class. This is clearly a simplified example; the code I'm dealing with has many such #Provides methods so cutting them each into individual Provider<...> classes and introducing a module to configure them adds a fair amount of clutter - and I thought Guice was all about reducing boilerplate clutter?
Perhaps it's a reflection of my relative noobyness to Guice but I've come across a fair few cases where I've been tempted to do the above. I must be missing something...
#Provides methods can take dependencies as parameters just like parameters to an #Inject annotated constructor or method:
#Provides Something provideSomething(Dependency d) {
return new Something(d); // or whatever
}
This is documented here, though perhaps it could be made to stand out more.
Using a provider or #Provides methods are great if you need a dependency to manually construct an object. However, what if you need something to help you decide how to configure the bindings themselves? It turns out you can use Guice to create (and configure) your module.
Here is a (contrived) example. First, the module we want to configure:
/**
* Creates a binding for a Set<String> which represents the food in a pantry.
*/
public class PantryModule extends AbstractModule {
private final boolean addCheese;
#Inject
public ConditionalModule(#Named("addCheese") boolean addCheese) {
this.addCheese = addCheese;
}
#Override
protected void configure() {
Multibinder<String> pantryBinder = Multibinder
.newSetBinder(binder(), String.class);
pantryBinder.addBinding().toInstance("milk");
if (addCheese) {
pantryBinder.addBinding().toInstance("cheese");
}
pantryBinder.addBinding().toInstance("bread");
}
}
The PantryModule expects a boolean value to be injected to decide whether or not it should include cheese in the pantry.
Next, we'll use Guice to configure the module:
// Here we use an anonymous class as the "configuring" module. In real life, you would
// probably use a standalone module.
Injector injector = Guice.createInjector(new AbstractModule() {
#Override
protected void configure() {
// No cheese please!
bindConstant().annotatedWith(Names.named("addCheese")).to(false);
bind(PantryModule.class);
}
});
Module configuredConditionalModule = injector.getInstance(PantryModule.class);
Now that we have a configured module, we'll update our injector to use it...
//...continued from last snippet...
injector = injector.createChildInjector(configuredConditionalModule);
And finally we'll get the set of strings that represent our pantry:
//...continued from last snippet...
Set<String> pantry = injector.getInstance(new Key<Set<String>>() {});
for (String food : pantry) {
System.out.println(food);
}
If you put all the pieces together in a main method and run it, you'll get the following output:
milk
bread
If you change the binding to the "addCheese" boolean to true, you'll get:
milk
cheese
bread
This technique is cool, but probably only useful when you have control over the Injector instance and only when the module requires complex dependencies. Nonethless, I found a real need for this on a real project at work. If I did, then someone else might too.
The question is already well answered, but I just wanted to add a variation to Colin's example:
class MyModule extends AbstractModule {
public void configure() {
bind(Something.class).toProvider(new Provider<Something>() {
#Inject Dependency d;
Something get() { return d.buildSomething(); }
}
}
}
The #Provides method approach is clearer than what I have above for this simple case, but I've found that instantiating an actual Provider can be useful in some situations too. Something I stole from the mailing list; wouldn't have occurred to me on my own ;)
What is the problem with initializing the module just by calling new MyModule(d) or by creating a Provider<Something> that has an injected Injector? Those would appear to be the standard ways of handling this sort of problem. As has been mentioned, you can also use #Provides methods with arguments.
If the dependency is optional then you can create the module and then call a setter to initialize the value if needed (e.g., com.google.inject.persist.jpa.JpaPersistModule does this with properties, while using new JpaPersistModule(String) to load the correct configuration).
Otherwise I suppose it might be possible to do so (and then call createChildInjector(Modules... modules)), but I'd almost always prefer one of the other approaches to that one.

How to #Inject into existing object hierarchy using Guice?

I have an existing object hierarchy where some objects have fields that need to be injected. Also there are some other objects that are constructed using Google Guice and need to be injected with references to some objects from previously described object hierarchy. How do I do such kind of injection with Guice?
The problem is that objects from existing hierarchy were not constructed using Guice, and therefore are not subject to inject process by default. There is, of course injector.injectMembers() method that is able to inject into existing object instance, but it does not work on object hierarchies.
For those wondering why I can't build mentioned object hierarchy using Guice. This hierarchy represents GUI objects and is built by a GUI framework (Apache Pivot) from a declarative GUI description (in fact this process can be described as object deserialization). That way interface construction is rather simple, and I only want to inject certain service references into interface objects and vice versa (for callbacks).
Approach I am currently about to take is described below.
For injecting into preexisting object hierarchy just let all objects that are interested in injection implement certain interface, like:
public interface Injectable {
void injectAll(Injector injector);
}
Those objects would then implement this interface like so:
public void injectAll(Injector injector) {
injector.injectMembers(this);
for (Injectable child : children)
child.injectAll(injector);
}
Then I'd just call mainWindow.injectAll(injector) for root object in hierarchy and all objects of interest are injected.
Not very nice solution, but gets the work done on one side. On the other side, I need to inject objects from this hierarchy. I guess it can be done via implementing custom provider for such objects.
Is there a better solution to my problem? Maybe there is also something wrong with my approach?
This solution will work, but I'd like to propose a slightly different one to you.
Specifically, since you're going to traverse a deep object structure, this really looks like a job for the Visitor pattern. Also, what you're describing seems to call out for a two-stage injector: a "bootstrap" stage that can inject stuff needed by the pivot-created hierarchy (but can't inject any pivot-created elements) and a second stage that is the real injector used by your app (that can inject anything).
What I would suggest is this basic pattern: make a visitor that traverses the hierarchy and, as it goes, it does injection on those things that need it and records those things that need to be injected elsewhere. Then, when it is done visitng everything, it uses Injector.createChildInjector to make a new Injector that can inject stuff from the original Injector and stuff from the pivot-created hierarchy.
First define a visitor that can hit everything in this hierarchy:
public interface InjectionVisitor {
void needsInjection(Object obj);
<T> void makeInjectable(Key<T> key, T instance);
}
Then define an interface for all your pivot-created elements:
public interface InjectionVisitable {
void acceptInjectionVisitor(InjectionVisitor visitor);
}
You'd implement this interface in your pivot-created classes as (assuming this code in the FooContainer class):
public void acceptInjectionVisitor(InjectionVisitor visitor) {
visitor.needsInjection(this);
visitor.makeInjectable(Key.get(FooContainer.class), this);
for (InjectionVisitable child : children) {
child.acceptInjectionVisitor(visitor);
}
}
Note that the first two statements are optional - it may be that some objects in the pivot hierarchy don't need injection and it could also be that some of them you wouldn't want to have injectable later. Also, notice the use of Key - this means that if you want some class to be injectable with a particular annotation you can do something like:
visitor.makeInjectable(Key.get(Foo.class, Names.named(this.getName())), this);
Now, how do you implement InjectionVisitor? Here's how:
public class InjectionVisitorImpl implements InjectionVisitor {
private static class BindRecord<T> {
Key<T> key;
T value;
}
private final List<BindRecord<?>> bindings = new ArrayList<BindRecord<?>>();
private final Injector injector;
public InjectionVisitorImpl(Injector injector) {
this.injector = injector;
}
public void needsInjection(Object obj) {
injector.injectMemebers(obj);
}
public <T> void makeInjectable(Key<T> key, T instance) {
BindRecord<T> record = new BindRecord<T>();
record.key = key;
record.value = instance;
bindings.add(record);
}
public Injector createFullInjector(final Module otherModules...) {
return injector.createChildInjector(new AbstractModule() {
protected void configure() {
for (Module m : otherModules) { install(m); }
for (BindRecord<?> record : bindings) { handleBinding(record); }
}
private <T> handleBinding(BindRecord<T> record) {
bind(record.key).toInstance(record.value);
}
});
}
}
You then use this in your main method as:
PivotHierarchyTopElement top = ...; // whatever you need to do to make that
Injector firstStageInjector = Guice.createInjector(
// here put all the modules needed to define bindings for stuff injected into the
// pivot hierarchy. However, don't put anything for stuff that needs pivot
// created things injected into it.
);
InjectionVisitorImpl visitor = new InjectionVisitorImpl(firstStageInjector);
top.acceptInjectionVisitor(visitor);
Injector fullInjector = visitor.createFullInjector(
// here put all your other modules, including stuff that needs pivot-created things
// injected into it.
);
RealMainClass realMain = fullInjector.getInstance(RealMainClass.class);
realMain.doWhatever();
Note that the way createChildInjector works ensures that if you have any #Singleton things bound in the stuff injected into the pivot hierarchy, you'll get the same instances injected by your real injector - the fullInjector will delegate injectoion to the firstStageInjector so long as the firstStageInjector is able to handle the injection.
Edited to add: An interesting extension of this (if you want to delve into deep Guice magic) is to modify InjectionImpl so that it records the place in your source code that called makeInjectable. This then lets you get better error messages out of Guice when your code accidentally tells the visitor about two different things bound to the same key. To do this, you'd want to add a StackTraceElement to BindRecord, record the result of new RuntimeException().getStackTrace()[1] inside the method makeInjectable, and then change handleBinding to:
private <T> handleBinding(BindRecord<T> record) {
binder().withSource(record.stackTraceElem).bind(record.key).toInstance(record.value);
}
You could inject MembersInjectors to inject nested fields. For example, this will deeply inject an existing Car instance:
public class Car {
Radio radio;
List<Seat> seats;
Engine engine;
public Car(...) {...}
#Inject void inject(RadioStation radioStation,
MembersInjector<Seat> seatInjector,
MembersInjector<Engine> engineInjector) {
this.radio.setStation(radioStation);
for (Seat seat : seats) {
seatInjector.injectMembers(seat);
}
engineInjector.injectMembers(engine);
}
}
public class Engine {
SparkPlug sparkPlug;
Turbo turbo
public Engine(...) {...}
#Inject void inject(SparkPlug sparkplug,
MembersInjector<Turbo> turboInjector) {
this.sparkPlug = sparkPlug;
turboInjector.injectMembers(turbo);
}
}

Categories

Resources