Monday, February 11, 2013

Sample Apps: Spring data MongoDB and JSF Integration tutorial (PART 4)


Table of Contents:
1. Introduction to sample application (MongoShop Product Catalog)
2. MongoDB schema design and data preparation
3. JSF (PrimeFaces) and Spring data MongoDB Integration
4. Enquriy data with spring data repository and mongotemplate
5. Create, Edit and delete data

Enquriy data with spring data repository and mongotemplate


Spring Data Repository:
Spring Data repository abstraction reduces the boilerplate code to write the data access layer of the application. Automatic implementation of Repository interfaces provides simple operation on mongoDB. It helps our product save and delete function make

MongoTemplate:
MongoTemplate offers convenience operations to create, update, delete and query for MongoDB documents and provides a mapping between your domain objects and MongoDB documents. In our application, since the spring data repository cannot fulfill the requirement of searching function, we use MongoTemplate to archive the searching capability.

Customizing Spring Data Repository
Since the searching of product cannot be easily implement with Spring data repository abstraction, we would like to implements the multi-criteira product search with MongoDBTemplate. To enrich Spring data repository with MongoTemplate, we can do the following to customize the repository:

ProductRepository.java
package com.borislam.repository;

import java.util.List;
import org.springframework.data.repository.PagingAndSortingRepository;
import com.borislam.domain.Product;

public interface ProductRepository  extends PagingAndSortingRepository<Product, String> , ProductRepostitoryCustom{
 
 List<product> findByType(String type);
 List<product> findByTypeAndTitle(String type, String title); 
 Product findBySku(String sku);
}


ProductRepositoryCustom.java
package com.borislam.repository;

import java.util.List;
import com.borislam.domain.Product;
import com.borislam.view.ProductSearchCriteria;


public interface ProductRepostitoryCustom {
 public List<product> searchByCriteria(ProductSearchCriteria criteria);
 
}

ProductRepositoryImpl.java
package com.borislam.repository.impl;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.util.StringUtils;
import com.borislam.domain.Product;
import com.borislam.repository.ProductRepostitoryCustom;
import com.borislam.view.ProductSearchCriteria;

public class ProductRepositoryImpl implements ProductRepostitoryCustom{
 
 @Autowired
 private MongoTemplate mongoTemplate;
 
 @Override
 public List<product> searchByCriteria(ProductSearchCriteria criteria) {
  Query query = new Query();
  if ( StringUtils.hasText(criteria.getSku())) 
  { 
   Criteria c = Criteria.where("sku").is(criteria.getSku());
   query.addCriteria(c);
  }
  if (StringUtils.hasText(criteria.getTitle())) {
   Criteria c = Criteria.where("title").regex(".*" + criteria.getTitle() + ".*", "i");
   query.addCriteria(c);
  }
  if (StringUtils.hasText(criteria.getDescription())) {
   Criteria c = Criteria.where("description").regex(".*" + criteria.getDescription() + ".*", "i");
   query.addCriteria(c);
  }
  if (StringUtils.hasText(criteria.getProductType())) {
   Criteria c = Criteria.where("type").is(criteria.getProductType());
   query.addCriteria(c);
   
  }  
  if (StringUtils.hasText(criteria.getTrack())) {
   Criteria c = Criteria.where("details.tracks").regex(".*" + criteria.getTrack() + ".*", "i");
   query.addCriteria(c);
  }
  if (StringUtils.hasText(criteria.getChapter())) {
   Criteria c = Criteria.where("details.chapters").regex(".*" + criteria.getChapter() + ".*", "i");
   query.addCriteria(c);
  }
  return mongoTemplate.find(query, Product.class);
 }
 
 
}


Data Model:
Product.java
package com.borislam.domain;

public class Product {
  private String id;
  private String sku ;
  private String  type;
  private String title;
  private String description;
  private String publisher;
  private Pricing pricing;
  private Detail details;
 public String getId() {
  return id;
 }
 public void setId(String id) {
  this.id = id;
 }
 public String getSku() {
  return sku;
 }
 public void setSku(String sku) {
  this.sku = sku;
 }
 public String getType() {
  return type;
 }
 public void setType(String type) {
  this.type = type;
 }
 public String getTitle() {
  return title;
 }
 public void setTitle(String title) {
  this.title = title;
 }
 public String getDescription() {
  return description;
 }
 public void setDescription(String description) {
  this.description = description;
 }
 public String getPublisher() {
  return publisher;
 }
 public void setPublisher(String publisher) {
  this.publisher = publisher;
 }
 public Pricing getPricing() {
  return pricing;
 }
 public void setPricing(Pricing pricing) {
  this.pricing = pricing;
 }
 public Detail getDetails() {
  return details;
 }
 public void setDetails(Detail details) {
  this.details = details;
 }    
}
Pricing.java
package com.borislam.domain;




public class Pricing {
 private String id;
 private double list;
 private double retail;
 public String getId() {
  return id;
 }
 public void setId(String id) {
  this.id = id;
 }
 public double getList() {
  return list;
 }
 public void setList(double list) {
  this.list = list;
 }
 public double getRetail() {
  return retail;
 }
 public void setRetail(double retail) {
  this.retail = retail;
 }
 public Pricing(double list, double retail) {
  super();
  this.list = list;
  this.retail = retail;
 }
 
}

Detail.java
package com.borislam.domain;

import java.util.List;

public class Detail {
 private String id;
 private String title;
 private String author;
 private String artist;
 private String genre;
 private List<string> pic;
 private List<string> chapters;
 private List<string> tracks;
 public String getTitle() {
  return title;
 }
 public void setTitle(String title) {
  this.title = title;
 }
 public String getAuthor() {
  return author;
 }
 public void setAuthor(String author) {
  this.author = author;
 }
 public String getGenre() {
  return genre;
 }
 public void setGenre(String genre) {
  this.genre = genre;
 }
 public List<string> getPic() {
  return pic;
 }
 public void setPic(List<string> pic) {
  this.pic = pic;
 }
 public List<string> getChapters() {
  return chapters;
 }
 public void setChapters(List<string> chapters) {
  this.chapters = chapters;
 }
 public String getId() {
  return id;
 }
 public void setId(String id) {
  this.id = id;
 }
 public String getArtist() {
  return artist;
 }
 public void setArtist(String artist) {
  this.artist = artist;
 }
 public List<string> getTracks() {
  return tracks;
 }
 public void setTracks(List<string> tracks) {
  this.tracks = tracks;
 }
 
}


JSF Part:
common.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
 xmlns:h="http://java.sun.com/jsf/html"
 xmlns:f="http://java.sun.com/jsf/core"
 xmlns:ui="http://java.sun.com/jsf/facelets"
 xmlns:p="http://primefaces.org/ui">

<f:view contentType="text/html">

 <h:head>

  <f:facet name="first">
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
   <title><ui:insert name="pageTitle">Page Title</ui:insert></title>
   <ui:insert name="head" />
  </f:facet>

 </h:head>


 <h:body>
  <div style="margin:auto;width:1024px;">
<div id="header" class="ui-widget" >
<div id="logo" style="border:1px  solid #acbece; border-bottom: none; ">
<p:graphicImage   value="/resources/image/mongoshopheader.jpg"/></div>
<div id="logo" style="border:1px solid #acbece;">
<p:menubar style="border:none"><p:menuitem value="Search" url="/search.jsf" icon="ui-icon-search" /><p:menuitem value="New Product" url="/detail.jsf" icon="ui-icon-document" /></p:menubar></div>
</div>
<div id="page" class="ui-widget" style="overflow:hidden;">
<div id="content"  style="display:block">
<ui:insert name="content">...</ui:insert>     
             </div>
</div>
</div>
</h:body>

</f:view>
</html>


Search.xhml
<html xmlns="http://www.w3.org/1999/xhtml"
 xmlns:ui="http://java.sun.com/jsf/facelets"
 xmlns:h="http://java.sun.com/jsf/html"
 xmlns:f="http://java.sun.com/jsf/core"
 xmlns:p="http://primefaces.org/ui">


 <ui:composition template="/template/common.xhtml">
 
  <ui:define name="pageTitle">
   <h:outputText value="Product Search" />
  </ui:define>
 
  <ui:define name="content">
      <h:form id="searchForm">
       <p:growl id="mainGrowl" sticky="true"  /><p:panelGrid style="width:1024px"><f:facet name="header">
     <p:row><p:column colspan="4">Product Search
             </p:column></p:row></f:facet>  
       <p:row><p:column><h:outputLabel for="sku" value="sku: " />
         </p:column><p:column><p:inputText id="sku" value="#{productSearchBean.criteria.sku}" /></p:column><p:column><h:outputLabel for="productType" value="Product Type: " />
         </p:column><p:column><p:selectOneMenu id="productType"   label="Type"   value="#{productSearchBean.criteria.productType}"  ><f:selectItem itemLabel="Select One" itemValue="" />  
                 <f:selectItem itemLabel="Audio Album" itemValue="Audio Album" />  
                 <f:selectItem itemLabel="Book" itemValue="Book" /> 
             </p:selectOneMenu></p:column></p:row><p:row><p:column><h:outputLabel for="title" value="Title: " />
         </p:column><p:column><p:inputText id="title" value="#{productSearchBean.criteria.title}" /></p:column><p:column><h:outputLabel for="description" value="Description: " />
         </p:column><p:column><p:inputText id="description" value="#{productSearchBean.criteria.description}" /></p:column></p:row><p:row><p:column><h:outputLabel for="track" value="Track: " />
         </p:column><p:column><p:inputText id="track" value="#{productSearchBean.criteria.track}" /></p:column><p:column><h:outputLabel for="chapter" value="Chapter: " />
         </p:column><p:column><p:inputText id="chapter" value="#{productSearchBean.criteria.chapter}" /></p:column></p:row></p:panelGrid><p:commandButton value="search" icon="ui-icon-search"  actionListener="#{productSearchBean.doSearch}" update="dataTable"/><hr/><p:dataTable id="dataTable" var="prod" value="#{productSearchBean.productList}"  
     paginator="true" rows="10"><p:column><f:facet name="header">  
                    <h:outputText value="Sku" />  
                </f:facet>  
                <h:outputText value="#{prod.sku}" />  
            </p:column><p:column><f:facet name="header">  
                    <h:outputText value="Type" />  
                </f:facet>  
                <h:outputText value="#{prod.type}" />  
            </p:column><p:column><f:facet name="header">  
                    <h:outputText value="Title" />  
                </f:facet>  
                <h:outputText value="#{prod.title}" />  
            </p:column><p:column><f:facet name="header">  
                    <h:outputText value="Publisher" />  
                </f:facet>  
                <h:outputText value="#{prod.publisher}" />  
            </p:column><p:column><f:facet name="header">  
                    <h:outputText value="Artist" />  
                </f:facet>  
                <h:outputText value="#{prod.details.artist}" />  
            </p:column><p:column><f:facet name="header">  
                    <h:outputText value="Author" />  
                </f:facet>  
                <h:outputText value="#{prod.details.author}" />  
            </p:column></p:dataTable></h:form>
  </ui:define>
 </ui:composition>
</html>

ProductSearchCriteria.java
package com.borislam.view;

public class ProductSearchCriteria {
 private String sku;
 private String description;
 private String productType;
 private String track;
 private String chapter;
 private String title;
 public String getSku() {
  return sku;
 }
 public void setSku(String sku) {
  this.sku = sku;
 }
 public String getDescription() {
  return description;
 }
 public void setDescription(String description) {
  this.description = description;
 }
 public String getProductType() {
  return productType;
 }
 public void setProductType(String productType) {
  this.productType = productType;
 }
 public String getTrack() {
  return track;
 }
 public void setTrack(String track) {
  this.track = track;
 }
 public String getTitle() {
  return title;
 }
 public void setTitle(String title) {
  this.title = title;
 }
 public String getChapter() {
  return chapter;
 }
 public void setChapter(String chapter) {
  this.chapter = chapter;
 }
 
}


ProductSearchBean.java
package com.borislam.view;


import java.util.List;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;
import com.borislam.domain.Product;
import com.borislam.service.ProductService;


@Component
@Scope("session")
public class ProductSearchBean {
 
 private Product selectedProduct;
 
 private ProductSearchCriteria criteria = new ProductSearchCriteria();
 
 private List<product> productList;
 
 
 public Product getSelectedProduct() {
  return selectedProduct;
 }


 public void setSelectedProduct(Product selectedProduct) {
  this.selectedProduct = selectedProduct;
 }


 public List<product> getProductList() {
  return productList;
 }

 public void setProductList(List<product> productList) {
  this.productList = productList;
 }

 public ProductSearchCriteria getCriteria() {
  return criteria;
 }


 public void setCriteria(ProductSearchCriteria criteria) {
  this.criteria = criteria;
 }
 @Autowired
 private ProductService productService;
 
 public void doSearch(ActionEvent event){
  productList= productService.searchByCriteria(criteria);
 }
}


Service Layer:
ProductService.java
package com.borislam.service;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.borislam.domain.Product;
import com.borislam.repository.ProductRepository;
import com.borislam.view.ProductSearchCriteria;


@Service
public class ProductService {
 
 @Autowired
 private ProductRepository productRepository;
 
 public List<product> searchByCriteria(ProductSearchCriteria criteria){
  return productRepository.searchByCriteria(criteria);
 }
 
 public Product getProduct(String sku) {
  return productRepository.findBySku(sku);
 }
}


Part 5 of the tutorial ...

No comments: