I have an existing class named Legacy which is mostly written in old school singleton pattern. Now I want to introduce a new field to it and I would like to use Guice. Legacy itself is not Guice controlled, it is used by another Service class (inside the Service class, it calls the getInstance() of Legacy class to retrieve the Legacy object right now), and that Service class is been created using Guice injector.
public class Legacy {
public synchronized static Legacy getInstance() {
if(sInstance == null) {
sInstance = new Legacy();
}
return sInstance;
}
private Legacy() {
legacyObj = LegacyField.getInstance(); // get a singleton
}
private static Legacy sInstance;
private LegacyField legacyObj;
private NewField newObj; // this is the new dependency I would like to add using Guice
}
What I tried is that I tried to put method Inject into Legacy class
#Inject
public void setNewField(NewField newObj) {
this.newObj = newObj;
}
And in the module file of the Service, I bind the NewField object, but when I run the program, it throwed a NullPointer exception. So the inject doesn't work. Any idea of how to make NewField inject into my program but keep the current old-school singleton paradigm and not changing too much about everything else?
EDIT
There are a least three solutions below and I don't quite know which is the best or are they equivalent.
I just found another solution:
// put in the module
bind(Legacy.class).toInstance(Legacy.getInstance());
In this example, your module itself, not Guice, takes responsibility for obtaining a Legacy instance, then asks Guice to always use this single instance to fulfill all Legacy injection requests.
But according to the javadoc
When the Injector is created, it will automatically perform field and method injection for this instance, but any injectable constructor on Legacy is simply ignored. Note that using this approach results in "eager loading" behavior that you can't control.
Though only slightly cleaner than Thomas's answer, you can configure the injection of your Singleton from within your Module using requestInjection or requestStaticInjection.
// In your Module:
requestInjection(Legacy.getInstance()); // for an instance field, or
requestStaticInjection(Legacy.class); // for a static field.
The docs on the wiki warn about the downsides, though:
This API is not recommended for general use because it suffers many of the same problems as static factories: it's clumsy to test, it makes dependencies opaque, and it relies on global state.
Here is a somewhat hackish solution.
In the bootstrapping of your application,
may be in method public static void main(String[] args),
you should already have code similar to this:
Injector injector = Guice.createInjector(yourModule);
At this place add the following line:
injector.injectMembers(Legacy.getInstance());
By doing so, all the #Injects in your Legacy singleton
should be resolved.
See also the javadoc of Injector.injectMembers.
Related
I have a situation where when I initialize some of my classes, some of the fields I need to be injected (e.g. references to factories etc) whereas some others are dynamic and created at runtime (e.g. usernames etc). How do I construct such objects using the GUICE framework?
Simply annotating the fields I need injected as #Inject doesn't work as they seem to not be set up when creating an object using the constructor. For instance:
class C {
#Inject
private FactoryClass toBeInjected;
private ConfigurationField passedIn;
public C(ConfigurationField passedIn) {
this.passedIn = passedIn;
}
}
If my understanding is correct (and I could be wrong), the fact that I'm creating a new instance of C via new and not through Guice means that no injection will take place. I do need to pass these parameters in the constructor, but also want some fields injected -- so how do I solve this problem?
A feature specifically matching "mixing injection and parameters passed" would be Assisted Injection.
class C {
// Guice will automatically create an implementation of this interface.
// This can be defined anywhere, but I like putting it in the class itself.
interface Factory {
C create(ConfigurationField passedIn);
}
#Inject
private FactoryClass toBeInjected;
private ConfigurationField passedIn;
private SomeOtherDepIfYoudLike otherDep;
#Inject public C(#Assisted ConfigurationField passedIn,
SomeOtherDepIfYoudLike otherDep) {
this.passedIn = passedIn;
this.otherDep = otherDep;
}
}
Now in your module:
#Override public void configure() {
install(new FactoryModuleBuilder().build(C.Factory.class));
}
Now when someone wants to create a C, they can avoid calling the constructor directly; instead, they inject a C.Factory into which they pass a ConfigurationField instance of their choice and receive a fully-constructed, fully-injected C instance. (Like with most well-designed DI objects, they can call the constructor directly.)
Note that this design is especially useful in a few ways:
You can use constructor injection, treat all your fields as final, and treat the object as immutable.
If you stick with constructor injection entirely, your object will never be in a partially-initialized state, and your API stays simple (call the constructor and your object is ready).
For testing, you can write any implementation of C.Factory and have it return any instance you want. This can include test doubles of C or its factory: Fakes, mocks, or spies that you create manually or by using Mockito, EasyMock, JMock, or any other mocking framework.
What you are looking for is "On Demand" Injections:
public static void main(String[] args)
{
Injector injector = Guice.createInjector(...);
CreditCardProcessor creditCardProcessor = new PayPalCreditCardProcessor();
injector.injectMembers(creditCardProcessor);
}
or for static things
#Override public void configure() {
requestStaticInjection(ProcessorFactory.class);
...
}
All explained very well https://github.com/google/guice/wiki/Injections#on-demand-injection.
Note:
Both of these things are code smells and should only really be used
for migrating old code over to Guice. New code should not use these
approaches.
With Google Guice or Gin I can specify parameter with are not controlled by the dependency injection framework:
class SomeEditor {
#Inject
public SomeEditor(SomeClassA a, #Assisted("stage") SomeClassB b) {
}
}
The assisted parameter stage is specified at the time an instance of SomeEditor is created.
The instance of SomeClassA is taken from the object graph and the instance of SomeClassB is taken from the caller at runtime.
Is there a similar way of doing this in Dagger?
UPDATE: As of Dagger 2.31 from January 2021, Dagger now natively supports assisted injection, which is recommended over the Square and Auto options. (Those other options still work, but may require extra setup compared to the native option.)
class SomeEditor {
#AssistedInject public SomeEditor(
SomeClassA a, #Assisted SomeClassB b) {
// ...
}
}
#AssistedFactory interface SomeEditorFactory {
SomeEditor create(SomeClassB b);
}
(original answer)
Because factories are a separate type of boilerplate to optimize away (see mailing list discussion here), Dagger leaves it to a sister project, AutoFactory. This provides the "assisted injection" functionality Guice offers via FactoryModuleBuilder, but with some extra benefits:
You can keep using AutoFactory with Guice or Dagger or any other JSR-330 dependency injection framework, so you can keep using AutoFactory even if you switch between them.
Because AutoFactory generates code, you don't need to write an interface to represent the constructor: AutoFactory will write a brand new type for you to compile against. (You can also specify an interface to implement, if you'd prefer, or if you're migrating from Guice.)
Because all the type inspection happens at compile-time, it produces plain old Java, which doesn't have any slowness due to reflection and which works well with debuggers and optimizers. This makes the Auto library particularly useful for Android development.
Example, pulled from AutoFactory's README, which will produce a SomeClassFactory with providedDepA in an #Inject-annotated constructor and depB in a create method:
#AutoFactory
final class SomeClass {
private final String providedDepA;
private final String depB;
SomeClass(#Provided #AQualifier String providedDepA, String depB) {
this.providedDepA = providedDepA;
this.depB = depB;
}
// …
}
Just like #xsveda, I also wrote an answer about this in this other question, which I'll also reproduce here.
Today, for assisted injection with Dagger you probably want to use AssistedInject. I wrote about it in this blogpost, but I'll add a full example here to make things easier.
First thing you need are the dependencies:
compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.4.0'
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.4.0'
Then here's how it can look like:
class ImageDownloader #AssistedInject constructor(
private val httpClient: HttpClient,
private val executorService: ExecutorService,
#Assisted private val imageUrl: URL,
#Assisted private val callback: ImageCallback
) {
#AssistedInject.Factory
interface Factory {
fun create(imageUrl: URL, callback: ImageCallback): ImageDownloader
}
}
First thing is that instead of annotating the constructor with #Inject, we annotate it with #AssistedInject. Then we annotate the parameters that will have to go through the factory, which is the opposite of what AutoFactory expects. Finally, we need an inner factory interface annotated with #AssistedInject.Factory that has a single method that receives the assisted parameters and returns the instance we're interested in.
Unfortunately, we still have an extra step here:
#AssistedModule
#Module(includes = [AssistedInject_AssistedInjectModule::class])
interface AssistedInjectModule
We don't necessarily need a dedicated module for it, even though that's a valid option. But we can also have those annotations in another module that is already installed in the component. The nice thing here is that we only need to do it once, and after that any factory will automatically become part of the graph.
With that, you can basically inject the factory and ask for your object as you'd normally do.
Yes, please check this Square project: square/AssistedInject
Currently it is not in 1.0 yet for purpose. They wait until Dagger will introduce a public API for registering those generated Module classes automatically - see this issue. With that you won't have to reference them in your Dagger code as in this example from README:
#AssistedModule
#Module(includes = AssistedInject_PresenterModule.class)
abstract class PresenterModule {}
I'm working with a Guice enabled framework.
When using classes that were created by the framework (or subclasses that override existing bindings), I can instantiate framework provided variables very easily. Whatever I need, it's just a matter of
#Inject
FrameworkProvidedType variable;
However, in my custom created classes, that doesn't work. All of the injected variables are null.
It's my understanding that in order to use injection, my class has to have a binding.
If I'm subclassing an existing framework class, I can override the binding in my module class. That's pretty straightforward.
But I have a new class and I don't know how to bind it to the underlying framework.
public Class myCustomClass {
private String iNeedthis;
private Context thisToo;
#Inject
FrameWorkThing magic;
public myCustomClass(String iNeedThis, Context thisToo){
this.iNeedThis = iNeedThis;
this.thisToo = thisToo;
}
public void DoMagic(){
//null pointer error because magic was not injected
magic.doMagic(this.iNeedthis);
}
}
How do I Guice-enable this new class?
I tried this in my Runtime Module
public Class<myCustomClass> bindMyCustomClass(){
return MyCustomClass.class;
}
and failed miserably.
No thanks to #bmorris591 who dismissed and downvoted the question out of the gate, I found an answer.
#Inject-ing a field into a class means that the class instance needs to be created by Guice.
Step 1 is creating a factory for the class. This may not be necessary, but it worked for me.
public interface MyCustomClassFactory {
public MyCustomClass create(String iNeedThis, Context thisToo);
}
Step 2 is installing the factory into Guice
#Override
public void configure(Binder binder) {
super.configure(binder);
binder.install(new FactoryModuleBuilder().build(MyCustomClass.class));
}
In my particular case - the framework I'm working with provides a Module class that is an implementation of com.google.inject.Module.
Within that class is a "configure(Binder binder)" function that is called on startup.
Step 3 is actually annotating the constructor
#Inject
public myCustomClass(String iNeedThis, Context thisToo){
this.iNeedThis = iNeedThis;
this.thisToo = thisToo;
}
Useful and related web page that put me on the right track:
http://beust.com/weblog/2012/08/21/advanced-dependency-injection-with-guice/
This talks about assisted injection, but it gave enough information and a simple enough to understand example that taking the next step was pretty easy.
My project is heavily using dependency injection, and I'm being very careful to avoid service locator antipattern. All objects are structured using constructor injection that allow easily identifiable list of dependencies. Now I'm building an object, and it has a special "constant" instance, which is basically static/singleton (consider example of something like Integer.MinValue). So my initial reflex was to create a static field with a static "getter" method, which would create the instance of the object if it wasn't previously created. The object itself has dependencies however, so I'm confused on what's the best practice for instantiating this "special instance". I'm looking for recommendations on how to best structure code in this scenario, ideally without having to call upon the container for resolution of dependencies. Some code:
public class PressureUnit extends DataUnit {
private static PressureUnit standardAtmosphere;
public static PressureUnit StandardAtmosphere() {
if(standardAtmosphere == null){
standardAtmosphere = new PressureUnit(1013.25); // this line is what is bothering me as I need to resolve other dependencies (have to use new as it's a static method and can't be injected like everywhere else)
}
return standardAtmosphere;
}
#AssistedInject
public PressureUnit(ITimeProvider timeProvider, IUnitProvider unitProvider, #Assisted double value) {
this(timeProvider, unitProvider, value, PressureUnits.hPa);
}
...
}
I really don't see any problem in your code since you are not newing up dependencies here and there, now with that being said i can give some suggestions:
If you specifically want the container to call an existing static factory method, you can use StaticFactoryExtension.
Why don't you use a factory.
Consider refactoring you design and removing the static method if possible.
While designing a service class should it be singleton in java? Generally DAO is made singleton, so should the calling Service class be made singleton also?
IMHO yes, services should not hold state and should therefore be made singleton.
Singletons are bad, if you develop them. If you are using dependency injection, let the DI container handle the singleton nature of your Service object. If you are not using dependency injection, use a static method instead of a singleton.
Classic example of bad:
public class HootUtility // singleton because developer was a goofball.
{
...
public void blammy(...) { ... }
public HootUtility getInstance() { ... }
}
... somewhere in the code.
HootUtility.getInstance().blammy(...); // This is silly.
Better implementation of the above:
public class HootUtility // Not a singleton because I am not a ______. (fill in the blank as you see fit)
{
// You can limit instantiation but never prevent instantiation.
// google "java reflection" for details.
private HootUtility()
{
throw new UnsuppotedOperationException();
}
public static void blammy(...) { ... }
}
... somewhere in the code.
HootUtility.blammy(...);
If you have a service interface that has an concrete implementation, use a dependency injection framework to inject the implementation (DI frameworks include: spring and guice).
Edit: If I was using spring, I would choose singleton scope (the default).
No
Actually I believe you shouldn't care about it while design. Like #DwB mentioned DI framework should do this job. Furthermore I believe no scope ("prototype") should be default and I don't see anything bad if somebody will create it itself.
Also that issue can be simplified by modularization and separating service interface and implementation like best practices told as to do.