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.
Related
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.
Im interested what is the proper manner to construct object with dependencies which themselves have #Assisted params. An example will better illustrate:
Ordinarilly with dependencies that do not have #Assisted params you can simply have a complex heirarchy of objects which all have their dependencies and these get injected no problem, I can just get an instance of an object and all its dependencies will be generated and injected without me having to do anything.
But if I wanted to change it so some of the dependencies in the object hierarchy have #Assisted params then I have to create those instances myself using a factory ie:
public SomeConcreteService(#Assisted String string) {
this.string = string;
}
MyFactory myFactory = injector.getInstance(MyFactory .class);
SomeService myService = factory.getMyService("some string");
This would cause problems for the clean instantiation of the objects because I would have to manually create those instances. and pass them into the required object, which essentially renders the DI for that object redundant I think???? ie I would then need to use the new keyword and pass in all dependencies manually...
new MyComplexObject(myService, myOtherService)
How do I make it so that I don't have to manually build the object graph if one or more of the dependencies uses #Assisted parameters?
The question you need to ask yourself is, "why am I making this #Assisted, and who is going to create these objects?"
If you use the key to get an instance you need, then what you have is fine:
public class YourInjectableClass {
#Inject private MyFactory factory;
public void doStuff(String key) {
// You have a key, and your factory, so you can create the instance yourself.
SomeService service = factory.getMyService(key);
// [...]
}
}
But if you use the key to get an instance create an instance to create an instance to get what you need, then that seems problematic. That might be a better problem for child injectors:
public class YourInjectableClass {
#Inject private Injector injector;
public void doStuff(String key) {
// You need an OuterObject. So rather than calling
// new OuterObject(new InnerObject(factory.getMyService(key))), do:
OuterObject outerObject =
injector.createChildInjector(new OuterObjectModule(key))
.getInstance(OuterObject.class);
// [...]
}
}
Because your value is needed throughout the dependency tree, you can treat it as an injected dependency. This can be a little more confusing, but saves you from letting your dependencies care about instantiation details all the way down the line.
Alternatively, you can create a manual OuterObjectFactory facade which does manually call new. This may be a better solution for legacy code, but can help to follow the Single Responsibility Principle by ensuring that one class is responsible for abstracting away instantiation details.
N.B. I'm assuming that SomeConcreteService takes other dependencies that the object graph can provide. If not, then there's no reason to use injection at all: Give SomeConcreteService a public constructor and call new SomeConcreteService("your value here") where needed. Though Guice takes some pains to abstract away the use of new, it is also unnecessary to create data objects or dependency-light objects like HashMap or Date.
We extend JAXBEqualsStrategy via pom:
<xjcArg>-Xequals-equalsStrategyClass=com.acme.foo.CustomEqualsStrategy</xjcArg>
The CustomEqualsStrategy extends JAXBEqualsStrategy. After running MAVEN clean install generate-source in Eclipse (Keplar) our model classes have equals method like this:
public boolean equals(Object object) {
final EqualsStrategy strategy = new CustomEqualsStrategy();
return equals(null, null, object, strategy);
}
Whereas if we do not extend JAXBEqualsStrategy, our model classes have equals method like this:
public boolean equals(Object object) {
final EqualsStrategy strategy = JAXBEqualsStrategy.INSTANCE;
return equals(null, null, object, strategy);
}
JAXBEqualsStrategy has
public static EqualsStrategy INSTANCE = new JAXBEqualsStrategy();
We expected to get
final EqualsStrategy strategy = CustomEqualsStrategy.INSTANCE;
in the generated equals method and are struggling to accomplish it.
You do not want to use CustomEqualsStrategy.INSTANCE. Using new CustomEqualsStrategy() is correct and should be preferred unless you have very good reasons for doing otherwise.
Since CustomEqualsStrategy extends JAXBEqualsStrategy, that means that unless you define your own INSTANCE field inside CustomEqualsStrategy, CustomEqualsStrategy.INSTANCE is the same as JAXBEqualsStrategy.INSTANCE, which means that you would be using an instance of JAXBEqualsStrategy after all.
Plus, using an INSTANCE field like that effectively signals that your class is meant to be used as a singleton, and thus has to be stateless. Most classes are not stateless, and even for classes that are, many such classes don't need to be used in a singleton style.
In short, really just stick with new CustomEqualsStrategy(). The code will have fewer surprises and you'll be happier for it. (Also, from reading the code for JAXBEqualsStrategy, perhaps you should be extending DefaultEqualsStrategy instead.)
Disclaimer: Plugin author here.
Actually, you can also get .INSTANCE or .getInstance()-calls generated as well. Please see this code:
https://svn.java.net/svn/jaxb2-commons~svn/basics/trunk/basic/src/main/java/org/jvnet/jaxb2_commons/plugin/util/StrategyClassUtils.java
So:
If the class of your equals strategy is known to the plugin in the runtime AND
Your class has a public static getInstance() method of the correct type OR
Your class has a public static field INSTANCE of the correct type
Then the plugin will use YourStrategy.getInstance() or YourStrategy.INSTANCE instead of new YourStrategy().
I guess you already have an INSTANCE method. Please try to include the JAR with your strategy into the XJC classpath (so that plugin could resolve your strategy class during the compile time).
Please also feel free to file an issue to support syntax like -Xequals-equalsStrategyInstanceField=com.acme.foo.CustomEqualsStrategy.INSTANCE or InstanceMethod accordingly.
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.
Background: I'm using Google Guice and so it's easier to pass through the configuration class but I think this is not the best way.
I have a configuration class which stores some paths:
class Configuration{
String getHomePath();
String getUserPath();
}
Also I have a class "a" which needs the "homepath" and a class "b" which needs the "userpath".
Is it better to pass the configuration class through the constructor of class a and b or only pass through the specific path?
If you're really using Guice correctly all your configuration like this should appear in modules' configure method. So:
Remove the configuration class.
Create annotation classes, probably called HomePath and UserPath.
Where class a uses getHomePath() replace that with a String field member named homePath.
Where class b uses getUserPath() replace that with a String field member named userPath.
Modify the class a and b constructors to be #Inject annotated (should already be) and take in a String parameter, respectively annotated with #HomePath and #UserPath and assign the String field member that injected value.
Create bindings in your module's configure method use .annotatedWith() which define correct values; if they're only available at run time, bind a provider.
E.G.
class a {
private String homePath;
#Inject
public a(#HomePath String homePath) {
this.homePath = homePath;
}
public String tellMeAboutHome() {
return "We live in a nice home called " + homePath;
}
}
class customModule extends AbstractModule {
public static final String userPath = "/home/rafael";
public void configure() {
bind(String.class).annotatedWith(HomePath.class).to("/home/");
bind(String.class).annotatedWith(UserPath.class).to(userPath);
}
}
If creating annotations is too much work for you, use the #Named annotation Guice ships with.
There's no single answer to your question, there are only options to choose from, based on your specific situation.
If you know your Configuration class is going to grow AND if it's likely for your A and B classes will use more from it, then pass the whole Configuration object to their constructors. NB: I know this is against the YAGNI principle but sometimes you may know you're gonna need it ;-)
Otherwise, you can consider using #Named injection of your paths so that you reduce A and B classes dependencies to their minimum, which is a good design practice.
The general rule is code to make the dependency graph (which classes know about or depend on other classes/ interfaces) as simple, regular and fixed as possible.
If not passing the Configuration class makes a or b have zero dependencies on on user-written classes, or is necessary to avoid a dependency loop, then use the individual path strings. Otherwise, if it makes more sense to say 'this class has access to configuration info, in a way that may change in the future', pass the class.
I'd avoid the singleton approach, especially if you already have Guice set up.