Annotations for accessing request parameters @PathParam @QueryParam @MatrixParam @HeaderParam @CookieParam @FormParam @DefaultValue @Context

 

Annotations for accessing request parameters

JAX-RS offers annotations to pull some information out of a request. You can use this offering to extract the following parameters from a request: a query, URI path, form, cookie, header, and matrix. Mostly, these parameters are used in conjunction with the GETPOSTPUT, and DELETE methods.

@PathParam

A URI path template, in general, has a URI part pointing to the resource. It can also take the path variables embedded in the syntax; this facility is used by the clients to pass parameters to the REST APIs, as appropriate. The @javax.ws.rs.PathParamannotation injects (or binds) the value of the matching path parameter present in the URI path template into a class field, a resource class bean property (the getter method for accessing the attribute), or a method parameter. Typically, this annotation is used in conjunction with the HTTP method type annotations, such as @GET, @POST, @PUT, and @DELETE.

The following example illustrates the use of the @PathParam annotation to read the value of the path parameter, id, into the deptId method parameter. The URI path template for this example looks like /departments/{id}:

//Other imports removed for brevity 
javax.ws.rs.PathParam 
 
@Path("departments") 
public class DepartmentService { 
   @DELETE 
   @Path("{id}") 
   public void removeDepartment(@PathParam("id") Short deptId) { 
      removeDepartmentEntity(deptId); 
   } 
   //Other methods removed for brevity 
} 

The REST API call to remove the department resource identified by id=10 looks like DELETE /departments/10 HTTP/1.1.

We can also use multiple variables in a URI path template. For example, we can have the URI path template embedding the path variables to query a list of departments from a specific city and country, which may look like /departments/{country}/{city}. The following code snippet illustrates the use of @PathParam to extract variable values from the preceding URI path template:

@Produces(MediaType.APPLICATION_JSON) 
@Path("{country}/{city} ")   
public List<Department> findAllDepartments(  
  @PathParam("country") 
String countyCode,   @PathParam("city") String cityCode) { 
  //Find all departments from the data store for a country  
  //and city 
  List<Department> departments =  
    findAllMatchingDepartmentEntities(countyCode,  
      cityCode ); 
   return departments; 
} 

@QueryParam

The @javax.ws.rs.QueryParam annotation injects the value(s) of a HTTP query parameter into a class field, a resource class bean property (the getter method for accessing the attribute), or a method parameter.

The following example illustrates the use of @QueryParam to extract the value of the desired query parameter present in the URI. This example extracts the value of the query parameter, name, from the request URI and copies the value into the deptName method parameter. The URI that accesses the IT department resource looks like /departments?name=IT:

@GET 
@Produces(MediaType.APPLICATION_JSON) 
public List<Department>  
  findAllDepartmentsByName(@QueryParam("name") String deptName) { 
    List<Department> depts= findAllMatchingDepartmentEntities  
      (deptName);  
  return depts;        
} 

The following example illustrates the use of @QueryParam to extract the value of the query parameter, locationId, from the request URI and copies the value into the deptLocationId class field. The URI that accesses the IT department resource looks like /departments/queryByLocation?locationId=1700:

//Usage of QueryParam for injecting class field
@QueryParam("locationId")
Short deptLocationId;

/**
* Returns list of departments by location
*
* @param locationId
* @return
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("queryByLocation")
public List<Departments> findAllDepartmentsByLocation() {
//Find all departments from the data store
Query queryDepartmentsByLocation =
entityManager.createNamedQuery("Departments.findByLocationId");
queryDepartmentsByLocation.setParameter("locationId", deptLocationId);
List<Departments> departments = queryDepartmentsByLocation.getResultList();
logger.log(Level.INFO, departments.toString());
return departments;
}

@MatrixParam

Matrix parameters are another way of defining parameters in the URI path template. The matrix parameters take the form of name-value pairs in the URI path, where each pair is preceded by a semicolon (;). For instance, the URI path that uses a matrix parameter to list all departments in Bangalore city looks like /departments;city=Bangalore.

The @javax.ws.rs.MatrixParam annotation injects the matrix parameter value into a class field, a resource class bean property (the getter method for accessing the attribute), or a method parameter.

The following code snippet demonstrates the use of the @MatrixParam annotation to extract the matrix parameters present in the request. The URI path used in this example looks like /departments/matrix;name=IT;city=Bangalore:

@GET @Produces(MediaType.APPLICATION_JSON) @Path("matrix") 
public List<Department> findAllDepartmentsByNameWithMatrix(
@MatrixParam("name") String deptName,
@MatrixParam("city") String locationCode) {
List<Department> depts=findAllDepartmentsFromDB(deptName, city);
return depts;
}

You can use PathParamQueryParam, and MatrixParam to pass the desired search parameters to the REST APIs. Now, you may ask, 

"When to use what?"
Although there are no strict rules here, a very common practice followed by many is to use PathParam to drill down to the entity class hierarchy and locate the specific resource.  For example, you may use the URI of the following form to identify an employee working in a specific department: /departments/{dept}/employees/{id}.
QueryParam can be used for specifying attributes to locate the resources. For example, you may use URI with QueryParam to identify employees who joined on January 1, 2015, which may look like /employees?doj=2015-01-01.

The MatrixParam annotation is not used frequently. This is useful when you need to make a complex REST style query to multiple levels of resources and subresources. MatrixParam is applicable to a particular path element, while the query parameter is applicable to the entire request.

@HeaderParam

The HTTP header fields provide the necessary information about the request and response contents in HTTP. For example, the header field, Content-Length: 348, for an HTTP request says that the size of the request body content is 348 octets (8-bit bytes). The @javax.ws.rs.HeaderParam annotation injects the header values present in the request into a class field, a resource class bean property (the getter method for accessing the attribute), or a method parameter.

The following example extracts the referrer header parameter and logs it for audit purposes. The referrer header field in HTTP contains the address of the previous web page from which a request to the currently processed page originated:

@POST 
public void createDepartment(@HeaderParam("Referer")  
String referer,  Department entity) { 
  logSource(referer); 
  createDepartmentInDB(department); 
} 
Remember that HTTP provides a very wide selection of headers that cover most of the header parameters that you are looking for. Although you can use custom HTTP headers to pass some application-specific data to the server, try using standard headers whenever possible. Furthermore, avoid using a custom header for holding properties specific to a resource, the state of the resource, or parameters directly affecting the resource. For such scenarios, you can consider the other approaches discussed in this section, namely PathParam, QueryParam, or MatrixParam.


@CookieParam

The @javax.ws.rs.CookieParam annotation injects the matching cookie parameters present in the HTTP headers into a class field, a resource class bean property (the getter method for accessing the attribute), or a method parameter.

The following code snippet uses the Default-Dept cookie parameter present in the request to return the default department details:

@GET 
@Path("cook") 
@Produces(MediaType.APPLICATION_JSON) 
public Department getDefaultDepartment(@CookieParam("Default-Dept") 
short departmentId) { Department dept=findDepartmentById(departmentId); return dept; }


@FormParam

The @javax.ws.rs.FormParam annotation injects the matching HTML form parameters present in the request body into a class field, a resource class bean property (the getter method for accessing the attribute), or a method parameter. The request body carrying the form elements must have the content type specified as application/x-www-form-urlencoded.

Consider the following HTML form that contains the data capture form for a department entity. This form allows the user to enter the department entity details:

<!DOCTYPE html> 
<html> 
  <head> 
  <title>Create Department</title> 
  </head> 
  <body> 
    <form method="POST" action="/resources/departments"> 
    Department Id:  
    <input type="text" name="departmentId"> 
    <br> 
    Department Name:  
      <input type="text" name="departmentName"> 
      <br> 
      <input type="submit" value="Add Department" /> 
    </form> 
  </body> 
</html> 

Upon clicking on the submit button on the HTML form, the department details that you entered will be posted to the REST URI, /resources/departments. The following code snippet shows the use of the @FormParam annotation for extracting the HTML form fields and copying them to the resource class method parameter:


@Path("departments") 
public class DepartmentService { 
 
  @POST 
  //Specifies content type as  
  //"application/x-www-form-urlencoded" 
  @Consumes(MediaType.APPLICATION_FORM_URLENCODED) 
  public void createDepartment(@FormParam("departmentId") short   
    departmentId,  
      @FormParam("departmentName") String departmentName) { 
      createDepartmentEntity(departmentId, departmentName); 
  } 
} 

@DefaultValue

The @javax.ws.rs.DefaultValue annotation specifies a default value for the request parameters accessed using one of the following annotations: PathParamQueryParamMatrixParamCookieParamFormParam, or HeaderParam. The default value is used if no matching parameter value is found for the variables annotated using one of the preceding annotations.

The following REST resource method will make use of the default value set for the from and to method parameters if the corresponding query parameters are found missing in the URI path:


@GET 
@Produces(MediaType.APPLICATION_JSON) 
public List<Department> findAllDepartmentsInRange 
  (@DefaultValue("0")  @QueryParam("from") Integer from,  
    @DefaultValue("100")  @QueryParam("to") Integer to) { 
    findAllDepartmentEntitiesInRange(from, to); 
} 

@Context

The JAX-RS runtime offers different context objects, which can be used for accessing information associated with the resource class, operating environment, and so on. You may find various context objects that hold information associated with the URI path, request, HTTP header, security, and so on. Some of these context objects also provide the utility methods for dealing with the request and response content. JAX-RS allows you to reference the desired context objects in the code via dependency injection. JAX-RS provides the @javax.ws.rs.Context annotation, which injects the matching context object into the target field. You can specify the @Contextannotation on a class field, a resource class bean property (the getter method for accessing the attribute), or a method parameter.

The following example illustrates the use of the @Context annotation to inject the javax.ws.rs.core.UriInfo context object into a method variable. The UriInfo instance provides access to the application and request URI information. This example uses UriInfo to read the query parameter present in the requested URI path template, /departments/IT:

@GET 
@Produces(MediaType.APPLICATION_JSON) 
public List<Department> findAllDepartmentsByName( 
  @Context UriInfo  uriInfo){ 
  String deptName =  
    uriInfo.getPathParameters().getFirst("name"); 
  List<Department> depts= findAllMatchingDepartmentEntities 
    (deptName); 
  return depts; 
} 

Here is a list of the commonly used classes and interfaces, which can be injected using the @Context annotation:

  • javax.ws.rs.core.Application: This class defines the components of a JAX-RS application and supplies additional metadata
  • javax.ws.rs.core.UriInfo: This interface provides access to the application and request URI information
  • javax.ws.rs.core.Request: This interface provides a method for request processing, such as reading the method type and precondition evaluation
  • javax.ws.rs.core.HttpHeaders: This interface provides access to the HTTP header information
  • javax.ws.rs.core.SecurityContext: This interface provides access to security-related information
  • javax.ws.rs.ext.Providers: This interface offers the runtime lookup of a provider instance, such as MessageBodyReaderMessageBodyWriterExceptionMapper, and ContextResolver
  • javax.ws.rs.ext.ContextResolver<T>: This interface supplies the requested context to the resource classes and other providers
  • javax.servlet.http.HttpServletRequest: This interface provides the client request information for a servlet
  • javax.servlet.http.HttpServletResponse: This interface is used to send a response to a client
  • javax.servlet.ServletContext: This interface provides methods for a servlet to communicate with its servlet container
  • javax.servlet.ServletConfig: This interface carries the servlet configuration parameters

@BeanParam

The @javax.ws.rs.BeanParam annotation allows you to inject all the matching request parameters into a single bean object. The @BeanParam annotation can be set on a class field, a resource class bean property (the getter method for accessing the attribute), or a method parameter. The bean class can have fields or properties annotated with one of the request parameter annotations, namely @PathParam@QueryParam@MatrixParam@HeaderParam@CookieParam, or @FormParam. Apart from the request parameter annotations, the bean can have the @Context annotation if there is a need.

Consider the example that we discussed for @FormParam. The createDepartment() method that we used in that example has two parameters annotated with @FormParam:


public void createDepartment( 
  @FormParam("departmentId") short departmentId,  
   @FormParam("departmentName") String departmentName)   

Let's see how we can use @BeanParam for the preceding method to give a more logical and meaningful signature by grouping all the related fields into an aggregator class, thereby avoiding too many parameters in the method signature.

The DepartmentBean class that we use for this example is as follows:

public class DepartmentBean { 
 
  @FormParam("departmentId")  
    private short departmentId; 
 
  @FormParam("departmentName")  
    private String departmentName; 
 
  //getter and setter for the above fields  
  //are not shown here to save space 
} 

The following code snippet demonstrates the use of the @BeanParam annotation to inject the DepartmentBean instance that contains all the FormParam values extracted from the request message body:

@POST 
public void createDepartment(@BeanParam DepartmentBean deptBean) 
{ 
  createDepartmentEntity(deptBean.getDepartmentId(), 
    deptBean.getDepartmentName()); 
} 


@Encoded

By default, the JAX-RS runtime decodes all the request parameters before injecting the extracted values into the target variables annotated with one of the following annotations: @FormParam@PathParam@MatrixParam, or @QueryParam. You can use @javax.ws.rs.Encoded to disable the automatic decoding of the parameter values. With the @Encoded annotation, the value of parameters will be provided in the encoded form itself. This annotation can be used on a class, method, or parameters. If you set this annotation on a method, it will disable decoding for all the parameters defined for this method. You can use this annotation on a class to disable decoding for all the parameters of all the methods. In the following example, the value of the name path parameter is injected into the method parameter in the URL encoded form (without decoding). The method implementation should take care of the decoding of the values in such cases:

@GET 
@Produces(MediaType.APPLICATION_JSON) 
public List<Department> 
findAllDepartmentsByName(@QueryParam("name") String deptName) { //Method body is removed for brevity }
URL encoding converts a string into a valid URL format, which may contain alphabetic characters, numerals, and some special characters supported in the URL string. To learn more about the URL specification, visit http://www.w3.org/Addressing/URL/url-spec.html.





































































































































Comments

Popular posts from this blog

Understanding the JAX-RS resource life cycle

Generating a chunked output using Jersey APIs