JAX-RS - Resource Context

[Updated: Nov 22, 2017, Created: Nov 22, 2017]

The ResourceContext interface provides methods (getResource(resourceClass) and initResource(resourceInstance)) which can be used to access subresource classes. This is similar to what we saw in Sub Resource Locators tutorial. The advantage of using ResourceContext is that the target subresource will be injected and managed within the declared scope just like a top level root resource class. Let's understand that with an example.

Example

ResourceContext can be injected with @Context annotation:

@Path("/")
public class OrderResource {

  @Context
  private ResourceContext resourceContext;

  @Path("/orders/{id}")
  public OrderDetails getOrderById(@PathParam("id") int orderId) {
      return resourceContext.initResource(new OrderDetails(orderId));
  }
}
public class OrderDetails {

  private final int id;
  @Context
  private HttpHeaders headers;

  public OrderDetails(int id) {
      System.out.println("--- init --");
      this.id = id;
  }

  @GET
  public String getOrderDetails() {
      return String.format("response from getOrderDetails(), headers: %s%n",
              headers.getRequestHeaders());
  }
}

To try examples, run embedded tomcat (configured in pom.xml of example project below):

mvn tomcat7:run-war

The client

public class OrderClient {
  public static void main(String[] args) {
      Client client = ClientBuilder.newClient();
      WebTarget target =
              client.target("http://localhost:8080/orders/234");
      Response response = target.request()
                                .get();
      System.out.printf("status: %s%n", response.getStatus());
      System.out.printf("-- response body --%n%s%n", response.readEntity(String.class));
  }
}

Output

status: 200
-- response body --
response from getOrderDetails(), headers: {user-agent=[Jersey/2.25.1 (HttpUrlConnection 1.8.0_65)], host=[localhost:8080], accept=[text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2], connection=[keep-alive]}

Note that the instance of OrderDetails is returned by the resource locator method OrderResource.getOrderById is initialized and all target request context/request related parameters are injected before it is returned . If we initialize it without ResourceContext (like this) then the HttpHeaders will not be injected. Let's try that:

@Path("/")
public class OrderResource {

  private @Context
  ResourceContext resourceContext;

  @Path("/orders/{id}")
  public OrderDetails getOrderById(@PathParam("id") int orderId) {
      return new OrderDetails(orderId);
  }
}

Restart the server and run the client again.

output

java.lang.NullPointerException
	at com.logicbig.example.OrderDetails.getOrderDetails(OrderDetails.java:21)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
	at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144)
	at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161)
	at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:205)
	at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99)

The NullPointerException is thrown where OrderDetails.getOrderDetails class uses headers.getRequestHeader(). That shows @Context annotation doesn't work if subresource is not initialized via ResourceContext.

Example Project

Dependencies and Technologies Used :

  • jersey-server 2.25.1: Jersey core server implementation.
  • jersey-container-servlet 2.25.1: Jersey core Servlet 3.x implementation.
  • JDK 1.8
  • Maven 3.3.9

ResourceContext Example Select All Download
  • resource-context-example
    • src
      • main
        • java
          • com
            • logicbig
              • example
        • resources
        • webapp
          • WEB-INF

See Also