Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java constructor with Guice injected fields along with non-injected fields

I have a class which has a constructor where all the arguments are injected by GUICE.

Public class Order {

    private final ClassOne classOneObj;
    private final ClassTwo classTwoObj;

    @Inject
    public order(ClassOne classOneObj, ClassTwo classTwoObj){
    this.classOneObj = classOneObj;
    this.classTwoObj = classTwoObj;
    }
}

Now, I want to add one more field(say, int status)variable which can't be injected.

Is it a good practice to create an object first with all the injected parameters and then set the new field which can't be injected with a setter method?

I came up with another approach where I created a factory class as given below:

public class OrderFactory {

    private final ClassOne classOneObj;
    private final ClassTwo classTwoObj;

    @Inject
    public order(ClassOne classOneObj, ClassTwo classTwoObj){
    this.classOneObj = classOneObj;
    this.classTwoObj = classTwoObj;
    }

   //getter methods for all the above variables

    public  ClassOne getclassOneObj(){
          return classOneObj;
    }
    ....

    public Order createOrder(int status) {
        return new Order(status, classOneObj, classTwoObj);
    }
}

Then the new Order class will look like

public class Order {

    int status
    private final ClassOne classOneObj;
    private final ClassTwo classTwoObj;


    public order(int status, ClassOne classOneObj, ClassTwo classTwoObj){
    this.status = status
    this.classOneObj = classOneObj;
    this.classTwoObj = classTwoObj;
    }

    //getter methods for all these member variables
}

Now to create the order object I will first create an OrderFactory object and then using the "createOrder" method I will create the Order object.

I am ending up with writing boilerplate code. Not sure if this is a good practice. Can anybody suggest on this if this approach is correct or there is any better approach for this problem?

I read in Google Guice and found there is a feature @Assisted for assisted injection for such cases. But I found that complex and couldn't convince myself whether I should go with that in my case.

Thanks in advance for any suggestion or guidance.

like image 401
Nil Avatar asked Oct 21 '22 21:10

Nil


1 Answers

Your factory approach is excellent. Please don't use the setters: if the field can be made immutable, it should be immutable, whether or not it makes it "convenient" to instantiate.

Another approach you can take is Assisted Injection, which solves this exact problem. With that, you only define the factory interface, and its implementation is magically given to you by Guice:

class Order {
  interface Factory {
    Order create(Status status);
  }

  @AssistedInject Order(
      ClassOne one, 
      ClassTwo two, 
      @Assisted Status status) {
  }
}

Module code:

bind(Order.Factory.class).toProvider(
    FactoryProvider.newFactory(Order.Factory.class, Order.class));

Then the clients inject Factory and use it just like they do in your example.

like image 182
iluxa Avatar answered Oct 24 '22 04:10

iluxa