JAX-RS Handling QueryString (@QueryParam,@DefaultValue,UriInfo)

This tutorial shows us how to capture Query parameters using @QueryParam and UriInfo and the role of @DefaultValue annotation.

Example Scenario :

We have a rest service which is like a car inventory and has cars of different models and years. For the sake of simplicity, let’s say it has only Honda cars. We want to retrieve one or more cars from the inventory based on different query parameters passed in the request URI.


Project artifacts:

1. Technologies used –

a. Eclipse IDE for Java EE developer 4.5.0.20150621-1200 (Mars)
b. Preinstalled Maven with Eclipse Mars
c. Tomcat 7.0.64
d. RESTEasy 3.0.4.Final
e. Java 1.8

Jars used –

javax.ws.rs-api-2.0.jar
resteasy-jaxrs-3.0.4.Final.jar
jaxrs-api-3.0.4.Final.jar
slf4j-simple-1.5.8.jar
slf4j-api-1.5.8.jar
scannotation-1.0.3.jar
javassist-3.12.1.GA.jar
jboss-annotations-api_1.1_spec-1.0.1.Final.jar
activation-1.1.jar
httpclient-4.2.1.jar
httpcore-4.2.1.jar
commons-logging-1.1.1.jar
commons-codec-1.6.jar
commons-io-2.1.jar
jcip-annotations-1.0.jar

2. Eclipse project folder structure:

JAX-RS QueryParamDirectory Struc

3. Web Project

Create a standard web project in Eclipse by following the below link.

Create a Maven Web Project

4. Maven Dependencies

file:pom.xml. Maven unit of work to declare project dependencies, compile code and build war file for deployment in Tomcat.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.javanbeyond</groupId>
    <artifactId>WorkingWithQueryParam</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>Restful Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>javax.ws.rs</groupId>
            <artifactId>javax.ws.rs-api</artifactId>
            <version>2.0</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jaxrs</artifactId>
            <version>3.0.4.Final</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>WorkingWithQueryParam</finalName>
    </build>
</project>

 5. POJO

file: Car.java. A POJO which is stored as car in Car Inventory web service and data of which is sent to client based on request URI.

package com.javanbeyond.data;

// A simple POJO
public class Car {
  private int id;
  private String make;
  private String model;
  private String exteriorColor;
  private String interiorColor;
  private int year;

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getMake() {
    return make;
  }

  public void setMake(String make) {
    this.make = make;
  }

  public String getModel() {
    return model;
  }

  public void setModel(String model) {
    this.model = model;
  }

  public String getExteriorColor() {
    return exteriorColor;
  }

  public void setExteriorColor(String exteriorColor) {
    this.exteriorColor = exteriorColor;
  }

  public String getInteriorColor() {
    return interiorColor;
  }

  public void setInteriorColor(String interiorColor) {
    this.interiorColor = interiorColor;
  }

  public int getYear() {
    return year;
  }

  public void setYear(int year) {
    this.year = year;
  }

}

6. Application class

file: MyApplication.java. The Class that registers the resource class OrderReceiver with JAX-RS runtime. It has two sets.
Our resource class should be added to the singleton set.

package com.javanbeyond.service;

import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;

// regular application class
public class MyApplication extends Application {
  private Set<Object> singletons = new HashSet<Object>();
  private Set<Class<?>> empty = new HashSet<Class<?>>();

  public MyApplication() {
    singletons.add(new OrderReceiver());
  }

  @Override
  public Set<Class<?>> getClasses() {
    return empty;
  }

  @Override
  public Set<Object> getSingletons() {
    return singletons;
  }
}

7. Resource class

file: OrderReceiver.java . In JAX-RS, we use @QueryParam annotation to capture information provided in the query string of URI and pass it to methods as parameters. The “/cars/{make}” @Path value  before the class, brings the URI “http://localhost:8080/rest/cars/honda” to this class. {make} is mapped to “honda”. The part after this decides which method will be called at runtime.

If you need more information about query string, please refer Http Query String.

Case 1: Getting Query Strings with @QueryParam

The method getCarByQueryParam receives the URI  “/cars/honda/getCarByQueryParam?model=civic&year=1991″ with the values of queries, model and year mapped  to the same name parameters of the method by @QueryParam. The method returns a car with model as Civic and year as 1991.

// Request match : /cars/honda/getCarByQueryParam?model=civic&year=1991
  // Needed a car with year as 1991 and model as civic. Simple query parameter
  // matching
  @GET
  @Path("getCarByQueryParam")
  @Produces(MediaType.APPLICATION_XML)
  public StreamingOutput getCarByQueryParam(@QueryParam("model"String model,
      @QueryParam("year"int year) {
    System.out.println("in getCarByQueryParam");
    for (Entry<Integer, Car> carEntry : carInventory.entrySet()) {
      final Car car = carEntry.getValue();
      if (car.getModel().equalsIgnoreCase(model)
          && car.getYear() == year) {
        return new StreamingOutput() {
          public void write(OutputStream outputStream)
              throws IOException, WebApplicationException {
            outputRequestedItem(outputStream, car);
          }
        };
      }
    }
    return null;

  }

Case 2 : Query String from UriInfo

In the method getCarByQueryInfo , query strings are extracted using UriInfo class which is injected by @Context annotation. This method tackles URI “/cars/honda/getCarByQueryInfo?model=civic&year=1991″  and returns a car with model as Civic and year as 1991.

// Request match : /cars/honda/getCarByQueryInfo?model=civic&year=1991
  // Using UriInfo

  @GET
  @Path("getCarByQueryInfo")
  @Produces(MediaType.APPLICATION_XML)
  public StreamingOutput getCarByQueryInfo(@Context UriInfo uriInfo) {
    System.out.println("in getCarByQueryInfo");
    int year = Integer
        .valueOf(uriInfo.getQueryParameters().getFirst("year"));
    String model = uriInfo.getQueryParameters().getFirst("model");
    for (Entry<Integer, Car> carEntry : carInventory.entrySet()) {
      final Car car = carEntry.getValue();
      if (car.getModel().equalsIgnoreCase(model)
          && car.getYear() == year) {
        return new StreamingOutput() {
          public void write(OutputStream outputStream)
              throws IOException, WebApplicationException {
            outputRequestedItem(outputStream, car);
          }
        };
      }
    }
    return null;

  }

Case 3: Missing query string and @DefaultValue annotation

When the URI “/cars/honda/getCarByDefaultValue?color=white” hits the service, the missing query string ‘year’ is given a default value 2000 provided by @DefaultValue annotation. This annotation helps resolving optional query parameters. Please note that default value provided will be used only if the value is missing.In the below case, though default value is provided for both the parameters, only missing ‘year’ query parameter will be given a default value.

// Request match : /cars/honda/getCarByDefaultValue?color=white
  // Using @Default annotation

  @GET
  @Path("getCarByDefaultValue")
  @Produces(MediaType.APPLICATION_XML)
  public StreamingOutput getCarByDefaultValue(
      @DefaultValue("2000"@QueryParam("year"int year,
      @DefaultValue("white"@QueryParam("color"String color) {
    System.out.println("in getCarByDefaultValue");
    for (Entry<Integer, Car> carEntry : carInventory.entrySet()) {
      final Car car = carEntry.getValue();
      if (car.getInteriorColor().equalsIgnoreCase(color)
          && car.getYear() == year) {
        return new StreamingOutput() {
          public void write(OutputStream outputStream)
              throws IOException, WebApplicationException {
            outputRequestedItem(outputStream, car);
          }
        };
      }
    }
    return null;

  }

8. Deployment descriptor

file: web.xml . Deployment descriptor file for mapping URIs to servlet. Application class is registered by setting as init param to the servlet.

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
    <display-name>Archetype Created Web Application</display-name>
    <context-param>
        <param-name>resteasy.servlet.mapping.prefix</param-name>
        <param-value>/rest</param-value>
    </context-param>
    <servlet>
        <servlet-name>rest</servlet-name>
        <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.javanbeyond.service.MyApplication</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>rest</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>client.html</welcome-file>
    </welcome-file-list>
</web-app>

 

Example Execution:

1. Deploy the application in Tomcat.

2. Open your favorite browser and type the url – “http://localhost:8080/WorkingWithQueryParam/rest/cars/honda/getCarByQueryParam?model=civic&year=1991” and press Enter. You will get an XML response of a car of Civic model and year 1991.

JAX-RS Query Parameter Response

3. Type the url  “http://localhost:8080/WorkingWithQueryParam/rest/cars/honda/getCarByQueryInfo?model=civic&year=1991” and press enter. You will get the below response:

JAX-RS UriInfo REST

4. Type the url “http://localhost:8080/WorkingWithQueryParam/rest/cars/honda/getCarByDefaultValue?color=white” and press Enter.

JAX-RS DefaultValue Example

 

Leave a Reply

Back to Top
%d bloggers like this: