My favorites | Sign in
Google
                
Search
for
Updated Nov 10, 2009 by dhanji
ServletModule  
Using Guice Servlet and Binding Language

Installing a Servlet Module

Once you have GuiceFilter up and running, Guice Servlet is set up. However, you will need to install an instance of ServletModule in order to get real use out of Guice Servlet:

   Guice.createInjector(new ServletModule());

This module sets up the request and session scopes, and provides a place to configure your filters and servlets from. While you are free to create the injector from any place of your choice, a logical place to do it in is a ServletContextListener.

A ServletContextListener is a Java servlet component that is triggered as soon as a web application is deployed, and before any requests begin to arrive. Guice Servlet provides a convenience utility that you can subclass in order to register your own ServletContextListeners:

public class MyGuiceServletConfig extends GuiceServletContextListener {

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

Next, add the following to web.xml so the servlet container triggers this class when the app is deployed:

<listener>
  <listener-class>com.example.MyGuiceServletConfig</listener-class>
</listener>

You can now use Guice Servlet as per your needs. Note that it is not necessary to use a ServletContextListener to use Guice Servlet, as long as you remember to install ServletModule when creating your injector.

The Binding Language

Think of the ServletModule as an in-code replacement for the web.xml deployment descriptor. Filters and servlets are configured here using normal Java method calls. Here is a typical example of registering a servlet when creating your Guice injector:

   Guice.createInjector(..., new ServletModule() {

     @Override
     protected void configureServlets() {
       serve("*.html").with(MyServlet.class)
     }
   }

This registers a servlet (subclass of HttpServlet) called MyServlet to serve any web requests ending in .html. You can also use a path-style syntax to register servlets as you would in web.xml:

       serve("/my/*").with(MyServlet.class)

Filter Mapping

You may also map Servlet Filters using a very similar syntax:

      filter("/*").through(MyFilter.class);

This will route every incoming request through MyFilter, and then continue to any other matching filters before finally being dispatched to a servlet for processing.

Note: Every servlet (or filter) is required to be a @Singleton. If you cannot annotate the class directly, you must bind it using bind(..).in(Singleton.class), separate to the filter() or servlet() rules. Mapping under any other scope is an error. This is to maintain consistency with the Servlet specification. Guice Servlet does not support the deprecated SingleThreadModel.

Available Injections

Installing the servlet module automatically gives you access to several classes from the servlet framework. These are useful for working with the servlet programming model and are injectable in any Guice injected object by default, when you install the ServletModule:

@RequestScoped
class SomeNonServletPojo {

  @Inject
  public SomeNonServletPojo(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
    ...
  }

}

The request and response are scoped to the current http request. Similarly the http session object is scoped to the current user session. In addition to this you may also inject the current ServletContext and a map of the request parameters using the binding annotation @RequestParameters as follows:

@Inject @RequestParameters Map<String, String[]> params;

This must be a map of strings to arrays of strings because http allows multiple values to be bound to the same request parameter, though typically there is only one. Note that if you want access to any of the request or session scoped classes from singletons or other wider-scoped instances, you should inject a Provider<T> instead.

Dispatch Order

You are free to register as many servlets and filters as you like this way. They will be compared and dispatched in the order in which the rules appear in your ServletModule:

   Guice.createInjector(..., new ServletModule() {

     @Override
     protected void configureServlets() {
       filter("/*").through(MyFilter.class);
       filter("*.css").through(MyCssFilter.class);
       // etc..

       serve("*.html").with(MyServlet.class);
       serve("/my/*").with(MyServlet.class);
       // etc..
      }
    }

This will traverse down the list of rules in lexical order. For example, a url /my/file.js will first be compared against the servlet mapping:

       serve("*.html").with(MyServlet.class);

And failing that, it will descend to the next servlet mapping:

       serve("/my/*").with(MyServlet.class);

Since this rule matches, Guice Servlet will dispatch the request to MyServlet and stop the matching process. The same process is used when deciding the dispatch order of filters (that is, matched to their order of appearance in the binding list).

Varargs Mapping

The two mapping rules above can also be written in more compact form using varargs syntax:

       serve("*.html", "/my/*").with(MyServlet.class);

This way you can map several URI patterns to the same servlet. A similar syntax is also available for filter mappings.


Comment by zorzella, Aug 24, 2009

Programatically configure Jetty with the following boilerplate:

    Server server = new Server(portNumber);    
    Context root = new Context(server, "/", Context.SESSIONS);
    
    root.addFilter(GuiceFilter.class, "/*", 0);
    root.addServlet(DefaultServlet.class, "/");

    ...

    server.start();
Comment by sp.majou, Oct 18, 2009

How can we inject request scoped objects into servlets (so singletons) ?

I ask that because I tried to inject a request scoped PersistenceManager? from JDO ORM into the servlet and I get a scope exception.

Finally I injected a Provider<PersistenceManager> into the servlet to make it work. Ss there a better way to do it ?

Comment by dhanji, Oct 18, 2009

Provider is the recommended way to do it, it has an added level of safety that is explicit about using and discarding the object.

Comment by downtime, Nov 09, 2009

Is there an actual example of how to "use" a servlet anywhere? I see lots of examples of configuration, documentation about the scoping, discussions about performance, etc.. but I haven't seen a full example of how to "use" a servlet. For example in the "Available Injects" section above it seems like this is a start of how to implement a servet with constructor injectoins, but how is this servlet actually used by the container? Do you still need to implement the doGet(), doPost(), service() methods or what?

Comment by dhanji, Nov 09, 2009

@downtime It is just a normal servlet like any other, except that you can inject into it using Guice. Yes, it needs to do something with doGet() or post or service(). It follows the servlet programming model.

All Guice servlet does is get rid of web.xml (except for GuiceFilter?) and make your servlets injectable and guicified.

Comment by downtime, Nov 10, 2009

Thanks jhanji for the reply, but say you've implmented the class as given in the example about:

@Inject public MyServletObject?(HttpServletRequest? request, HttpServletResponse? response, HttpSession? session) {
...
}

It seems to me that you've already injected the request and response in the constructor, does them mean that you'll again need to inject the request and response in the doGet() method?

@Inject public MyServletObject?(HttpServletRequest? request, HttpServletResponse? response, HttpSession? session) {
...
@Override @Inject
protected void doGet(HttpServletRequest? request, HttpServletResponse? response)
...
}
}
Comment by dhanji, Nov 10, 2009

@downtime

MyServletObject?? is not meant to be a Servlet =) Sorry about the confusing name. It is meant to be anything OTHER pojo that wants the current request/session etc.

For an example of servlets you should take a look at the IntegrationTest??.java in servlet/test in trunk. The sitebricks project also has code that makes use of servlets in this fashion.

You could also look at the slides from our talk on the front page and my JavaOne? 2009 talk which has more examples.


Sign in to add a comment