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));
}
} Outputstatus: 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 ProjectDependencies 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
|