Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I'm just getting acquainted with implementing REST web services in Java using JAX-RS and I ran into the following problem. One of my resource classes requires access to a storage backend, which is abstracted away behind a StorageEngine interface. I would like to inject the current StorageEngine instance into the resource class serving the REST requests and I thought a nice way of doing this would be by using the @Context annotation and an appropriate ContextResolver class. This is what I have so far:

In MyResource.java:

class MyResource {     @Context StorageEngine storage;     [...] } 

In StorageEngineProvider.java:

@Provider class StorageEngineProvider implements ContextResolver<StorageEngine> {     private StorageEngine storage = new InMemoryStorageEngine();      public StorageEngine getContext(Class<?> type) {         if (type.equals(StorageEngine.class))             return storage;         return null;     } } 

I'm using com.sun.jersey.api.core.PackagesResourceConfig to discover the providers and the resource classes automatically, and according to the logs, it picks up the StorageEngineProvider class nicely (timestamps and unnecessary stuff left out intentionally):

INFO: Root resource classes found:     class MyResource INFO: Provider classes found:     class StorageEngineProvider 

However, the value of storage in my resource class is always null - neither the constructor of StorageEngineProvider nor its getContext method is called by Jersey, ever. What am I doing wrong here?

like image 798
Tamás Avatar asked Jun 15 '10 17:06

Tamás


People also ask

What is a context resolver?

public interface ContextResolver<T> Contract for a provider that supplies context information to resource classes and other providers. A ContextResolver implementation may be annotated with Produces to restrict the media types for which it will be considered suitable.

Is a specific implementation of JAX-RS?

JAX-RS is a specification for RESTful Web Services with Java. There is a reference implementation that is included in Java EE but since it is a specification, other frameworks can be written to implement the spec, and that includes Jersey, Resteasy, and others. Yes, exactly!

Why do we need JAX-RS?

Why use JAX-RS / Jersey? Because it makes the development of RESTful services easier. JAX-RS is a standard that makes it easy to create a RESTful service that can be deployed to any Java application server: GlassFish, WebLogic, WebSphere, JBoss, etc.

What is a JAX-RS provider?

The JAX-RS specification allows you to plug in your own request/response body reader and writers. To do this, you annotate a class with @Provider and specify the @Produces types for a writer and @Consumes types for a reader. You must also implement a MessageBodyReader/Writer interface respectively.


1 Answers

I don't think there's a JAX-RS specific way to do what you want. The closest would be to do:

@Path("/something/") class MyResource {     @Context     javax.ws.rs.ext.Providers providers;      @GET     public Response get() {         ContextResolver<StorageEngine> resolver = providers.getContextResolver(StorageEngine.class, MediaType.WILDCARD_TYPE);         StorageEngine engine = resolver.get(StorageEngine.class);         ...     } } 

However, I think the @javax.ws.rs.core.Context annotation and javax.ws.rs.ext.ContextResolver is really for types related to JAX-RS and supporting JAX-RS providers.

You may want to look for Java Context and Dependency Injection (JSR-299) implementations (which should be available in Java EE 6) or other dependency injection frameworks such as Google Guice to help you here.

like image 189
Bryant Luk Avatar answered Sep 21 '22 13:09

Bryant Luk