This tutorial shows how to use ValueChangeListener to create dependent dropdown in JSF 2 and MySQL. I have used here JSF valueChangeListener which fires value change event when select option gets change. Any component that receives user input, such as one of the HTML select or text input components, can publish value change events.
Prerequisites

MySQL database
JSF 2.2
Tomcat 7
JDK 1.6_43
jar files
valuechangelistener example in jsf

At the end of this example you will be able to see this output in the browser:

When the index.jsf file gets executed

valuechangelistener example in jsf
When you select the parent category and for this category if there is any sub-category
valuechangelistener example in jsf
When you select sub-category and press the submit button
valuechangelistener example in jsf
Now look at the below source codes.

Create MySQL database tables

Table – category

CREATE TABLE `category` (
  `category_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `category_name` varchar(50) COLLATE latin1_general_ci NOT NULL,
  `category_link` varchar(255) COLLATE latin1_general_ci NOT NULL,
  `parent_id` int(10) unsigned NOT NULL DEFAULT '0',
  `sort_order` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`category_id`),
  UNIQUE KEY `unique` (`category_name`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;

 

Insert some data

insert  into `category`(`category_id`,`category_name`,`category_link`,`parent_id`,`sort_order`) values (1,'Tutorials','tutorials',0,1),
(2,'Java','java',1,1),
(3,'Liferay','liferay',1,1),
(4,'Frameworks','frameworks',0,2),
(5,'JSF','jsf',4,2),
(6,'Struts','struts',4,2),
(7,'Spring','spring',4,2),
(8,'Hibernate','hibernate',4,2),
(9,'Webservices','webservices',0,3),
(10,'REST','rest',9,3),
(11,'SOAP','soap',9,3);

 

Table – tutorial

CREATE TABLE `tutorial` (
  `category_id` int(10) unsigned NOT NULL,
  `no_of_tutorials` int(10) unsigned NOT NULL,
  KEY `fk_category_id` (`category_id`),
  CONSTRAINT `fk_category_id` FOREIGN KEY (`category_id`) REFERENCES `category` (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;

 

Insert some data

insert  into `tutorial`(`category_id`,`no_of_tutorials`) values (2,3),(3,2),(5,1),(6,5),(7,3),(8,4);

 

Now we will look into the JSF part Deployment descriptor – web.xml

<?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" 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>jsf2-combobox</display-name>
    <!-- mention whether development or production environment -->
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>
    <!-- load the faces servlet on application start up -->
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!-- url pattern mapping for the faces servlet -->
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>
    <!-- welcome file, file extension mapping must match url pattern mapping -->
    <welcome-file-list>
        <welcome-file>index.jsf</welcome-file>
    </welcome-file-list>
</web-app>

 

Look at the view file – index.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<h:head>
<title>JSF 2.x dependent dropdown Example</title>
</h:head>
<h:body>
<h2>Select and see the results</h2>
<p>
<h:form prependid="false">
<!-- html table having only one column -->
<h:panelgrid columns="1">
<!-- check category list not empty -->
<h:panelgroup rendered="#{!empty comboboxMBean.categories}">
Category:
<h:selectonemenu value="#{comboboxMBean.category}" --="" when="" option="" gets="" selected="selected" submit="" the="" form="">
onchange="submit()"
<!-- get the new value -->
valueChangeListener="#{comboboxMBean.onCategorySelect}"&gt;
<!-- populate select, option with the db values -->
<f:selectitems value="#{comboboxMBean.categories}" var="cat" itemlabel="#{cat.name}" itemvalue="#{cat.id}"></f:selectitems>
</h:selectonemenu>
</h:panelgroup>
<!-- check sub-category list not empty -->
<h:panelgroup rendered="#{!empty comboboxMBean.subCategories}">
Sub-category:
<h:selectonemenu value="#{comboboxMBean.subCategory}" onchange="submit()" valuechangelistener="#{comboboxMBean.onSubcategorySelect}">
<f:selectitems value="#{comboboxMBean.subCategories}" var="subCat" itemlabel="#{subCat.name}" itemvalue="#{subCat.id}"></f:selectitems>
</h:selectonemenu>
</h:panelgroup>
<!-- if number of tutorial found for the category/subcategory then print -->
<h:panelgroup rendered="#{comboboxMBean.noOfTutorials gt 0}">
No. of Tutorials: #{comboboxMBean.noOfTutorials}
</h:panelgroup>
<!-- if number of tutorial not found for the category/subcategory then print -->
<h:panelgroup rendered="#{comboboxMBean.noOfTutorials lt 0}">
No tutorial found for this category!
</h:panelgroup>
</h:panelgrid>
</h:form>
</p>
</h:body>

 

JSF managed bean – ComboboxMBean.java. I am not going to use faces-config.xml file so I have used annotation based configuration for managed bean.

import java.io.Serializable;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ValueChangeEvent;
//it is a jsf managed bean
@ManagedBean
//scope of the managed bean
@ViewScoped
//if the managed bean is in ViewScoped or SessionScoped then you must implement Serializable
public class ComboboxMBean implements Serializable {
    /**
     *
     */
    private static final long serialVersionUID = 1L;
    private Integer category;
    private Integer subCategory;
    private Integer noOfTutorials;
    private List categories;
    private List subCategories;
    private QueryHelper queryHelper;
    public ComboboxMBean() {
        queryHelper = new QueryHelper();
    }
    public Integer getCategory() {
        return category;
    }
    public void setCategory(Integer category) {
        this.category = category;
    }
    public Integer getSubCategory() {
        return subCategory;
    }
    public void setSubCategory(Integer subCategory) {
        this.subCategory = subCategory;
    }
    public Integer getNoOfTutorials() {
        populateNoOfTutorials();
        return noOfTutorials;
    }
    public void setNoOfTutorials(Integer noOfTutorials) {
        this.noOfTutorials = noOfTutorials;
    }
    public List getCategories() {
        if (categories == null) {
            populateCategories();
        }
        return categories;
    }
    public void setCategories(List categories) {
        this.categories = categories;
    }
    public List getSubCategories() {
        populateSubCategories();
        return subCategories;
    }
    public void setSubCategories(List subCategories) {
        this.subCategories = subCategories;
    }
    private void populateCategories() {
        categories = queryHelper.getAllCategories();
    }
    private void populateSubCategories() {
        if (category != null) {
            subCategories = queryHelper.getAllSubCategories(category);
        }
    }
    private void populateNoOfTutorials() {
        if (subCategory != null) {
            noOfTutorials = queryHelper.getNoOfTutorials(subCategory);
        }
    }
    //when category selection gets changed
    public void onCategorySelect(ValueChangeEvent vce) {
        Integer newCat = Integer.valueOf(vce.getNewValue().toString());
        if (newCat != category) {
            setCategory(newCat);
        }
    }
    //when sub-category selection gets changed
    public void onSubcategorySelect(ValueChangeEvent vce) {
        Integer newSubcat = Integer.valueOf(vce.getNewValue().toString());
        if (newSubcat != subCategory) {
            setSubCategory(newSubcat);
        }
    }
}

 

Model – Category.java

public class Category {
    
    private Integer id;
    private String name;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

 

Constant declarations – Constants.java

public class Constants {
    private Constants() {
    }
    // DB Constants
    public static final String DB_USER_NAME = "root";
    public static final String DB_USER_PASSWORD = "";
    public static final String DB_INSTANCE_NAME = "cdcol";
    public static final String DB_CONNECTION_URL = "jdbc:mysql://localhost:3306";
    public static final String DB_DRIVER_CLASS = "com.mysql.jdbc.Driver";
}

 

Database helper class for database related common functionality

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DBHelper {
    /**
     * to load the database driver
     *
     * @return a database connection
     * @throws SQLException
     *             throws an exception if an error occurs
     */
    public static Connection getDBConnection() throws SQLException {
        Connection conn = null;
        try {
            Class.forName(Constants.DB_DRIVER_CLASS);
            conn = DriverManager.getConnection(Constants.DB_CONNECTION_URL
                    + "/" + Constants.DB_INSTANCE_NAME, Constants.DB_USER_NAME,
                    Constants.DB_USER_PASSWORD);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }
    /**
     * to get a result set of a query
     *
     * @param query
     *            custom query
     * @return a result set of custom query
     * @throws SQLException
     *             throws an exception if an error occurs
     */
    public static ResultSet getDBResultSet(Connection conn, String query)
            throws SQLException {
        ResultSet rs = null;
        if (null != conn) {
            PreparedStatement st = conn.prepareStatement(query);
            rs = st.executeQuery();
        }
        return rs;
    }
    /**
     * to run an update query such as update, delete
     *
     * @param query
     *            custom query
     * @throws SQLException
     *             throws an exception if an error occurs
     */
    public static void runQuery(Connection conn, String query)
            throws SQLException {
        if (null != conn) {
            PreparedStatement st = conn.prepareStatement(query);
            st.executeUpdate();
        } else {
            System.out.println("Query execution failed!");
        }
    }
    /**
     * close an opened PreparedStatement
     *
     * @return a void
     * @throws SQLException
     *             throws an exception if an error occurs
     */
    public static void closePreparedStatement(PreparedStatement ps)
            throws SQLException {
        if (null != ps) {
            ps.close();
        }
    }
    /**
     * close an opened ResultSet
     *
     * @return a void
     * @throws SQLException
     *             throws an exception if an error occurs
     */
    public static void closeResultSet(ResultSet rs) throws SQLException {
        if (null != rs) {
            rs.close();
        }
    }
    /**
     * close an opened database connection
     *
     * @return a void
     * @throws SQLException
     *             throws an exception if an error occurs
     */
    public static void closeDBConnection(Connection conn) throws SQLException {
        if (null != conn) {
            conn.close();
        }
    }
}

 

QueryHelper for database query

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class QueryHelper {
    public List getAllCategories() {
        Connection connection = null;
        List categories = new ArrayList();
        Category emptyCat = new Category();
        emptyCat.setId(0);
        emptyCat.setName("-- Select Category --");
        categories.add(emptyCat);
        try {
            connection = DBHelper.getDBConnection();
            if (connection != null) {
                String sql = "SELECT category_id, category_name FROM category WHERE parent_id=0";
                ResultSet resultSet = DBHelper.getDBResultSet(connection, sql);
                if (resultSet != null) {
                    while (resultSet.next()) {
                        Category category = new Category();
                        category.setId(resultSet.getInt(1));
                        category.setName(resultSet.getString(2));
                        categories.add(category);
                    }
                    return categories;
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (connection != null) {
                    DBHelper.closeDBConnection(connection);
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    public List getAllSubCategories(Integer category_id) {
        Connection connection = null;
        List categories = new ArrayList();
        Category emptyCat = new Category();
        emptyCat.setId(0);
        emptyCat.setName("-- Select Sub-category --");
        try {
            connection = DBHelper.getDBConnection();
            if (connection != null) {
                String sql = "SELECT category_id, category_name FROM category WHERE parent_id="
                        + category_id;
                ResultSet resultSet = DBHelper.getDBResultSet(connection, sql);
                if (resultSet != null) {
                    categories.add(emptyCat);
                    while (resultSet.next()) {
                        Category category = new Category();
                        category.setId(resultSet.getInt(1));
                        category.setName(resultSet.getString(2));
                        categories.add(category);
                    }
                    return categories;
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (connection != null) {
                    DBHelper.closeDBConnection(connection);
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    public Integer getNoOfTutorials(Integer category_id) {
        Connection connection = null;
        try {
            connection = DBHelper.getDBConnection();
            if (connection != null) {
                String sql = "SELECT no_of_tutorials FROM tutorial WHERE category_id="
                        + category_id;
                ResultSet resultSet = DBHelper.getDBResultSet(connection, sql);
                if (resultSet != null) {
                    if (resultSet.next()) {
                        Integer no = resultSet.getInt(1);
                        return no;
                    }
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (connection != null) {
                    DBHelper.closeDBConnection(connection);
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

 

Thanks for your reading. Please do not forget to leave a comment. Comment helps to improve.

Tags:

I am a professional Web developer, Enterprise Application developer, Software Engineer and Blogger. Connect me on Roy Tutorials | TwitterFacebook Google PlusLinkedin | Reddit

Leave a Reply

Your email address will not be published. Required fields are marked *