Squarespace / jersey2-guice

Jersey 2.0 w/ Guice

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Getting a ServletContext

natros opened this issue · comments

I have some modules that needs a ServletContext. The problem is that JerseyGuiceServletContextListener#modules() is being called before JerseyGuiceServletContextListener#contextInitialized(). Is there any way to pass a ServletContext to a module.

I'm using apache shiro security framework with guice support. The ShiroWebModule needs a ServletContext
http://shiro.apache.org/static/1.2.1/apidocs/org/apache/shiro/guice/web/ShiroWebModule.html#ShiroWebModule(javax.servlet.ServletContext)

Try...

class MyContextModule extends com.squarespace.jersey2.guice.JerseyModule {
  @Override
  protected void configure() {
    bind(ServletContext.class).toProvider(ContextProvider.class);
  }

  private static class ContextProvider implements Provider<ServletContext>

    @Inject
    private Provider<ServiceLocator> locator;

    @Override
    public ServletContext get() {
      return locator.get().getService(ServletContext.class);
    }
  }
}

Make sure the binding is declared in a JerseyModule.

I don't think this is going to work. I need a instance of ServletContext inside the module.
With the jersey 1.x I override contextInitialized to get the servlet context.

public class MyListener extends GuiceServletContextListener {
    private ServletContext servletContext;

    @Override
    protected Injector getInjector() {
        return Guice.createInjector(new ShiroWebModule(servletContext));
    }

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        servletContext = servletContextEvent.getServletContext();
        super.contextInitialized(servletContextEvent);
    }
}

I'm trying this

public abstract class Jersey2GuiceServletContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent event) {
        ServiceLocator serviceLocator = BootstrapUtils.newServiceLocator();
        BootstrapUtils.newInjector(serviceLocator, stage(), modules(event.getServletContext()));
        BootstrapUtils.install(serviceLocator);
    }

    protected abstract Stage stage();

    protected abstract List<? extends Module> modules(ServletContext servletContext);

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }
}

and

public class GuiceListener extends Jersey2GuiceServletContextListener {
    @Override
    protected Stage stage() {
        return DEVELOPMENT;
    }

    @Override
    protected List<? extends Module> modules(ServletContext servletContext) {
        return newArrayList(new ShiroWebModule(servletContext));
    }
}

I see. The reason why this library isn't using contextInitialized is because it's called too late in the initialization chain. One part of your app gets potentially initialized with HK2's own ServiceLocator and the other half by this librarie's ServiceLocator.

A much safer approach is to use Jersey's own ServiceLocatorGenerator SPI (see JerseyServiceLocatorGeneratorSPI) or bootstrap it from a main() method (we do the latter). But neither of that is really helping you with ShiroWebModule. I think that class has a conceptual dependency problem.