Injecting Security Principal (or any other custom component) into Jersey Resources with Guice

Recently I saw a post on a Jersey users mailing list (browse archive) asking for help with injection of a custom component into a Jersey resource. In particular, Jersey supports injection of a SecurityContext out of the box. Yet, the user wanted to directly inject custom security Principal rather than invoking the same SecurityContext.getUserPrincipal() getter all the time.

As you probably know, there is a jersey-guice module that provides a Jersey integration with Google Guice. Using Guice is an easy and elegant way how to extend injectable components in Jersey. Jersey already provided a very basic sample showing how to use Guice which I decided to update and extend to demonstrate how injecting a custom SecurityContext as well as Principal can be done.

First I have created a custom SecurityContext implementation:

public final class MySecurityContext implements SecurityContext {
 
    private static final class MyPrincipal implements Principal {
 
        @Override
        public String getName() {
            return "test-name";
        }
 
        @Override
        public String toString() {
            return "MyPrincipal{" + getName() + '}';
        }
    }
 
    @Override
    public Principal getUserPrincipal() {
        return new MyPrincipal();
    }
    // ... rest of the code omitted for clarity... 
}

To make sure that my custom implementation will get injected and used by Jersey components I had to bind my implementation to the SecurityContext interface. As described in the jersey-guice module documentation, this can be done by extending and implementing a custom GuiceServletContextListener class:

public class GuiceServletConfig extends GuiceServletContextListener {
 
    @Override
    protected Injector getInjector() {
        return Guice.createInjector(new ServletModule() {
 
            @Override
            protected void configureServlets() {
                // Bind classes and resources
                ...
                bind(SecurityContext.class).to(MySecurityContext.class);
                ...
 
                serve("/*").with(GuiceContainer.class);
            }
        });
    }
}

This custom servlet context listener is then registered in the web application’s web.xml config file:

<web-app version="2.5" ... >
    <listener>
        <listener-class>com.sun.jersey.samples.guice.GuiceServletConfig</listener-class>
    </listener>
    ...
</web-app>

Now that I have showed how to inject a custom implementation of the whole SecurityContext, I will add more code to enable direct injection of Principal instances. In order to do that I need to create a custom Guice Provider. I will make it servlet request-scoped to make sure I am injecting proper Provider instance. The resulting implementation is quite straightforward:

@RequestScoped
public final class PrincipalProvider implements Provider<Principal> {
 
    private SecurityContext sc;
 
    @Inject
    public PrincipalProvider(SecurityContext sc) {
        this.sc = sc;
    }
 
    @Override
    public Principal get() {
        return sc.getUserPrincipal();
    }
}

Now the only remaining thing is to update the custome guice servlet context listener implementation with a new binding:

public class GuiceServletConfig extends GuiceServletContextListener {
 
    @Override
    protected Injector getInjector() {
        return Guice.createInjector(new ServletModule() {
 
            @Override
            protected void configureServlets() {
                // Bind classes
                ...
                bind(Principal.class).toProvider(PrincipalProvider.class);
                bind(SecurityContext.class).to(MySecurityContext.class);
 
                serve("/*").with(GuiceContainer.class);
            }
        });
    }
}

With that, I can now inject the Principal directly into my Jersey resources. At the same time I can be sure that the my custom implementation of the SecurityContext will be used:

@Path("bound/perrequest")
@RequestScoped
public class PerRequestResource {
    ...
    private final SingletonComponent sc;
    private final Principal principal;
 
    //Create singleton component and inject into resource at construction as well as principal
    @Inject
    public PerRequestResource(SingletonComponent sc, Principal principal) {
        this.sc = sc;
        this.principal = principal;
    }
    ...
}

For the complete sample code, please download the guicefilter-webapp Jersey sample project.

2 thoughts on “Injecting Security Principal (or any other custom component) into Jersey Resources with Guice

  1. Solomon Duskis

    I set up RESTEasy to allow you to inject RequestScoped beans into JAX-RS methods of Singletons: http://www.jroller.com/Solomon/entry/annotations_your_way_in_resteasy. I’ll see if I can re-write your example (which is much more interesting than mine) with Spring. Here’s the jist:

    @Path(“bound/perrequest”)
    @Singleton
    public class PerRequestResource {

    private final SingletonComponent sc;
    private final Principal principal;

    //Create singleton component and inject into resource at construction as well as principal
    @Inject
    public PerRequestResource(SingletonComponent sc) {
    this.sc = sc;
    this.principal = principal;
    }

    @GET
    public Something getSomething(@MyInjectAnnotation Principal principal, @PathParam…){

    }
    }

    I’m definitely interested in your feedback

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>