⚠️ Migration & Compatibility Module — This module is not part of the GuicedEE foundation. It exists solely to assist projects migrating from Jakarta CDI-based frameworks to the native Guice-first model. New projects should use Google Guice annotations and APIs directly. GuicedEE's foundation is Guice, not CDI.
Lightweight Jakarta CDI compatibility bridge for GuicedEE applications migrating from CDI-based frameworks.
Maps CDI annotations (@Inject, @Named, @ApplicationScoped, @Qualifier) to their Guice equivalents, provides a BeanManager adapter backed by the Guice injector, and registers itself as the Jakarta CDIProvider — so existing CDI-annotated code runs seamlessly inside a Guice-managed container during migration.
For new projects: Use Google Guice annotations (
com.google.inject.Inject,@Singleton,@Provides, etc.) directly. This module is intended as a transitional bridge, not a permanent dependency.
Built on Google Guice · Jakarta CDI · JPMS module com.guicedee.cdi · Java 25+
<dependency>
<groupId>com.guicedee</groupId>
<artifactId>cdi</artifactId>
</dependency>Gradle (Kotlin DSL)
implementation("com.guicedee:cdi:2.0.2-SNAPSHOT")- CDI → Guice annotation mapping —
jakarta.inject.Inject,jakarta.inject.Named,jakarta.inject.Singleton, andjakarta.inject.Qualifierare mapped to their Guice counterparts automatically - Scope bridging —
@jakarta.inject.Singletonand@jakarta.enterprise.context.ApplicationScopedare bound to Guice'sSINGLETONscope viaBindScopeProvision BeanManageradapter —GuiceCDIBeanManagerAdapterimplementsjakarta.enterprise.inject.spi.BeanManagerand delegates toIGuiceContextfor bean resolutionCDIProviderregistration —JakartaCDIProvideris set as the JakartaCDIprovider on startup, soCDI.current()returns a Guice-backedGuicedCDIinstanceGuiceCDIBeanManager— simplified bean lookup API with support for type,@Namedqualifier, and annotation qualifier- SPI-driven wiring — five Guice SPI providers (
BindScopeProvider,InjectionPointProvider,BindingAnnotationProvider,NamedAnnotationProvider,InjectorAnnotationsProvider) are registered via JPMSprovides - Automatic module loading —
GuiceCDIModuleis discovered viaServiceLoader/ JPMS; no manual installation required - JPMS-first — full
module-info.javawith properexports,requires,provides, andusesdirectives
Step 1 — Add the dependency (see Installation above).
Step 2 — Annotate your classes with standard Jakarta CDI annotations:
@jakarta.enterprise.context.ApplicationScoped
public class GreetingService {
public String greet(String name) {
return "Hello, " + name + "!";
}
}Step 3 — Inject anywhere via @Inject:
public class WelcomeResource {
@jakarta.inject.Inject
private GreetingService greeter;
public String hello(String name) {
return greeter.greet(name);
}
}Step 4 — Declare the dependency in your module-info.java:
module my.app {
requires com.guicedee.cdi;
}Step 5 — Bootstrap GuicedEE:
IGuiceContext.registerModuleForScanning.add("my.app");
IGuiceContext.instance();
WelcomeResource resource = IGuiceContext.get(WelcomeResource.class);
resource.hello("World"); // "Hello, World!"The CDI module itself is loaded automatically — no JPMS provides declaration is needed in your application module.
flowchart TD
n1["Startup"]
n2["IGuiceContext.instance()"]
n1 --> n2
n3["IGuiceModule hooks"]
n2 --> n3
n4["GuiceCDIModule.configure()"]
n3 --> n4
n5["bind(GuiceCDIBeanManager.class) → Singleton"]
n4 --> n5
n6["bind(ICDIProvider.class) → GuiceCDIProvider<br/>Singleton"]
n4 --> n6
n7["bind(GuiceCDIBeanManagerAdapterImpl.class) → Singleton"]
n4 --> n7
n8["bind(BeanManager.class) → GuiceCDIBeanManagerAdapterImpl"]
n4 --> n8
n9["bind(JakartaCDIProvider.class) → Singleton"]
n4 --> n9
n10["CDI.setCDIProvider(new JakartaCDIProvider())"]
n4 --> n10
n11["Guice SPI providers<br/>auto-registered via JPMS"]
n2 --> n11
n12["BindScopeProvision → @Singleton, @ApplicationScoped → SINGLETON"]
n11 --> n12
n13["InjectionPointProvision → @Inject, @Named, @PostConstruct detection"]
n11 --> n13
n14["BindingAnnotationsProvision → @Qualifier as binding annotation"]
n11 --> n14
n15["NamedAnnotationProvision → jakarta.inject.Named → Guice Names.named()"]
n11 --> n15
n16["InjectorAnnotationsProvision → jakarta.inject.Inject recognition"]
n11 --> n16
CDI.current()
→ JakartaCDIProvider.getCDI()
→ GuicedCDI (singleton)
→ select(Class<T>)
→ IGuiceContext.get(Class<T>) ← Guice injector lookup
@Inject BeanManager beanManager
→ GuiceCDIBeanManagerAdapterImpl
→ getReference(bean, type, ctx) → IGuiceContext.get(type)
→ getInjectableReference(ip, ctx) → IGuiceContext.get(ip.getType())
→ createCreationalContext(...) → no-op implementation
The CDI module registers five Guice SPI providers that teach the Guice runtime how to handle Jakarta CDI annotations:
| SPI Interface | Implementation | Purpose |
|---|---|---|
BindScopeProvider |
BindScopeProvision |
Binds @jakarta.inject.Singleton and @ApplicationScoped to Guice's SINGLETON scope |
InjectionPointProvider |
InjectionPointProvision |
Detects @Inject, @Named, and @PostConstruct on annotated members |
BindingAnnotationProvider |
BindingAnnotationsProvision |
Registers @Qualifier as a Guice binding annotation marker |
NamedAnnotationProvider |
NamedAnnotationProvision |
Converts jakarta.inject.Named to com.google.inject.name.Names.named() |
InjectorAnnotationsProvider |
InjectorAnnotationsProvision |
Identifies jakarta.inject.Inject as an injector annotation |
Simplified bean lookup API backed by IGuiceContext:
@Inject
private GuiceCDIBeanManager beanManager;
// By type
MyService svc = beanManager.getBean(MyService.class);
// By type + @Named qualifier
MyService svc = beanManager.getBean(MyService.class, "primary");
// By type + annotation qualifier
MyService svc = beanManager.getBean(MyService.class, myQualifier);
// Check existence
boolean exists = beanManager.containsBean(MyService.class);Minimal jakarta.enterprise.inject.spi.CDI<Object> implementation. Returned by CDI.current() after the module sets the provider:
CDI<Object> cdi = CDI.current();
MyService svc = cdi.select(MyService.class).get();The Guice module that wires everything together. Loaded automatically via IGuiceModule SPI — sort order Integer.MAX_VALUE - 200 (loads after most modules).
flowchart LR
com_guicedee_cdi["com.guicedee.cdi"]
com_guicedee_cdi --> com_guicedee_client["com.guicedee.client<br/>SPI contracts — IGuiceModule, IGuiceContext"]
com_guicedee_cdi --> jakarta_cdi["jakarta.cdi<br/>Jakarta CDI API — BeanManager, CDI, CDIProvider"]
com_guicedee_cdi --> jakarta_el["jakarta.el<br/>Expression Language — required by BeanManager interface"]
Issues and pull requests are welcome — please add tests for new bridging behaviour or annotation support.