Search code examples
websocketglassfish-4atmosphere

Atmosphere @ManagedService Injection fails with WebSockets


I'm having a problem using websocket transport when using Atmosphere. The code is shown below:

When I use long-polling as a transport, everything works fine. I'm able to call methods on the injected class without any problems. When I configure the client to use websocket, however, I end up getting a exception saying IllegalStateException: Singleton not set for org.glassfish.main.core.kernel and the method call fails. I suspect this is due to the way Atmosphere/Glassfish handles WebSockets outside the normal servlet (and therefore, ApplicationContext) environment.

@ManagedService(path = "/rt/test/{id}")
public class TestWebService {

    private @Inject TestWebController controller;

    @Get
    public void onGet(AtmosphereResource r) {
        Broadcaster b = controller.getBroadcaster(r.getRequest().getPathInfo(), true);
        if(b != null)
            r.setBroadcaster(b);
        else
            r.getResponse().setStatus("Invalid parameter", 400);
    }
}

Now the controller:

@ApplicationScoped
public class TestWebController {
    private @Inject IdValidator validator;

    public void eventHandler(@Observes MyEvent myEvent) {
        Broadcaster b = getBroadcaster(myEvent.getId(), false);
        if(b != null)
            b.broadcast(myEvent.getMessage());
    }

    public Broadcaster getBroadcaster(String id, boolean create) {
        if(validator.validate(id)) {
            Broadcaster b = BroadcasterFactory.getDefault().lookup(id);
            if(b == null && create)
                b = BroadcasterFactory.getDefault().get(id);

            return b;
        } 
        return null;
    }
}

I've tried different scopes for the controller and just about everything else. If I move the broadcaster create logic into the web service class, it works just fine (without the annotation) but then I loose the ability to validate the id which is somewhat important.

I'm using Glassfish 4 and Atmosphere 2.1.7 with atmosphere-runtime, atmosphere-annotations and atmosphere-cdi jars loaded.

I'm going to try the latest 2.2 release candidate but there are no mentions of any similar issues in the bug tracker so I'm not optimistic.

UPDATE: The same issue occurs with Atmosphere 2.2 RC3.

UPDATE: I was able to make this work by annotating the class with @javax.ejb.Stateful. I have not performed any substantial testing yet to see if there are any side effects but I am able to connect with a websocket and have confirmed that the injection happens correctly. I am using Atmosphere 2.2.0.


Solution

  • This is actually due to a shortcoming in the CDI spec: https://java.net/jira/plugins/servlet/mobile#issue/GLASSFISH-20468

    I've had to resort to long polling for now as a result, sadly.