Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optional injection in Guice

Tags:

java

guice

Is it possible to tell Guice that it's not necessary to inject all constructor arguments? For example, I have a constructor Foo that takes two args of types Bar and Baz. All of them are optional in my system: they may

  1. both present
  2. both missing
  3. only Bar present
  4. only Baz present.

That said, it depends on other modules providing these bindings. I want to get something like this:

class Foo {
  private final Bar bar;
  private final Baz baz;

  @Inject(optional = true)
  public Foo(@Nullable Bar bar, @Nullable Baz baz) {
    this.bar = bar;
    this.baz = baz;
  }
}

But I can't really use optional with constructors. Is there a way to do that?

like image 785
Vladimir Kostyukov Avatar asked Mar 19 '15 23:03

Vladimir Kostyukov


People also ask

Can Guice inject null?

Guice forbids null by default So if something tries to supply null for an object, Guice will refuse to inject it and throw a NULL_INJECTED_INTO_NON_NULLABLE ProvisionException error instead. If null is permissible by your class, you can annotate the field or parameter with @Nullable .

What does @inject do in Guice?

Note that the only Guice-specific code in the above is the @Inject annotation. This annotation marks an injection point. Guice will attempt to reconcile the dependencies implied by the annotated constructor, method, or field.

What is @named annotation in Guice?

Guice comes with a built-in binding annotation @Named that takes a string: public class RealBillingService implements BillingService { @Inject public RealBillingService(@Named("Checkout") CreditCardProcessor processor, TransactionLog transactionLog) { ... }

What is dependency injection Guice?

Guice is an open source, Java-based dependency injection framework. It is quiet lightweight and is actively developed/managed by Google. This tutorial covers most of the topics required for a basic understanding of Google Guice and to get a feel of how it works.


2 Answers

I think the preferred Guice pattern for this is:

public class HolderPatter {

  static class Bar {
    @Inject Bar(BarDependency dependency) {}
  }
  static class Baz {
    @Inject Baz(BazDependency dependency) {}
  }

  static class BarHolder {
    @Inject(optional=true) Bar value = null;
  }

  static class BazHolder {
    @Inject(optional=true) Baz value = null;
  }

  static class Foo {
    private final Bar bar;
    private final Baz baz;

    @Inject
    public Foo(BarHolder bar, BazHolder baz) {
      this.bar = bar.value;
      this.baz = baz.value;
    }
  }
}

Note that this will also allow you to specify sane default values...

like image 91
condit Avatar answered Sep 18 '22 10:09

condit


The latest version of Guice recently added OptionalBinder which works better than the @Inject(optional=true) method and also adds several advanced features.

See also the thread where OptionalBinder was announced.

like image 44
Daniel Pryden Avatar answered Sep 18 '22 10:09

Daniel Pryden