Gupta.Swap
Gupta.Swap

Reputation: 265

Guice - Use injected field inside of constructor

Is there a way I can use a injected fields inside of a default constructor? Below is the pseudo code -

public class SomeClass() {
    @Inject private SomeField someField;
    @Inject private SomeOtherField someOtherField;

    private SomeImportantObject someImportantObject;

    public SomeClass() {
        SomeBuilder
            .get()
            .withFieldValue( someField.getValue() )
            .withSomeOtherFieldValue( someOtherField.getValue() )
            .build();
    }
}

Now the problem that I am facing is that when I call injector.getInstance( SomeClass.class ), I get a NullPointerException.

Caused by: java.lang.NullPointerException
    at com.something.something.SomeClass.<init>(SomeClass.java:10)

Now I understand that this is happening because the default constructor is called before the dependencies are inject.

But, is there any way that the dependencies could be injected before?
Or, is there a better to do this?

Note, I do not want to inject these dependencies using constructor as I am expecting around 20-30 of such fields.

Upvotes: 0

Views: 1288

Answers (2)

Makoto
Makoto

Reputation: 106400

Dependencies can only be realistically injected after initialization in the case of a no-arg constructor, or at initialization in the case of a constructor with arguments.

What this means is that, in its current state, your code isn't going to work with DI since you want to build something out at initialization.

Of course, this begs the question of the design; this doesn't seem like a great idea even with DI. Suppose at initialization, your builder threw an exception. Your object would be in a wonky partially-initialized state and it wouldn't be entirely useful to you.

With that, I'd strongly encourage you to move your builder out of your constructor. Once it's out, then it doesn't matter if you're using DI or not, and either DI pattern (constructor or field or setter) would work for you.

Upvotes: 1

homerman
homerman

Reputation: 3569

if those fields are being injected purely to be used by SomeBuilder to produce SomeImportantObject, then:

  • inject an instance of SomeBuilder that already has those fields set, or
  • inject the instance of SomeImportantObject.

i understand your desire to avoid bloating the constructor with too many arguments. in this case i'd look to see if those properties could be logically grouped into a few (or a single) new type that instead be passed as constructor parameters.

Upvotes: 1

Related Questions