Custom Converter Data Type in JSF Framework


On the Eclipse, create a Maven project

Click Next button and select maven-archetype-webapp

Click Next button and enter Project Information:

  • GroupId: LearnJSFFrameworkWithRealApps
  • Artifact Id: LearnJSFFrameworkWithRealApps
  • Package: com.demo

Click Finish button to finish create Maven project. Add Libraries and Dynamic Web Module as below:

  1. Select project and right click, select Properties menu
  2. Select Project Facets on left side
  3. Select Dynamic Web Module
  4. Select JavaServer Faces




Open web.xml file in src\main\webapp\WEB-INF folder and add configurations for JSF Framework as below:

<?xml version="1.0" encoding="UTF-8"?>
<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_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>LearnJSFFrameworkWithRealApps</display-name>
	<context-param>
		<param-name>javax.faces.PROJECT_STAGE</param-name>
		<param-value>Development</param-value>
	</context-param>
	<welcome-file-list>
		<welcome-file>faces/index.xhtml</welcome-file>
	</welcome-file-list>
	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>/faces/*</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.jsf</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.faces</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.xhtml</url-pattern>
	</servlet-mapping>
</web-app>

Open pom.xml file and add configurations for JSF Framework as below:

<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.demo</groupId>
	<artifactId>LearnJSFFrameworkWithRealApps</artifactId>
	<packaging>war</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>LearnJSFFrameworkWithRealApps Maven Webapp</name>
	<url>http://maven.apache.org</url>

	<dependencies>
		<dependency>
			<groupId>com.sun.faces</groupId>
			<artifactId>jsf-api</artifactId>
			<version>2.2.8</version>
		</dependency>
		<dependency>
			<groupId>com.sun.faces</groupId>
			<artifactId>jsf-impl</artifactId>
			<version>2.2.17</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.1</version>
		</dependency>
		<dependency>
			<groupId>com.sun.el</groupId>
			<artifactId>el-ri</artifactId>
			<version>1.0</version>
		</dependency>
		<dependency>
		    <groupId>mysql</groupId>
		    <artifactId>mysql-connector-java</artifactId>
		    <version>8.0.11</version>
		</dependency>
		<dependency>
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-core</artifactId>
		    <version>5.2.16.Final</version>
		</dependency>
		<dependency>
		    <groupId>org.hibernate</groupId>
		    <artifactId>hibernate-entitymanager</artifactId>
		    <version>5.2.16.Final</version>
		</dependency>
	</dependencies>

	<build>
		<finalName>LearnJSFFrameworkWithRealApps</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.1</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Create a database with the name is learn_jsf_with_real_apps. This database have 2 tables: Category table and Product table

--
-- Table structure for table `category`
--

CREATE TABLE `category` (
  `id` int(11) Primary Key AUTO_INCREMENT,
  `name` varchar(250) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Dumping data for table `category`
--

INSERT INTO `category` (`name`) VALUES('Category 1');
INSERT INTO `category` (`name`) VALUES('Category 2');
INSERT INTO `category` (`name`) VALUES('Category 3');

--
-- Table structure for table `product`
--

CREATE TABLE `product` (
  `id` int(11) Primary Key AUTO_INCREMENT,
  `name` varchar(250) COLLATE utf8_unicode_ci NOT NULL,
  `price` decimal(10,1) NOT NULL,
  `quantity` int(11) NOT NULL,
  `description` text COLLATE utf8_unicode_ci NOT NULL,
  `status` tinyint(1) NOT NULL,
  `category_id` int(11) NOT NULL,
   FOREIGN KEY (`category_id`) REFERENCES `category` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

--
-- Dumping data for table `product`
--

INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Mobile 2', '1.0', 5, 'description 2', 1, 1);
INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Mobile 1', '2.0', 2, 'description 1', 1, 1);
INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Mobile 3', '3.0', 9, 'description 3', 1, 1);
INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Computer 1', '5.0', 12, 'description 4', 0, 1);
INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Computer 2', '7.0', 5, 'description 5', 1, 2);
INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Computer 3', '12.0', 2, 'description 6', 1, 2);
INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Laptop 1', '3.0', 8, 'description 7', 0, 2);
INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Laptop 2', '4.0', 11, 'description 8', 0, 3);
INSERT INTO `product` (`name`, `price`, `quantity`, `description`, `status`) VALUES('Laptop 3', '2.0', 15, 'description 9', 1, 3);




Create new package, named com.entities. In this package, create new entities as below:

In com.entities package, create new java class named Category.java as below:

package com.entities;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "category")
public class Category implements Serializable {

	private Integer id;
	private String name;
	private Set<Product> products = new HashSet<Product>(0);

	@Id
	@GeneratedValue(strategy = IDENTITY)
	public Integer getId() {
		return this.id;
	}

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

	@Column
	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@OneToMany(fetch = FetchType.LAZY, mappedBy = "category")
	public Set<Product> getProducts() {
		return this.products;
	}

	public void setProducts(Set<Product> products) {
		this.products = products;
	}

	@Override
	public boolean equals(Object obj) {
		if (!(obj instanceof Category)) {
			return false;
		}
		Category category = (Category) obj;
		return (this.id == category.id);
	}

}

In com.entities package, create new java class named Product.java as below:

package com.entities;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "product")
public class Product implements Serializable {

	private Integer id;
	private Category category;
	private String name;
	private double price;
	private int quantity;
	private String description;
	private boolean status;

	@Id
	@GeneratedValue(strategy = IDENTITY)
	public Integer getId() {
		return this.id;
	}

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

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "category_id", nullable = false)
	public Category getCategory() {
		return this.category;
	}

	public void setCategory(Category category) {
		this.category = category;
	}

	@Column
	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Column
	public double getPrice() {
		return this.price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	@Column
	public int getQuantity() {
		return this.quantity;
	}

	public void setQuantity(int quantity) {
		this.quantity = quantity;
	}

	@Column
	public String getDescription() {
		return this.description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	@Column
	public boolean isStatus() {
		return this.status;
	}

	public void setStatus(boolean status) {
		this.status = status;
	}

	@Override
	public boolean equals(Object obj) {
		if (!(obj instanceof Product)) {
			return false;
		}
		Product product = (Product) obj;
		return (this.id == product.id);
	}

}

Create new xml file named hibernate.cfg.xml in src\main\java folder as below:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                                         "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory>
		<property name="hibernate.enable_lazy_load_no_trans">true</property>
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.password">123456</property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/learn_jsf_with_real_apps</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		<property name="hibernate.current_session_context_class">thread</property>
		<mapping class="com.entities.Category" />
		<mapping class="com.entities.Product" />
	</session-factory>
</hibernate-configuration>




Create new package named com.models. In this package, create new java class named HibernateUtil.java as below:

package com.models;

import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

public class HibernateUtil {

	private static final SessionFactory sessionFactory;

	static {
		try {
			StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder().configure("hibernate.cfg.xml").build();
			Metadata metaData = new MetadataSources(standardRegistry).getMetadataBuilder().build();
			sessionFactory = metaData.getSessionFactoryBuilder().build();
		} catch (Throwable th) {
			throw new ExceptionInInitializerError(th);
		}
	}

	public static SessionFactory getSessionFactory() {
		return sessionFactory;

	}
}

Create new package named com.models. In this package, create new models as below:

In com.models package, create new java class named CategoryModel.java as below:

package com.models;

import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.entities.Category;

public class CategoryModel {

	private SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List<Category> findAll() {
		List<Category> categories = null;
		Session session = null;
		Transaction transaction = null;
		try {
			session = sessionFactory.openSession();
			transaction = session.beginTransaction();
			org.hibernate.query.Query query = session.createQuery("from Category");
			categories = query.getResultList();
			transaction.commit();
		} catch (Exception e) {
			categories = null;
			if (transaction != null) {
				transaction.rollback();
			}
		} finally {
			session.close();
		}
		return categories;
	}

	@SuppressWarnings({ "rawtypes" })
	public Category find(int id) {
		Category category = null;
		Session session = null;
		Transaction transaction = null;
		try {
			session = sessionFactory.openSession();
			transaction = session.beginTransaction();
			org.hibernate.query.Query query = session.createQuery("from Category where id = :id");
			query.setParameter("id", id);
			category = (Category) query.getSingleResult();
			transaction.commit();
		} catch (Exception e) {
			category = null;
			if (transaction != null) {
				transaction.rollback();
			}
		} finally {
			session.close();
		}
		return category;
	}

}

In com.models package, create new java class named ProductModel.java as below:

package com.models;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.entities.Product;

public class ProductModel {

	private SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

	public boolean create(Product product) {
		boolean result = true;
		Session session = null;
		Transaction transaction = null;
		try {
			session = sessionFactory.openSession();
			transaction = session.beginTransaction();
			session.save(product);
			transaction.commit();
		} catch (Exception e) {
			result = false;
			if (transaction != null) {
				transaction.rollback();
			}
		} finally {
			session.close();
		}
		return result;
	}

}




Create new package named com.demo in src/main/java folder. In this package, create new java class named ProductManagedBean.java as below:

package com.demo;

import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import com.entities.Category;
import com.entities.Product;
import com.models.CategoryModel;
import com.models.ProductModel;

@SessionScoped
@ManagedBean(name = "productManagedBean")
public class ProductManagedBean {

	private Product product;
	private List<Category> categories;

	public ProductManagedBean() {
		CategoryModel categoryModel = new CategoryModel();
		this.product = new Product();
		this.categories = categoryModel.findAll();
	}

	public List<Category> getCategories() {
		return categories;
	}

	public void setCategories(List<Category> categories) {
		this.categories = categories;
	}

	public Product getProduct() {
		return product;
	}

	public void setProduct(Product product) {
		this.product = product;
	}

	public String save() {
		ProductModel productModel = new ProductModel();
		productModel.create(this.product);
		return "success?faces-redirect=true";
	}

}

Create new package named com.converters in src/main/java folder. In this package, create new java class named CategoryConverter.java as below:

package com.converters;

import javax.faces.bean.ManagedBean;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import com.entities.Category;
import com.models.CategoryModel;

@ManagedBean(name = "categoryConverter")
@FacesConverter(value = "categoryConverter")
public class CategoryConverter implements Converter {

	@Override
	public Category getAsObject(FacesContext facesContext, UIComponent uiComponent, String value) {
		try {
			CategoryModel categoryModel = new CategoryModel();
			Category category = categoryModel.find(Integer.parseInt(value));
			return category;
		} catch (Exception e) {
			return null;
		}
	}

	@Override
	public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object value) {
		Category category = (Category) value;
		return String.valueOf(category.getId());
	}

}

Create new xhtml files in src\main\webapp as below:

Create new xhtml file named index.xhtml as below:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html">

<h:head></h:head>
<body>

	<h3>Add New Product</h3>
	<h:form>
		<table cellpadding="2" cellspacing="2">
			<tr>
				<td>Name</td>
				<td>
					<h:inputText value="#{productManagedBean.product.name}"></h:inputText>
				</td>
			</tr>
			<tr>
				<td>Price</td>
				<td>
					<h:inputText value="#{productManagedBean.product.price}"></h:inputText>
				</td>
			</tr>
			<tr>
				<td>Quantity</td>
				<td>
					<h:inputText value="#{productManagedBean.product.quantity}"></h:inputText>
				</td>
			</tr>
			<tr>
				<td>Description</td>
				<td>
					<h:inputTextarea cols="20" rows="5" value="#{productManagedBean.product.description}"></h:inputTextarea>
				</td>
			</tr>
			<tr>
				<td>Status</td>
				<td>
					<h:selectBooleanCheckbox value="#{productManagedBean.product.status}"></h:selectBooleanCheckbox>
				</td>
			</tr>
			<tr>
				<td>Category</td>
				<td>
					<h:selectOneMenu id="aaa" value="#{productManagedBean.product.category}"  converter="#{categoryConverter}">
						<f:selectItems var="category"
							value="#{productManagedBean.categories}"
							itemLabel="#{category.name}"
							itemValue="#{category}"></f:selectItems>
					</h:selectOneMenu>
				</td>
			</tr>
			<tr>
				<td>&nbsp;</td>
				<td>
					<h:commandButton value="Save" action="#{productManagedBean.save()}"></h:commandButton>
				</td>
			</tr>
		</table>
	</h:form>

</body>
</html>

Create new xhtml file named success.xhtml as below:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:c="http://java.sun.com/jsp/jstl/core">

<h:head></h:head>
<body>

	<h3>Success Page</h3>
	<p>Add new product successfully</p>

</body>
</html>




Select project, right click and select Run on Server menu

Access index.xhtml page with following url:

http://localhost:8080/LearnJSFFrameworkWithRealApps/faces/index.xhtml