governator icon indicating copy to clipboard operation
governator copied to clipboard

WIP: ConditionalBinder

Open elandau opened this issue 9 years ago • 1 comments

The ConditionalBinder enables specifying multiple candidates for a binding with each having a condition that can be based on configuration or other state. ConditionalBinder follows an implementation very similar to Multibinder in that all bindings are created with custom annotations and are resolved at injector creation time.

For example,

public class SnacksModule extends AbstractModule {
    protected void configure() {
        ConditionalBinder<Snack> conditionalbinder
          = ConditionalBinder.newConditionalBinder(binder(), Snack.class);
        conditionalbinder.when(new ConditionalOnProperty("type", "twix")).toInstance(new Twix());
        conditionalbinder.when(new ConditionalOnProperty("type", "snickers")).toProvider(SnickersProvider.class);
        conditionalbinder.when(new ConditionalOnProperty("type", "skittles")).to(Skittles.class);
        conditionalbinder.whenNone().to(Carrots.class);
     }
}

The following situations are not valid and result in a CreationException error at injector creation (not injection) time. The exception will contain detailed information on the candidate bindings and where in code they were bound

  • Multiple matching candidates
  • No matched candidates
  • Multiple default bindings specified
  • Using conditional binding in Stage.PRODUCTION

Several approaches were considered for implementing this feature, including a Module annotation based approach. The benefits of this approach are,

  • Follows Guice conventions (such as Multibinder and MapBinder)
  • Does not require Module post processing (which would complicate usage)
  • Makes conditional processing injectable

Drawbacks to this approach are,

  • Does not work in Stage.PRODUCTION (results in unmatched conditionals being instantiated). Allowing this to run in production stage is possible but would add complexity that may not be necessary since we run only in the lazy Stage.DEVELOPMENT. We can revisit this if running in Stage.PRODUCTION becomes are requirement.
  • Unmatched conditionals result in unused bindings

elandau avatar Dec 11 '15 18:12 elandau

I didn't see any unit tests that use the @Conditional[Anything]; annotation-based conditionals are supported yes?

tcellucci avatar Nov 22 '16 22:11 tcellucci