Where do @Context objects come from

13,495

Solution 1

You can write your own injection provider and plug that into Jersey - look at SingletonTypeInjectableProvider and PerRequestTypeInjectableProvider - extend one of these classes (depending on the lifecycle you want for the injectable object) and register your implementation as a provider in your web app.

For example, something like this:

@Provider
public class MyObjectProvider extends SingletonTypeInjectableProvider<Context, MyObject> {
    public MyObjectProvider() {
        // binds MyObject.class to a single MyObject instance
        // i.e. the instance of MyObject created bellow will be injected if you use
        // @Context MyObject myObject
        super(MyObject.class, new MyObject());
    }
}

To include the provider in your web app you have several options:

  1. if your app uses classpath scanning (or package scanning) just make sure the provider is in the right package / on the classpath
  2. or you can simply register it using META-INF/services entry (add META-INF/services/com.sun.jersey.spi.inject.InjectableProvider file having the name of your provider class in it's contents)

Solution 2

I think I may be on to something...and if this works, Martin should get partial credit. :)

It appears that the @Provider class must implement the com.sun.jersey.spi.inject.Injectable<T> interface. However, I'm not sure that this is enough to actually have the @Context be injected. What's missing, is that we have to tell the ResourceConfig object of the web app about the @Provider. In the context of what I'm trying to do, and taking hints from neo4j-server, the remaining work boils down to:

  • extending com.sun.jersey.spi.container.servlet.ServletContainer, and overriding the configure method:
@Override
protected void configure(WebConfig wc, ResourceConfig rc, WebApplication wa)
{
  super.configure( wc, rc, wa );
  Set<Object> singletons = rc.getSingletons();
  singletons.add(new MyObjectProvider());
}
  • specifying that this container must be used in the web.xml deployment descriptor:
<servlet>
  <servlet-name>JAX-RS Servlet Container</servlet-name>
  <servlet-class>com.blah.MyServletContainer</servlet-class>
</servlet>
Share:
13,495

Related videos on Youtube

Kricket
Author by

Kricket

Corporate tech drone by day, basically a full-stack developer merging into software architect. In my free time I raise my two kids, play Ultimate Frisbee and try to help the French with their eengleashe.

Updated on September 15, 2022

Comments

  • Kricket
    Kricket over 1 year

    I've been searching everywhere, but can't seem to find a clear answer...

    What is the mechanism whereby a server (glassfish for my problem) injects actual objets that are annotated with @Context? More specifically, if I wanted to write a class that did something like:

    @Path("/")
    public class MyResource {
      @GET
      public String doSomething(@Context MyObject obj) {
        // ...
      }
    }
    

    then how would I do it? Where is it that the MyObject is instanciated, who does it, and how?

    Edit: I've seen stuff like the following:

    Using @Context, @Provider and ContextResolver in JAX-RS

    http://jersey.576304.n2.nabble.com/ContextResolver-confusion-td5654154.html

    However, this doesn't square with what I've seen, e.g. in the constructor of org.neo4j.server.rest.web.RestfulGraphDatabase, which has the following signature:

    public RestfulGraphDatabase(
      @Context UriInfo uriInfo,
      @Context Database database,
      @Context InputFormat input,
      @Context OutputFormat output,
      @Context LeaseManager leaseManager )
    
  • Ludwig Magnusson
    Ludwig Magnusson almost 12 years
    Does these documents say how to write such functionallity yourself? Which I understood was the question.
  • Ryan Stewart
    Ryan Stewart almost 12 years
    You don't. It's for framework components. If you want dependency injection, look for a DI container, like Spring.
  • smcg
    smcg almost 12 years
    Aren't link-only answers frowned upon, since the linked site's contents can change?
  • Martin Matula
    Martin Matula almost 12 years
    Oh, no - you don't need to do that. I've edited my answer to show how to register your provider.
  • justin
    justin almost 9 years
    If you're subclassing javax.ws.rs.core.Application, you can register the provider with this.getSingletons().add(new MyObjectProvider()); in your Application's constructor.
  • David Berg
    David Berg over 8 years
    The links are broken.
  • elanh
    elanh over 8 years
  • elanh
    elanh over 8 years
    The classes were removed from version 2.0+
  • Alex Theedom
    Alex Theedom over 6 years
    Correct. You can only inject the 12 allowable object instances as listed here: readlearncode.com/java-ee/…