Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tomcat8 WebSockets (JSR-356) with Guice 3.0

I am trying to @Inject a Guice service into a @ServerEndpoint. I am using Tomcat 8.0.15 as the JSR-356 implementation. However, the dependency injection isn't working. Is there any additional configuration that needs to be done in order to enable Guice injection? Note that I am using all standard javax annotations only.

like image 391
Aritra Avatar asked Dec 16 '14 07:12

Aritra


2 Answers

I figured this out. The Websocket endpoint needs to have a custom configurator, which creates and returns instances using the Guice injector instance.

Example:

Custom Guice servlet context listener:

public class CustomServletContextListener extends GuiceServletContextListener { 
    public static Injector injector;

    @Override
    protected Injector getInjector() {
        injector = Guice.createInjector(...);
        return injector;
    }
}

Websockets custom configurator:

public class CustomConfigurator extends Configurator {
  @Override
  public <T> T getEndpointInstance(Class<T> clazz)
        throws InstantiationException {
    return CustomServletContextListener.injector.getInstance(clazz);
  }
}

And then in the Websocket endpoint:

@ServerEndpoint(value = "/ws/sample_endpoint", configurator = CustomConfigurator.class)
public class SampleEndpoint {
  private final SomeService service;

  @Inject
  public SampleEndpoint(SomeService service) {
    this.service = service;
  }
  ...
}
like image 131
Aritra Avatar answered Nov 06 '22 13:11

Aritra


Building upon Aritra's own answer:

To be honest, I don't know for sure if this works with Guice 3.0, but it does work for 4.0, which is the current stable release.

I think a somewhat cleaner approach is to change your CustomConfigurator into something like this:

public class CustomConfigurator extends Configurator {
    @Inject
    private static Injector injector;

    public <T> T getEndpointInstance(Class<T> endpointClass) {
        return injector.getInstance(endpointClass);
    }
}

And then from your extended ServletModule class' configureServlets method, call requestStaticInjection(CustomConfigurator.class)

That way you won't expose the injector to everyone. I don't know about you, but it gives me a nice and fuzzy feeling inside to know that no one will be able to mess with my injector :-).

like image 33
StanB123 Avatar answered Nov 06 '22 12:11

StanB123