Proper structure for dependency injection (using Guice) - java

I would like some suggestions and feedback on the best way to structure dependency injection for a system with the structure described below. I'm using Guice and thus would prefer solutions centered around it's annotation-based declarations, not XML-heavy Spring-style configuration.
Consider a set of similar objects, Ball, Box, and Tube, each dependent on a Logger, supplied via the constructor. (This might not be important, but all four classes happen to be singletons --- of the application, not Gang-of-Four, variety.)
A ToyChest class is responsible for creating and managing the three shape objects. ToyChest itself is not dependent on Logger, aside from creating the shape objects which are.
The ToyChest class is instantiated as an application singleton in a Main class.
I'm confused about the best way to construct the shapes in ToyChest. I either (1) need access to a Guice Injector instance already attached to a Module binding Logger to an implementation or (2) need to create a new Injector attached to the right Module.
(1) is accomplished by adding an #Inject Injector injectorfield to ToyChest, but this feels weird because ToyChest doesn't actually have any direct dependencies --- only those of the children it instantiates.
For (2), I'm not sure how to pass in the appropriate Module.
Am I on the right track? Is there a better way to structure this?
The answers to this question mention passing in a Provider instead of using the Injector directly, but I'm not sure how that is supposed to work.
EDIT:
Perhaps a more simple question is: when using Guice, where is the proper place to construct the shapes objects? ToyChest will do some configuration with them, but I suppose they could be constructed elsewhere. ToyChest (as the container managing them), and not Main, just seems to me like the appropriate place to construct them.

A proper way is to have guice construct your dependencies. That is create and configure.
In your situation you should have an injector constructed in the Main. From the injector you get ToyChest. When you obtain ToyChest through the injector its managed by guice and you can depend on it to supply all dependencies properly configured.
In your case you can inject Provider<Ball>, Provider<Box>, etc. in ToyChest and when needed just retrieve instance from the provider. ToyChest is not responsible for constructing the instance, just to use it. You can also check MapBinder if you have a plugin architecture.
So far everything is managed by guice, so the shapes can have their logger injected without the using class knowing about it.
If you have some runtime parameters that you want to pass to the newly created shape instances, you can use AssistedInject.
Just a hint: you are not required to use constructor injection, you can have injection on field or setter, which simplifies the constructor.

Related

Guice and 'injection' of the Injector

I tryied Google Guice after reading this article : http://tech.puredanger.com/2007/07/03/pattern-hate-singleton/
But there is something I didn't understand : when you use the #Singleton anotation of Guice, the injection inject the same instance, but only for one Injector.
If I create an other Injector somewhere else, the #Singletion doesn't works (as stated in the documentation).
So I will have to pass the injector instance everywhere in my code, or make it available in a singleton.
And this is exactly I would like to avoid.
How to we manage injectorS to make it possible to return the same instance everytime ?
Thanks.
Code using Guice shouldn't normally need to access the injector itself: objects will receive either their dependencies or a Provider<T> for their dependencies, if they need to construct more than one.
Usually, objects only need the injector if they have dependencies but aren't themselves created by the injector (so they can't have their dependencies injected). If you're using Guice everywhere, you probably only need to do that on application start-up. If you're only using Guice for part of your project, the injector becomes a single singleton that proxies for all the other singletons you're now accessing through it.
Do note that classes annotated #Singleton are still singleton objects, albeit without some of the baggage associated with non-injected singletons. You should still try to avoid depending on them too much.

How to let Guice bind an annotated injection to a single instance

I have an UI component that will be used in several UI module in an application.
I would like to annotate the UI component that to be injected into several other classes in one UI module to be a singleton, but not a singleton across the whole application. So that for each UI module use the UI component, one and only one of the UI component instance is used.
I couldn't find a straight solution for this from the Guice document. So i think maybe I can use annotation to distinguish those instance?
Say in Module A, I annotate all the injection of the UI component with Named("ModuleA"); and in Module B, with Named("ModulaB"). and in the configuration, i tried to use something like:
this.bind(UIComponentA.class)
.annotatedWith(Names.named("ModulaA"))
.to(UIComponentAImpl.class).in(Singleton.class);
this.bind(UIComponentA.class)
.annotatedWith(Names.named("ModulaB"))
.to(UIComponentAImpl.class).in(Singleton.class);
Because UICompoenetAImpl also need to be injected, so I couldn't simply create the instance there. Totally not sure if this works.
And I'm wondering what's the standard way to accomplish this?
One other option might be to use a child injector for each module.
This would allow you to bind a difference instance of UIComponentA in each module. Bind them in the child injector rather than the parent. You would then need to make sure that all of your module's dependencies are built from the right child injector, probably by making sure the root of each module is loaded from the right place.
Because UICompoenetAImpl also need to be injected, so I couldn't simply create the instance there.
I think you can just create UIComponentAImpl there and bind toInstance. When you do so - other beans will be injected in UIComponentAImpl. Please see my example here.

Guice Injection into Business Layer of Java Web App

I have sucessfully used Guice to Inject Providers into the servlet portion of an existing java web application, however, I can't access the injectors through the business layer (non-servlet java classes) of the application.
I have read up on Injecting the Injector, but to me that seems more like a hack and in several places, including the Guice documentation, it says not to do that too much.
I guess my question is, Where do I bootstrap a java web app so that the non-servlet/filter classes have access to the injector created in the class I use to extend GuiceServletContextListener? Is there any way to make those classes injectable without injecting the injector?
Thank you and let me know if you need any clarification.
Edit:
I am attempting to do this with a simple logger, so far, in my
servlets, I call:
#Inject
private static org.slf4j.Logger log;
The injection is set up in MyLoggerModule as follows (which is in the
createInjector call with ServletModule) :
#Override
public void configure() {
bindListener(Matchers.any(), new SLF4JTypeListener()); // I
built my own SLF4JTypeListener...
}
This all works perfectly in the servlets, but the field injection does
not work when called by a class that is not a servlet or filter.
Guice doesn't intercept calls for new objects, so if your business layer isn't already using Guice to create the objects that need injection, it'll need modification to do so.
The injection only works when handled by Guice during injection. So starting from the base injector you've made, whatever is marked with #Inject which is needed for the instance you've requested will be provided by Guice as best it can, and in turn, during instanciation of those, further #Inject annotations will be filled in by providers and bindings until nothing new needs to be instanciated. From that point on however you are not going to get fields injected into servlets created outside Guice's injection, perhaps by calling new somewhere, which is likely what your Object Factory is doing.
You'll need to change your Object Factory to use providers instead of new. If you could edit these, it wouldn't be too hard to do since Guice can give you default providers for bindings.
So one way your business layer could be Guice aware is to have whatever is creating servlets first create an Injector and then request the servlets be created by the injector. If this means you'll have more than one injector, then yes, that will be a problem but only for the objects you want to be singletons. So you could make a factory pattern class for a singleton injector, or you could find where these classes (here typed bar) which are creating servlets themselves are created (in foo), and then start with the injector there (in foo) using one Guice injector to create those (bar type) classes and also modifying them (bar type) to request a provider for the servlets which they'll use instead of making calls for a new servlet.
Now that I think about this, it could be simple if it kind of only happens once or twice for 10-20 servlet types, or it could be complicated if there's some framework that defines totally flexible behavior for what gets newed up when and why.
Another option would be avoiding #Inject on fields at all times, as recommended. So now your servlets are taking in an org.slf4j.Logger as a construction parameter. The constructor is marked #Inject, and it assigns the parameter's value to the field. Then any place you're not using injection should break with an incorrect number of parameters at a new call. Fix these by figuring out how to either get the servlet provided here instead, or how to get a provider for the servlet into the class.
Not sure what you mean... if you inject objects in to your servlets/filters, those objects have their dependencies injected by Guice as well, and so on all the way down.
How are you creating the classes that you're trying to inject this logger in to? They must be created by Guice to be injected, which means no new.

How do I write a Guice Provider that doesn't explicitly create objects?

Say I have a ClassWithManyDependencies. I want to write a Guice Provider for this class, in order to create a fresh instance of the class several times in my program (another class will depend on this Provider and use it at several points to create new instances).
One way to achieve this is by having the Provider depend on all the dependencies of ClassWithManyDependencies. This is quite ugly.
Is there a better way to achieve this?
Note - I certainly don't want the Provider to depend on the injector. Another option I considered is having ClassWithManyDependencies and ClassWithManyDependenciesProvider extend the same base class, but it's butt ugly.
As mentioned on the mailing list, anywhere you can inject ClassWithManyDependencies you can simply inject Provider<ClassWithManyDependencies> instead, no need to write anything special yourself. Guice does this for you.
You shouldn't have to write a provider except to integrate with other frameworks.
Just DON'T bind your ClassWithManyDependencies in scope SINGLETON and in the class that wants to build many instances, instead of having a ClassWithManyDependencies instance injected you have a Provider injected. (Guice can do that for free for every binded class)
On this provider you can just call get(), if not in scope SINGLETON it makes a fresh new instance each time.
Now if you are in the tricky case that ClassWithManyDependencies relies both on some GUICE IOC and on some constructor parameters, then you shall go for Assisted Injections

Is there ever a case for 'new' when using dependency injection?

Does dependency injection mean that you don't ever need the 'new' keyword? Or is it reasonable to directly create simple leaf classes such as collections?
In the example below I inject the comparator, query and dao, but the SortedSet is directly instantiated:
public Iterable<Employee> getRecentHires()
{
SortedSet<Employee> entries = new TreeSet<Employee>(comparator);
entries.addAll(employeeDao.findAll(query));
return entries;
}
Just because Dependency Injection is a useful pattern doesn't mean that we use it for everything. Even when using DI, there will often be a need for new. Don't delete new just yet.
One way I typically decide whether or not to use dependency injection is whether or not I need to mock or stub out the collaborating class when writing a unit test for the class under test. For instance, in your example you (correctly) are injecting the DAO because if you write a unit test for your class, you probably don't want any data to actually be written to the database. Or perhaps a collaborating class writes files to the filesystem or is dependent on an external resource. Or the behavior is unpredictable or difficult to account for in a unit test. In those cases it's best to inject those dependencies.
For collaborating classes like TreeSet, I normally would not inject those because there is usually no need to mock out simple classes like these.
One final note: when a field cannot be injected for whatever reason, but I still would like to mock it out in a test, I have found the Junit-addons PrivateAccessor class helpful to be able to switch the class's private field to a mock object created by EasyMock (or jMock or whatever other mocking framework you prefer).
There is nothing wrong with using new like how it's shown in your code snippet.
Consider the case of wanting to append String snippets. Why would you want to ask the injector for a StringBuilder ?
In another situation that I've faced, I needed to have a thread running in accordance to the lifecycle of my container. In that case, I had to do a new Thread() because my Injector was created after the callback method for container startup was called. And once the injector was ready, I hand injected some managed classes into my Thread subclass.
Yes, of course.
Dependency injection is meant for situations where there could be several possible instantiation targets of which the client may not be aware (or capable of making a choice) of compile time.
However, there are enough situations where you do know exactly what you want to instantiate, so there is no need for DI.
This is just like invoking functions in object-oriented langauges: just because you can use dynamic binding, doesn't mean that you can't use good old static dispatching (e.g., when you split your method into several private operations).
My thinking is that DI is awesome and great to wire layers and also pieces of your code that needs sto be flexible to potential change. Sure we can say everything can potentially need changing, but we all know in practice some stuff just wont be touched.
So when DI is overkill I use 'new' and just let it roll.
Ex: for me wiring a Model to the View to the Controller layer.. it's always done via DI. Any Algorithms my apps uses, DI and also any pluggable reflective code, DI. Database layer.. DI but pretty much any other object being used in my system is handled with a common 'new'.
hope this helps.
It is true that in today, framework-driven environment you instantiate objects less and less. For example, Servlets are instantiated by servlet container, beans in Spring instantiated with Spring etc.
Still, when using persistence layer, you will instantiate your persisted objects before they have been persisted. When using Hibernate, for example you will call new on your persisted object before calling save on your HibernateTemplate.

Categories

Resources