question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

GuiceServletContextListener.getInjector should have one param: servletContext

See original GitHub issue

From gianmarco.gherardi on February 16, 2011 11:04:39

This way, configuration parameters can be passed as constructor parameter to object. For example, this is possible in normal Java application:

public static void main(String[] args) {   String fooServerAddress = args[0];   Injector injector = Guice.createInjector(new FooModule(fooServerAddress));   FooClient client = injector.getInstance(FooClient.class);   … }

In Servlet application this should became:

public class AppGuiceServletContextListener extends GuiceServletContextListener {   @Override   protected Injector getInjector(ServletContext servletContext) {     String fooServerAddress = servletContext.getInitParameter(“fooServerAddress”);     return Guice.createInjector(new FooModule(fooServerAddress));   } }

Check also comments on https://code.google.com/p/google-guice/wiki/FrequentlyAskedQuestions and thread on http://groups.google.com/group/google-guice/browse_thread/thread/dad68e87fd94261e

_Original issue: http://code.google.com/p/google-guice/issues/detail?id=603_

Issue Analytics

  • State:open
  • Created 9 years ago
  • Comments:5

github_iconTop GitHub Comments

2reactions
richmartincommented, Jul 9, 2014

It would indeed be a much nicer API if getInjector took a ServletContext parameter. The existing workaround of overriding contextInitialized and caching the value is clumsy and unintuitive. It also places the burden on the subclass of ensuring that the methods are invoked in the expected order and behaving sensibly if they are not.

This is especially critical given that the without this, the obvious way of getting a ServletContext is to @Inject it into a module, which leads to a deprecation warning and the possibility of bugs due to it being injected into singleton contexts.

It would have been really easy to have included this parameter when the class was first written, now of course the problem is how to include it without breaking existing users. Perhaps the cleanest option would be:

  1. make the existing getInjector method non-abstract and mark it as deprecated.
  2. add a new getInjector(ServletContext)
  3. if the old method returns null, call the new method.
  4. after a couple of years, kill the old method.

E.g.

public abstract class GuiceServletContextListener
    implements ServletContextListener {

static final String INJECTOR_NAME = Injector.class.getName();

public void contextInitialized(ServletContextEvent servletContextEvent) {
  final ServletContext servletContext = servletContextEvent.getServletContext();

  // Set the Servletcontext early for those people who are using this class.
  // NOTE(dhanji): This use of the servletContext is deprecated.
  GuiceFilter.servletContext = new WeakReference<ServletContext>(servletContext);

  Injector injector = getInjector();
  if (injector == null) {
    injector = getInjector(servletContext);
  }
  injector.getInstance(InternalServletModule.BackwardsCompatibleServletContextProvider.class)
      .set(servletContext);
  servletContext.setAttribute(INJECTOR_NAME, injector);
}

public void contextDestroyed(ServletContextEvent servletContextEvent) {
  ServletContext servletContext = servletContextEvent.getServletContext();
  servletContext.removeAttribute(INJECTOR_NAME);
}

/**
 * This method will be removed soon, please use getInjector(ServletContext) instead.
 */
@Deprecated
protected Injector getInjector() {
  return null;
}

/**
 * Override this method to create (or otherwise obtain a reference to) your
 * injector.
 *
 * @param servletContext the ServletContext of the current servlet.
 */
protected Injector getInjector(ServletContext context) {
  return null;
} 
}

This has the advantage that it exposes a cleaner API that makes it much easier to figure out where and how you should obtain the ServletContext whilst not breaking any existing users.

Additional: Ironically, a couple of hours after writing this comment, I found a bug in some of my code:

public class ServletConfig extends GuiceServletContextListener {
  private static final Logger log = ServerLogFactory.get();

  private ServletContext servletContext;

  @Override
  public void contextInitialized(final ServletContextEvent servletContextEvent) {
    super.contextInitialized(servletContextEvent);
    this.servletContext = servletContextEvent.getServletContext();
    log.info("ServletContext initialized.");
  }

  protected Injector getInjector() {
    log.info("Creating injector");
    return Guice.createInjector(
        new ApplicationModule(),
        new ConvertServletModule(servletContext));
  }
}

Can you spot it? I was getting a NullPointerException thrown from somewhere inside ConvertServletModule. The problem was that my contextInitialized method had,

  super.contextInitialized(servletContextEvent);
  this.servletContext = servletContextEvent.getServletContext();

instead of,

  this.servletContext = servletContextEvent.getServletContext();
  super.contextInitialized(servletContextEvent);

So when getInjector was being called from inside the implementation of super.contextInitialized, the servletContext field was still null.

I think that is a great example of why we should change this to make the API clear and explicit: you get the ServletContext passed to you in getInjector and can use it to construct the injector.

0reactions
gissuebotcommented, Jul 7, 2014

From gianmarco.gherardi on February 20, 2012 01:34:57

Any updates on this?

Read more comments on GitHub >

github_iconTop Results From Across the Web

GuiceServletContextListener.getInjector should have one param ...
Hi, Dhanji, How getInjector() get to know about the servletContext, when sometime we measure relative paths at that point? So, in my projects,...
Read more >
Issue 603 in google-guice: GuiceServletContextListener.getInjector ...
Status: New Owner: ---- New issue 603 by gianmarco.gherardi: GuiceServletContextListener.getInjector should have one param: servletContext
Read more >
How to get Google Guice working with JaxRS (Jersey)
Changed the ServletContextListener to package com.hillingar.server; import java.util.logging.Logger; import javax.servlet.
Read more >
com.google.inject.servlet Documentation Differences
Opens up the request scope until the returned object is closed. Implementations should ensureensure (e.g. by blocking) that multiple threads threads cannot open ......
Read more >
Guice - Dev Notes
Add the new module to the Guice servlet context listener, ... This code will inject itself with Guice to get instances of Flex...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found