Module 7: Product Service RESTful Web Service: Pagination and Filtering - dineshmadhup/RESTful-Web-Service GitHub Wiki
In this Module there ischange in code in STEP-3 (ProductService.java) and STEP-4 (ProductResource.java) compare to Module-6. Also one new File is added called ProductFilterBean.java
The aim of Pagination and Filtering is to allow the user to find and filter the products of user choice.
http://localhost:8080/productService/webapi/products?start=1&size=1 http://localhost:8080/productService/webapi/products?year=2016
In this demonstration we show you three operation which is: Create, Read and Update
First of all we have created Product model which has some features which is:
Product id => pid
Product name =>productName
Product Price =>productPrice
Date Created => created
In Java we have defined the Product features with the help of Constructors and and some methods - setters and getters as shown below:
Package: org.dinesh.softarica.productService.model
Product.java
@XmlRootElement
public class Product {
private long pid;
private String productName;
private Date created;
private String productPrice;
public Product() {
}
public Product(long pid, String productName, String productPrice) {
this.pid = pid;
this.productName = productName;
this.productPrice = productPrice;
this.created = new Date();
}
public long getPid() {
return pid;
}
public void setPid(long pid) {
this.pid = pid;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public String getProductPrice() {
return productPrice;
}
public void setProductPrice(String productPrice) {
this.productPrice = productPrice;
}
}
}
Here you notice the annotation we have used @XmlRootElement
The @XmlRootElement annotation can be used with the following program elements:
• a top level class
• an enum type
When a top level class or an enum type is annotated with the @XmlRootElement annotation, then its value is represented as XML element in an XML document.
Now the Product is needed to be stored in databases. Rather than creating database using MySQL or SQL we have used Map to store the products.
Package: org.dinesh.softarica.productService.database
DatabaseClass.java
public class DatabaseClass {
private static Map<Long, Product> myProducts = new HashMap<>();
public static Map<Long, Product>getProduct() {
return myProducts;
}
}
Now we create a service where we define some methods so that we can store product details in DatabaseClass.
package: org.dinesh.softarica.productService.service;
ProductService.java
public class ProductService {
// Creating MAP with Key Long and value Product
private Map<Long, Product> myProducts = DatabaseClass.getProduct();
// No-arg constructor
public ProductService() {
myProducts.put(1L, new Product(1, "IPhone7", "900"));
}
public List<Product> getAllProducts() {
return new ArrayList<Product>(myProducts.values());
}
public Product getProduct(long id) {
return myProducts.get(id);
}
//Filtering based on year
public List<Product> getAllProductsForYear(int year) {
List<Product> productsForYear = new ArrayList<>();
Calendar cal = Calendar.getInstance();
for(Product product: myProducts.values()) {
cal.setTime(product.getCreated());
if(cal.get(Calendar.YEAR) == year) {
productsForYear.add(product);
}
}
return productsForYear;
}
// Pagination
public List<Product> getAllProductsPaginated(int start, int size) {
ArrayList<Product> list = new ArrayList<Product>(myProducts.values());
if(start + size > list.size())
return new ArrayList<Product>();
return list.subList(start, start + size);
}
// Create operation
public Product addProduct(Product product) {
product.setPid(myProducts.size() + 1);
myProducts.put(product.getPid(), product);
return product;
}
// Update Product
public Product updateProduct(Product product) {
if(product.getPid() <= 0) {
return null;
}
myProducts.put(product.getPid(), product);
return product;
}
// Delete Operation
public Product removeProduct(long pid) {
return myProducts.remove(pid);
}
}
Creating resources
package: org.dinesh.softarica.productService.resources;
ProductResource.java
@Path("/products")
/* Adding Produces and Consumes annotation on class level /
/ do not require at each individual method */
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class ProductResource {
ProductService productService = new ProductService();
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<Product> getJsonProduct(@BeanParam ProductFilterBean filterBean) {
System.out.println("Json method is called");
if(filterBean.getYear() > 0) {
return productService.getAllProductsForYear(filterBean.getYear());
}
if(filterBean.getStart() >=0 && filterBean.getSize() > 0) {
return productService.getAllProductsPaginated(filterBean.getStart(), filterBean.getSize());
}
return productService.getAllProducts();
}
@GET
@Produces(MediaType.TEXT_XML)
public List<Product> getXmlProduct(@BeanParam ProductFilterBean filterBean) {
System.out.println("Json method is called");
if(filterBean.getYear() > 0) {
return productService.getAllProductsForYear(filterBean.getYear());
}
if(filterBean.getStart() >=0 && filterBean.getSize() > 0) {
return productService.getAllProductsPaginated(filterBean.getStart(), filterBean.getSize());
}
return productService.getAllProducts();
}
@GET
@Path("/{productId}")
public Product getproduct(@PathParam("productId") long pid) {
return productService.getProduct(pid);
}
@POST
//@Consumes(MediaType.APPLICATION_JSON)
//@Produces(MediaType.APPLICATION_JSON)
public Product addProduct(Product product) {
return productService.addProduct(product);
}
@PUT
@Path("/{productId}")
public Product updateProduct(@PathParam("productId") long pid, Product product) {
product.setPid(pid);
return productService.updateProduct(product);
}
@DELETE
@Path("/{productId}")
public Product deleteProduct(@PathParam("productId") long pid) {
return productService.removeProduct(pid);
}
}
package org.dinesh.softarica.productService.resources.bean;
ProductFilterBean.java public class ProductFilterBean {
private @QueryParam("year") int year;
private @QueryParam("start") int start;
private @QueryParam("size") int size;
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
The annotation we have used is:
@Path(“/products”)
on the top level of the class named ProductResource which contains method getProduct and annotated with @GET
http://localhost:8080/productService/webapi/products/
By choosing GET operation see the list of products:
Filtering: Lets Filter the product based on year: 2016
Filtering: But if we search product for year 2015 then we don't get any because there are no any product created in 2015.
Pagination: start=0 & size=1
Pagination: start=0 & size=2
Pagination: start=1 & size=1
Download: Source Code