About Me

My photo
Related, I keep most of my code here https://github.com/rdammkoehler

Wednesday, December 1, 2010

Guice, Guice Servlet, Jersey, and the Request Scoped Dependancy

On my current project I've been working with Matt Foy to improve the tests around a rather large application. The original developers chose to use Guice with Guice Servlet and Jersey services to create their application. One of the things that we ran into this week was that we had no tests around the Guice configuration. So while everything seemed OK on the CI server, as soon as we actually deployed the application we discovered that the Jersey servlets would not function because various Request Scoped dependancies had not actually been injected. Basically our Module configurations were a mess and we didn't know it.

So, we created a simple sandbox representation of this problem and then discovered a way to effectively test that the Guice configuration was correct. We must give credit to the authors of Guice for making their test available, this is how we figured it out.

First let us show you the classes that I want to test, note this is highly contrived for the purpose of clarity;

The following servlet is simply in place to allow us to have a servlet with a Request Scoped dependency in a Jersey service.

The Dependancy is simply an implementation of an interface, neither of which contain any methods;

And we have a custom module for creating the Dependency. Note that the Dependancy.class is scoped as @RequestScoped;

And finally, the GuiceServletContextListener that would be used by the Servlet container to do the actual injections at runtime;

Now that you have the context, here's how we solved the problem. The GuiceFilter used by Guice Servlet support conducts the injection activity for the servlet when a request is executed. If you attempt to get, from the injector, any injected instance that is RequestScoped you will get an exception from the Injector indicating that you've requested a resource outside the scope of a Request. It's your own fault really :-).

So, by contriving a filter chain of assertions you can determine if Guice has actually injected the dependencies correctly. Here's how;

First we created this Assertion class;

The assertProvisioningType method allows you to assert that an instance is provided for any type request and that the provided instance is of the appropriate type.

The assertInstantiablity method allows you to assert that an instance is provided for a requested type.

The applyFilterChainAssertion method executes the given FilterChain using the GuiceFilter as the head of the chain. JMock is used in this case to support our current project configuration (Note: We'll be rewriting this with Mockito soon enough.) When you call this method with a FilterChain full of assertions they will have access to the Injector and will be within the Request scope, so you can easily make assertions about them without getting the nasty exception pictured here;

The expose method allows you to directly fetch a Request Scoped instance from the injector for additional testing.

Here is the test suite from our contrived example;

Hope this helps someone.


No comments: