What is javax.ws.rs.core.context? [ Part 1 ]
How to use the @Context annotation
The JAX-RS API provides a very handy mechanism to inject a range of useful resources, such as HTTP Headers, into your endpoint. The @Context annotation is an all purpose annotation that injects instances of the following objects:
- HttpHeaders -> HTTP header parameters and values
- UriInfo -> Captures path variables and query parameters
- SecurityContext -> Provides access to security related information for a request
- ResourceContext -> Provides access to instances of resource classes
- Request -> Precondition request processing
- Application, Configuration, and Providers -> Provide information about the JAX-RS application environment
- HttpServletRequest -> Provides access to the HttpServletRequest instance
- HttpServletResponse -> Provides access to the HttpServletResponse instance
- ServletConfig -> Provides access to the ServletConfig
- ServletContext -> Provides access to the ServletContext
Let’s examine each in turn with working code examples.
Inject an HttpHeaders instance with @Context
There are two ways to obtain the value of an HTTP header parameter. If you can use the @HeadParam annotation to mark a resource method parameter and pass it the parameter name the value of the HTTP header parameter is assigned to the String variable annotated by the @HeadParam annotation. The following code snippet retrieves the value of the user-agent parameter and assigned it to the UserAgent String.
@HeaderParam("user-agent") String userAgent
This is a great solution if you only require a few header values, but what if you want many or are not sure of the parameter name need to iterate over the headers then this solution is not good enough. Luckily the @Context annotation comes to our rescue. this annotation can inject all HTTP header parameters in one HttpHeaders object. Take a look at the code example below:
@Path("/http-headers") public class EndpointResource { @GET @Produces(MediaType.APPLICATION_JSON) public Response getAllHttpHeaders(final @Context HttpHeaders httpHeaders) { return Response.ok(httpHeaders.getRequestHeaders()).build(); } }
In this code snippet, the @Context annotation is used to instruct the container to pass the instance of the HttpHeaders object for the current request to the getAllHttpHeaders method. The method getRequestHeaders returns a MultivaluedMap<String, String> containing the HTTP parameters and their corresponding value. This is one of many methods that provide access to HTTP header data for the current request.
The MultivaluedMap is deserialized to JSON and sent back to the client in the response body.
If you clone the code in my Github repository and execute the code using the Maven command: mvn clean package, it will be deployed into an IBM Liberty Profile instance. Visit the URL http://localhost:8080/rest-server/http-headers and a JSON representation of the HTTP headers for the request will be displayed on the screen and should look something like the following:
{ "Accept": [ "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8" ], "accept-encoding": [ "gzip, deflate, br" ], "Accept-Language": [ "en-US,en;q=0.8,es;q=0.6" ], "connection": [ "keep-alive" ], "Content-Type": [ null ], "DNT": [ "1" ], "Host": [ "localhost:8080" ], "Upgrade-Insecure-Requests": [ "1" ], "User-Agent": [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36" ] }
Let’s take a look at another example that retrieves just one of the HTTP header values.
@GET @Path("/{header-param}") @Produces(MediaType.APPLICATION_JSON) public Response getSpecifiedHeader( final @PathParam("header-param") String header_param, final @Context HttpHeaders httpHeaders){ return Response.ok(httpHeaders.getRequestHeader(header_param)).build(); }
In this coding example, you pass the HTTP header parameter name to the resource method via a URL parameter. Then the method uses the parameter name to retrieve the value of associated HTTPHeader parameter and passes it back to the caller in JSON format.
So a called to the endpoint http://localhost:8080/rest-server/http-headers/User-Agent returns the value of the User-Agent HTTP parameter and should look something like this:
[ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36" ]
There is a handsome collection of methods in the HttpHeader class that allow you to query the parameters in the HTTP header. Here is a list of those methods. As you can see there are some convenience methods that return the MediaType and Local.
List<String> getRequestHeader(String var1); String getHeaderString(String var1); MultivaluedMap<String, String> getRequestHeaders(); List<MediaType> getAcceptableMediaTypes(); List<Locale> getAcceptableLanguages(); MediaType getMediaType(); Locale getLanguage(); Map<String, Cookie> getCookies(); Date getDate(); int getLength();
The HttpHeaders instance can also be injected as an instance variable as follows:
@Path("/http-headers") public class HttpHeaderResource { @Context private HttpHeaders httpHeaders; @GET @Produces(MediaType.APPLICATION_JSON) public Response getAllHttpHeaders(){ return Response.ok(httpHeaders.getRequestHeaders()).build(); } }
Inject an UriInfo instance with @Context
The UriInfo interface provides access to useful information about the requests URI. You can retrieve path related details such as query parameters are path variables.
The following code snippet gets the template parameters in the URI after the resource root.
@Path("/uri-info") public class UriInfoResource { @GET @Path("/{path: .*}") @Produces(MediaType.APPLICATION_JSON) public Response getPathParameters(final @Context UriInfo uriInfo){ return Response.ok(uriInfo.getPathParameters()).build(); } }
The response received after visiting the URL http://localhost:8080/rest-server/uri-info/path/to/resource is the paths after the resource root uri-info.
{ "path": [ "path/to/resource" ] }
The URI query parameters can just as easily be retrieved with a call to the method getQueryParameters(). Take a look at the code example below.
@GET @Path("/{search}") @Produces(MediaType.APPLICATION_JSON) public Response getQueryParameters(final @Context UriInfo uriInfo){ return Response.ok(uriInfo.getQueryParameters()).build(); }
A call to the URL http://localhost:8080/rest-server/uri-info/search?term=JavaEE captures the search term and value:
{ "term": [ "JavaEE" ] }
The UriInfo instance can also be injected into an instance variable like so:
@Context private UriInfo uriInfo;
What Next?
That is all for part 1, in part 2 of What is javax.ws.rs.core.context? you will learn how to use the @Context annotation to secure a RESTful webservice and how to retrieve and use a Resource.
Code Repository
The source code for this and all my articles is in the readlearncode_articles Github repository.
Reference: | What is javax.ws.rs.core.context? [ Part 1 ] from our JCG partner Alex Theedom at the Read Learn Code blog. |