eclipse-ee4j / eclipse-ee4j/tyrus
CdiComponentProvider ignores CDI scope: @ApplicationScoped/@Singleton @ServerEndpoint gets a new instance per connection
- Dominant language
- Java
- Stars
- 128
- Forks
- 49
- PR merge metrics
- No merged PRs in 30d
Description
**Module:** `tyrus-container-glassfish-cdi` (`org.glassfish.tyrus.gf.cdi.CdiComponentProvider`), Tyrus 2.2.2.
**Problem:** `create(Class)` always instantiates a fresh object via `InjectionTarget.produce()` regardless of the bean's scope. For a normal-scoped or `@Singleton` CDI endpoint this means the endpoint instance Tyrus uses is **not** the CDI contextual instance. Any state set in `@OnOpen` lives on the per-connection object, while `@Observes`/injected collaborators see the (separate) contextual bean — so e.g. a session registry populated in `@OnOpen` is invisible to a CDI observer broadcasting messages. Reported downstream at https://github.com/eclipse-ee4j/glassfish/issues/25316.
Current code:
```java
@Override
public Object create(Class c) {
if (managerRetrieved) {
AnnotatedType annotatedType = beanManager.createAnnotatedType(c);
InjectionTargetFactory injectionTargetFactory = beanManager.getInjectionTargetFactory(annotatedType);
InjectionTarget it = injectionTargetFactory.createInjectionTarget(null);
CreationalContext cc = beanManager.createCreationalContext(null);
T managedObject = (T) it.produce(cc); // fresh object, scope ignored
it.inject(managedObject, cc);
it.postConstruct(managedObject);
cdiBeanToContext.put(managedObject, new CdiInjectionContext(it, cc));
return managedObject;
} else {
return null;
}
}
```
**Expected:** when the endpoint class is a normal-scoped or singleton CDI bean, return its contextual reference so endpoint callbacks and CDI event delivery share one instance (matching how `EjbComponentProvider` returns the single EJB instance).
**Sketch:**
```java
Set> beans = beanManager.getBeans(c);
if (!beans.isEmpty()) {
Bean bean = beanManager.resolve(beans);
Class scope = bean.getScope();
if (scope == ApplicationScoped.class || scope == Singleton.class /* normal/singleton scopes */) {
CreationalContext cc = beanManager.createCreationalContext(bean);
return beanManager.getReference(bean, c, cc); // contextual instance
}
}
// else: existing InjectionTarget path for dependent/per-connection endpoints
```
Dependent-scoped endpoints should keep the current per-connection behavior, per the WebSocket spec default (one endpoint instance per connection).
**Repro:** https://github.com/hantsy/cargotracker (branch `ee11`), `mvn clean verify -P"arq-glassfish-managed" -D"it.test=RealtimeCargoTrackingServiceTest"`.
Contributor guide
Research direction
Start in tyrus-container-glassfish-cdi, at org.glassfish.tyrus.gf.cdi.CdiComponentProvider.create(Class), and compare its behavior with the EJB provider. Run the reported Cargotracker command to reproduce the issue. Done means normal-scoped and singleton endpoints use the CDI contextual instance while dependent endpoints retain per-connection behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100