How does EK9 DI compare to Google Guice modules?
← Dependency Injection · Ref: Q329
Google Guice uses Module classes with bind() statements to configure injection. EK9's 'defines application' with 'register' statements serves the same purpose but with compile-time validation.
GUICE MODULES VS EK9 APPLICATIONS
Guice:
class AppModule extends AbstractModule { @Override void configure() { bind(Service.class).to(ServiceImpl.class); } }
EK9:
defines application MyApp register ServiceImpl() as Service
KEY DIFFERENCES
1. VALIDATION TIMING: Guice validates at Injector creation (runtime). EK9 validates at compilation.
2. JUST-IN-TIME BINDINGS: Guice can create instances without explicit bindings (JIT). EK9 requires explicit registration for every injection point.
3. LINKED BINDINGS: Guice chains bind(A).to(B).to(C). EK9 registers concrete against abstract directly.
4. SCOPES: Guice has @Singleton, @RequestScoped, custom scopes. EK9 has singleton only.
5. PROVIDERS: Guice has Provider<T> for lazy/deferred creation. EK9 creates all components eagerly in prepare phase.
WHY NO JIT BINDINGS
Guice's JIT bindings mean a class with @Inject constructor can be injected without any bind() call. This is convenient but dangerous: it hides dependencies and makes the object graph unpredictable. EK9 requires every injection point to have an explicit registration.
INSTALLING MODULES
Guice composes modules: install(new DatabaseModule()). EK9 does not compose applications — each application is self-contained. If you need shared registrations, define shared components and register them in each application.
See Q227 for compile-time validation. See Q228 for registration ordering. See Q324 for injection syntax. See Q330 for scope comparison.
Example
defines module qa.di.guice.comparison defines component PaymentGateway as abstract charge() as abstract -> amount as String <- receipt as String? default operator ? StripeGateway is PaymentGateway override charge() -> amount as String <- receipt as String: "Stripe charged: " + amount default operator ? OrderProcessor as abstract process() as abstract -> orderId as String <- confirmation as String? default operator ? DefaultOrderProcessor is OrderProcessor gateway as PaymentGateway! override process() -> orderId as String <- confirmation <- String() confirmation: gateway.charge("100.00 for " + orderId) default operator ? defines application <?- This replaces Guice's AbstractModule.configure(). register replaces bind().to(). -?> GuiceEquivalentApp register StripeGateway() as PaymentGateway register DefaultOrderProcessor() as OrderProcessor defines program GuiceComparisonDemo() with application of GuiceEquivalentApp stdout <- Stdout() // === EXPLICIT REGISTRATION REPLACES bind().to() === processor as OrderProcessor! result <- processor.process("ORD-001") stdout.println(result) stdout.println("Application registration replaces Guice modules")
Common mistakes
E08150 — Unlike Guice which supports JIT bindings to concrete types, EK9 requires injection fields to use abstract component types. Explicit registration maps concrete to abstract. See ek9 -h E08150 for details.
Incorrect:
gateway as StripeGateway!
Correct:
gateway as PaymentGateway!
E08210 — Removing the PaymentGateway registration leaves DefaultOrderProcessor's injection field unsatisfied. Unlike Guice JIT bindings, EK9 requires every injection point to have an explicit registration. See ek9 -h E08210 for details.
Incorrect:
register DefaultOrderProcessor() as OrderProcessor
Correct:
register StripeGateway() as PaymentGateway register DefaultOrderProcessor() as OrderProcessor
Other ways to ask this
- What replaces Guice modules and bindings in EK9?
- How is EK9 injection different from Google Guice?
- Does EK9 have something like Guice's AbstractModule?
Coming from another language?
Google Guice: AbstractModule.configure() with bind().to() statements, @Provides methods, just-in-time bindings, Injector creation validates at runtime, Multibinder for collections, @Singleton scope. Dagger: compile-time DI for Android, @Component/@Module annotations. EK9: 'defines application' with 'register' statements, compile-time validation, no JIT bindings, explicit registration required, singleton scope only.
Keywords: inject, google, injector, bind, explicit, dagger, provider, guice, jit, dependency, migration, module