Guice inject based on scope - java

In my scenario I have a BaseObject which is an interface and then a BaseObjectImpl.
Then I have two clients, ClientA and ClientB which both reference BaseObjectImpl with the minor different being that the constructor argument to BaseObjectImpl should change depending on which client is using it. The setup looks like this:
BaseObject:
public interface BaseObject {
void doAction();
}
BaseObjectImpl:
public class BaseObjectImpl implements BaseObject {
#Inject
public BaseObjectImpl(RandomInjectedObject random, String inputString) {
this.inputString = inputString;
}
public void doAction() {
// print input string
}
Now for the clients:
ClientA:
public class ClientA {
#Inject
public ClientA(BaseObject baseObject) {
this.baseObject = baseObject;
}
ClientB:
public class ClientB {
#Inject
public ClientB(BaseObject baseObject) {
this.baseObject = baseObject;
}
Now the issue is that when inside my ClientAModule I want to provide the inputString argument such that it is set to clientAString and inside ClientBModule I want to provide clientBString instead.
What is the best way to go about doing this? Note that the BaseObjectImpl takes in two arguments (the other one has the same definition for both clients).
What I tried doing was inside the BaseObjectModule class that I have defined, I created a Builder inside which I could set a specific annotation and set a specific inputString. Then inside my Client<AB>Module I created a different BindingAnnotation in each of them. Then when I installed the BaseObjectModule I did so using the builder and each passed in their specific BindingAnnotation and inputString.
Then I try to bind the BindingAnnotation / inputString scope to a Provider for BaseObject is that I try to instantiate the BaseObjectImpl with the corresponding inputString and the injected RandomInjectedObject which I've provided also in the BaseObjectModule. I get an error saying:
This Provider cannot be used until the Injector has been created because I haven't created the injector inside the module itself.
I was looking at AssistedInjection so that I could make it so I just passed in the inputString at this time, but the problem is I still need the injector for that.

Related

Passing one instance of an object to different classes without using static or singleton

I am trying to figure out a way to pass one instance of the same class to multiple classes so I am able to build an object. The problem is it cannot be static or use singleton because many users will be hitting the application at the same time and I may run into other issues. Are there any design patterns that would work best with this scenario or if there is some way to use global variables in java? I am trying implement this with an existing rest service that was not designed very well.
public class OneInstanceOf
{//I want to build this map object without static
private Map<String, String> mapIwantToBuild = new HaspMap<String, String>();
public void methodIwantToCall(String name, String value)
{mapIwantToBuild.put(name, value)
}
The common pattern for you task is dependency injection. You can use spring framework for that task.
1.Create configuration with your bean:
#Configuration
public class YourConfiguration {
#Bean
public OneInstanceOf oneInstanceOf {
return new OneInstanceOf();
}
}
2.Inject your bean whatever you want (simplest - use autowiring):
#Component
public class Client1 {
#Autowire
private OneInstanceOf oneInstanceOf;
public void someMethod() {
oneInstanceOf.methodIwantToCall();
}
}
Spring will insure single instance of oneInstanceOf will be injected in all clients.
U can create a setter with parameter of instance class variable, in every class in which you want to pass the instance. Then create a method in one of the classes that calls setter of all those classes and pass parameter instance as parameter to that method.
Like below.
class A{
B b = new B;
set(B b){
C.setB(b);
D.setB(b);
E.setB(b);
}
}

Guice: instantiating a singleton before creating the module

Is it possible to instantiate and assign a singleton to a reference with Guice before creating the Module and pass that instance to the Module constructor be bound during configuration?
Here is an example of what I mean:
I have a method that allows me to create objects depending on a custom implementation of an interface which is being passed in constructor as an Optional (if the user won't provide a custom implementation, we will use the default one), which is being done by binding the interface to that particular implementation in the Module class. :
public static MyClass createMyClassObject(Optional<SpecialInterface> customSpecialInterfaceObject) {
SpecialInterface specialInterfacebject;
if(customSpecialInterfaceObject.isPresent() {
specialInterfaceObject = customSpecialInterfaceObject.get()
} else {
/* here I would like to bind it to an instance of the DefaultSpecialInterfaceObject but can't really do something like:
Injector injector = Guice.createInjector(myClassModule);
DefaultSpecialInterface instance = injector.getInstance(DefaultSpecialInterface.class);
as the module is yet to be created */
}
MyClassModule myClassModule = new MyClassModule(specialInterfaceObject);
Injector injector = Guice.createInjector(myClassModule);
return injector.getInstance(MyClass.class);
}
I'm currently using classes instead of instances to solve this problem, such as in the example below, but I don't quite like this solution. Would be happy to see a better way of doing it:
private static Class resolveSpecialInterfaceObject(Optional<SpecialInterface> customSpecialInterfaceObject) {
Class specialInterfaceObjectClass;
if (customSpecialInterfaceObject.isPresent()) {
specialInterfaceObjectClass= customSpecialInterfaceObject.get().getClass();
} else {
specialInterfaceObjectClass = DefaultSpecialInterface.class;
}
return specialInterfaceObjectClass;
}
public abstract class MyClassModule extends AbstractModule {
private final Class<SpecialInterface> specialInterfaceObjectClass;
public MyClassModule(Class<SpecialInterface> specialInterfaceObjectClass) {
this.specialInterfaceObjectClass= specialIntefaceObjectClass;
}
#Override
protected void configure() {
bind(SpecialInterface.class).to(specialInterfaceObjectClass);
}
}
Edit, from a comment below:
one more thing- didn't want to make the question too long; actually, I also want to perform another operation on the resulting instance of SpecialInterface, but only if it is the instance of DefaultSpecialInterface and I don't think it should be done in the Module. I was thinking if I could just have this bean up and running before, such as in Spring, so I could just pass it to the Module, but also use it in another method call before?
Can you take the whole Optional and use bind(...).toInstance(...)?
public static MyClass createMyClassObject(
Optional<SpecialInterface> customSpecialInterfaceObject) {
MyClassModule myClassModule = new MyClassModule(customSpecialInterfaceObject);
Injector injector = Guice.createInjector(myClassModule);
MyClassFactory instance = injector.getInstance(MyClassFactory.class);
return instance.createMyClassObject();
}
class MyClassModule extends AbstractModule {
private final Optional<SpecialInterface> customObject;
MyClassModule(Optional<SpecialInterface> customObject) {
this.customObject = customObject;
}
#Override public void configure() {
if (customObject.isPresent()) {
// Singleton by necessity: Guice doesn't know how to create another one.
bind(SpecialInterface.class).toInstance(customObject.get());
} else {
// Default scoped. Add ".in(Singleton.class)" if necessary.
bind(SpecialInterface.class).toInstance(DefaultSpecialInterfaceClass.class);
}
}
}
If you want to perform additional initialization on DefaultSpecialInterface and nothing else, you have a number of options:
If some kind of initialization is important for all implementations and likely too heavy to put into a class constructor, add an initialize method on your SpecialInterface. Make the custom one a no-op, and implement it for DefaultSpecialInterface.
If the initialization is unique to DefaultSpecialInterface, I see no reason why it shouldn't be in the Module. Write a #Provides method or bind to a Provider<SpecialInterface> that creates and initializes DefaultSpecialInterface correctly.
If your real goal is to keep the business logic out of a Module, you can do so by extracting it into a free-standing Provider or DefaultSpecialInterfaceFactory that is responsible for that.
Remember, Guice is responsible for feeding fully-constructed objects into your object graph, and that means that injecting a SpecialInterface should get a ready-to-use implementor of the SpecialInterface general contract. If Guice needs to perform some initialization to make that happen, it's not unreasonable to have it do so, and a Module isn't a bad place to do it.

Inject a different Spring bean depending on a target class

Say I have this:
interface Something {
}
interface Fetcher {
}
class FetcherImpl implements Fetcher {
private final Class<?> klass;
public FetcherImpl(Class<?> klass) {
this.klass = klass;
}
public Something fetch() {
// Fetch an instance Something depending on the klass
}
}
class ClassA {
private final Fetcher fetcher;
public ClassA(Fetcher fetcher) {
this.fetcher = fetcher;
}
public void someMethod() {
// ...
Something something = fetcher.fetch();
// ...
}
}
class ClassB {
private final Fetcher fetcher;
public ClassB(Fetcher fetcher) {
this.fetcher = fetcher;
}
public void someMethod() {
// ...
Something something = fetcher.fetch();
// ...
}
}
So, the idea is:
I have an data class, Something
I have a fetcher for that data class, Fetcher, that fetches it depending on the class. For example, it creates it depending on the contents of the file from the path /tmp/<class-name>.txt
There are a lot of classes that are using (their respective instance of) the fetcher, ClassA and ClassB in the above example
Some important points:
All clients of the fetcher are doing constructor injection, i.e. using a final field to store the fetcher. Thus bean post processors cannot be used
The set of classes using the fetcher is an open one
The creation of the fetcher instances should not be manually configured. I.e. when adding a class ClassC above that uses its own instance of the fetcher similar to ClassA and ClassB, there should not be additional Spring configuration for that particular class
Some real world examples of a similar pattern:
Loggers, e.g. instead of using
final Logger logger = LoggerFactory.getLogger(this.getClass())
the logger would be injected via the constructor
Cache implementations (i.e. get a cache for a specific class)
DAO objects (i.e. get a DAO for a particular bean, provided it can be generic enough)
Is this possible using Spring? If so, can you please provide some pointers or similar examples that I can read through? I am using Java configuration for Spring if that matters.

Guice assisted inject overuse alternatives, dependency injection vs non-DI constructors

The main reasons I like passing in runtime dependencys in constructors are:
It makes the dependency required
It provides a central place to set instance variables
Setting the dependency as an instance variable prevents you from
having to pass it around from method to method within the class or pass it in twice or more
to two or more public methods
This has led me to use a lot of Assisted Injects when using Guice. This creates extra code compared to not using DI so reading things like this:
How exactly is Assisted-inject suppose to be use to be useful?
It seems like most people don't pass the runtime(derived, not available at startup) dependencies in constructors using assisted inject, and instead pass them in individual methods. Thats fine for the simple class given in the above stackoverflow post where there is only one method that relies on the dependency:
public class SomeClass {
#Inject
SomeClass(...) {
...
}
public void doWork(int s) { /* use s */ ... }
}
But what if the class has many methods that use the dependency? Do you pass it from the public method to private methods and require it passed in on all public methods?
For example:
public class SomeClass {
#Inject
SomeClass(...) {
...
}
public void doWork(int s) {
/*some code */
someOtherMethod(s);
anotherMethod(s);
}
//any private method that needs it gets it passed in as a param
private void someOtherMethod(int s)...
private void anotherMethod(int s)...
//require it passed in all public methods that need it
public void anotherPublic(int s){
someOtherMethod(s);
}
}
As opposed to using constructors this adds a bit of extra code as seen here:
public class SomeClass {
private int s;
SomeClass(int s) {
this.s = s;
}
public void doWork() {
someOtherMethod();
anotherMethod();
}
private void someOtherMethod()...
private void anotherMethod()...
public void anotherPublic(){}
}
Or would you set the instance var from the service method like this?
public class SomeClass {
Integer s;
#Inject
SomeClass(...) {
...
}
public void doWork(Integer s) {
/***set instance var this time***/
this.s = s;
someOtherMethod();
anotherMethod();
}
private void someOtherMethod()...
private void anotherMethod()...
public void anotherPublicMethod(){
if(s==null){ //check if s was set already
throw new IllegalStateException();
}else{
/* do something else */
}
}
}
Or would you pass the dependency into the other public method as a param and set the instance var there as well? For Example:
public class SomeClass {
#Inject
SomeClass(...) {
...
}
public void doWork(Integer s) {
/***set instance var this time***/
this.s = s;
someOtherMethod();
anotherMethod();
}
private void someOtherMethod()...
private void anotherMethod()...
public void anotherPublicMethod(Integer s){
this.s = s;
/* do something else */
}
}
So I think passing the param from method to method or throwing illegal state exceptions to check for it isn't ideal compared to using normal constructors, but obviously there are advantages/disadvantages to any framework/pattern.
If I am just not separating my objects in the ideal way, please let me know some guidelines you use, ie "I only use one public method per service class, see this book or post about it:.." .
What do you guys do in the above situations?
You nailed down some great reasons to use assisted injection in your question: It ensures that the object instances only ever exist in a fully-initialized state, keeps your dependencies together, and frees the object's public interface from requiring a predictable parameter in every method.
I don't really have any alternatives to add, other than the ones you mentioned:
Adding a setter method for that dependency, probably requiring IllegalStateException checks or a good default value
Creating an initialize(int s) pseudoconstructor method with the same IllegalStateException checks
Taking in the parameter in individual methods
Replacing the FactoryModuleBuilder boilerplate with a custom factory, thereby creating more extra boilerplate you're trying to avoid
My favorites are the two you seem to be deciding between--assisted injection or taking the parameter in every method--mostly because they both keep the object in a predictable, usable state at all times. My decision between them rests on what kind of state the object should carry, whether that state is mutable, and how I want to control instances. For Car.licensePlateNumber, the license plate number may vary with the car instance; each car has one license plate number that (in this example) never varies, and the car isn't valid without it, so it should be a constructor argument. Conversely, Repository<T> may frequently take in the same T instance in all of its methods, but a Repository is still a Repository no matter which instance you pass in, and you may want the freedom to reuse that instance without creating a new one for each T (as you may have to do with assisted injection). Both designs are valid, and each one is optimal for a certain set of cases.
Remember that there shouldn't really be that much extra code required for assisted injection:
/** In module: install(new FactoryModuleBuilder().build(SomeClass.Factory.class)); */
public class SomeClass {
public interface Factory {
SomeClass create(int s);
}
private final int s;
#Inject
SomeClass(/* ..., */ #Assisted int s) {
this.s = s;
}
public void doWork() { /* ... */ }
}

Using methods from a subclass on an object that is an instance of the superclass

Let's say there's a class that I use extensively and is returned by a method.
CommonClass obj = getCommonObject();
Now I want to extend this class to create some utility method to avoid repeating myself.
public CommonClassPlus extends CommonClass {
public String dontRepeatYourself() {
// the reason I'm creating a subclass
}
}
Of course I would like to use my improved class for the method above, however, downcasting isn't allowed.
CommonClassPlus obj = getCommonObject();
//Cannot cast to CommonClassPlus
How can I use the method dontRepeatYourself() if I can only work with the object that is an instance of the superclass?
CommonClass and getCommonObject() are from an external library and I cannot change them.
You cannot add behavior to an existing instance in Java (like you could in JavaScript, for example).
The closest you can get in Java is the Decorator pattern:
CommonClassPlus obj = decorate(getCommonObject());
where decorate() is
public CommonClassPlus decorate(CommonClass x) {
return new CommonClassPlus(x);
}
This approach creates a potentially huge amount of boilerplate because it must delegate each method call to the wrapped instance. If a method in CommonClass is final and there is no interface you can reimplement, then this approach fails altogether.
In most cases you will be able to get along with a simple static helper method:
public static String dontRepeatYourself(CommonClass x) {
...
}
If CommonClass is from an external library, you probably want to wrap it in an Adapter Pattern anyway, using the principle of Composition over Inheritance.
This gives you complete control if you want to, say, change the library you're using, and allows you to add functionality like dontRepeatYourself().
public class CommonClassAdapter implements MyAdapter {
private final CommonClass common;
private final String cachedResult;
// Note that I'm doing dependency injection here
public CommonClassAdapter(CommonClass common) {
this.common = common;
// Don't expose these because they shouldn't be called more than once
common.methodIOnlyCallOnce();
cachedResult = common.anotherMethodIOnlyCallOnce();
}
#Override
public void someMethod() {
common.someMethodWithDifferentName();
}
#Override
public String dontRepeatYourself() {
return cachedResult;
}
}
Note also that most modern IDEs have things like Eclipse's Source -> Generate Delegate Methods to make this process faster.

Categories