An instance of javax.ws.rs.core.Request can be injected as field or method parameter using the @Context annotation. Request is a helper object which can be used to evaluate preconditions related to HTTP request headers. Following methods of Request can be used to check the preconditions for 'Last-Modified' and 'ETag' headers:
Response.ResponseBuilder evaluatePreconditions(EntityTag eTag)
'ETag' HTTP header is meant to utilize browser cache effectively. This method checks if the provided eTag value matches with the request's 'If-None-Match' header value. If it does then this method returns non-null ResponseBuilder with 304 status code and empty body, otherwise, user is responsible to prepare the response with 200 status and a new value of 'ETag' header. check out this to have basic understanding how 'ETag' works.
Response.ResponseBuilder evaluatePreconditions(Date lastModified)
'Last-Modified' HTTP header is also meant to utilize browser cache effectively. This method is used to check if provided lastModified value matches the 'If-Modified-Since' header value. If it does then this method returns non-null ResponseBuilder with 304 status code and empty body, otherwise, user is responsible to prepare the response with 200 status and a new value of 'Last-Modified' header. check out this to have basic understanding how 'Last-Modified' works. |
Example
A JAX-RS resource injecting Request
@Path("/users")
public class UserResource {
@GET
public Response getUsers(@Context Request request) {
Date lastModifiedDate = UserService.Instance.getUsersLastModifiedDate();
Response.ResponseBuilder responseBuilder = request.evaluatePreconditions(lastModifiedDate);
if (responseBuilder == null) {//last modified date didn't match, send new content
return Response.ok("dummy user list")
.lastModified(lastModifiedDate)
.build();
} else {
//sending 304 not modified
return responseBuilder.build();
}
}
@GET
@Path("{id}")
public Response getUser(@PathParam("id") String id, @Context Request request) {
EntityTag eTag = UserService.Instance.getETagForUser(id);
Response.ResponseBuilder responseBuilder = request.evaluatePreconditions(eTag);
if (responseBuilder == null) {//eTag has changed, sending new content
return Response.ok(UserService.Instance.getUser(id))
.tag(eTag)
.build();
} else {
//sending 304 not modified
return responseBuilder.build();
}
}
}
public enum UserService {
Instance;
public Date getUsersLastModifiedDate() {
return Date.from(LocalDate.now()
.minusDays(21).atStartOfDay()
.atZone(ZoneId.systemDefault()).toInstant());
}
public EntityTag getETagForUser(String userId) {
return new EntityTag("version1");
}
public Object getUser(String id) {
return "dummy user for id: " + id;
}
}
Output
Accessing '/users'
First access to '/users'
Checking request/response headers in google's Developer Tools:
Subsequent access to '/users'
If Last-Modified value changes on the server then server will send 200 status with new body and new 'Last-Modified' response header.
Accessing '/users/{id}'
First access:
Subsequent access:
If ETag value changes on the server then server will send 200 status with new body and new 'ETag' response header.
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
|