FAQ: How to add Search features to the JSF App?

A number of students have asked how to add search features to the JSF app? I'll walk through this process.

Basically, we will allow the user to search for a customer by name. We'll add a search box at to the screen and the user can enter a name. On the backend, we'll compare this name to the customer's first name or last name.


---

Overview of Development Process
1. Create the Search form
2. Add routing logic in StudentController managed bean
3. Add method in the StudentDbUtil to perfom search

---

Download Source Code
All of the complete solution code is available for download. See Resources section at the bottom of this lecture.


---
Detailed Steps

I will show you the detailed steps below so you can see what is added to each file.


1. Create the Search form

You need to add a search form to read the user input and submit it to your JSF Managed Bean

a. Edit the file: list-students.xhtml

b. Add a search form right after the "Add Student" button

            <!--  add a search box -->
            <h:form>
        
                <h:outputLabel>Search student:</h:outputLabel> <h:inputText value="#{studentController.theSearchName}" id="theSearchName" />
                
                <h:commandButton value="Search" action="list-students?faces-redirect=true" styleClass="add-student-button" />            
            
            </h:form>

This sends over a search request to our StudentController managed bean. It includes theSearchName the user entered. The view page will be the list-students.xhtml.

---

2. Add search logic in StudentController bean

You need to add search logic in the StudentControllerServlet to handle the search form submission

a. Edit the file: StudentController.java

b. Add a new private field for the "searchName". This is the search data entered by the user on the form.

    private String theSearchName; 

c. Add getter setter methods for this new field.

    public String getTheSearchName() {
        return theSearchName;
    }
    public void setTheSearchName(String theSearchName) {
        this.theSearchName = theSearchName;
    }

d. Move to the loadStudents() methods.

Update your loadStudents() method so it looks like this:

    public void loadStudents() {
        logger.info("Loading students");
        
        logger.info("theSearchName = " + theSearchName);
        
        try {
            
            if (theSearchName != null && theSearchName.trim().length() > 0) {
                // search for students by name
                students = studentDbUtil.searchStudents(theSearchName);                
            }
            else {
                // get all students from database
                students = studentDbUtil.getStudents();
            }
            
        } catch (Exception exc) {
            // send this to server logs
            logger.log(Level.SEVERE, "Error loading students", exc);
            
            // add error message for JSF page
            addErrorMessage(exc);
        }
        finally {
            // reset the search info
            theSearchName = null;
        }
    }

NOTE: You may have syntax errors on the studentDbUtil, but we'll resolve that in the next section.

This code checks the "theSearchName" field. If the field is not empty, then it will search for students based on "theSearchName". If the field is empty, then we'll get all students from the datbabase.

Finally, at the end of this call, we reset the search info to null. This clears everything out in preparation for the next call.

---

3. Add method in the StudentDbUtil to perfom search

Now, we'll add methods in the StudentDbUtil to search for a student by first name or last name

a. Edit the file: StudentDbUtil.java

b. Add the method:

    public List<Student> searchStudents(String theSearchName)  throws Exception {
        List<Student> students = new ArrayList<>();
        
        Connection myConn = null;
        PreparedStatement myStmt = null;
        ResultSet myRs = null;
        int studentId;
        
        try {
            
            // get connection to database
            myConn = dataSource.getConnection();
            
            //
            // only search by name if theSearchName is not empty
            //
            if (theSearchName != null && theSearchName.trim().length() > 0) {
                // create sql to search for students by name
                String sql = "select * from student where lower(first_name) like ? or lower(last_name) like ?";
                // create prepared statement
                myStmt = myConn.prepareStatement(sql);
                // set params
                String theSearchNameLike = "%" + theSearchName.toLowerCase() + "%";
                myStmt.setString(1, theSearchNameLike);
                myStmt.setString(2, theSearchNameLike);
                
            } else {
                // create sql to get all students
                String sql = "select * from student order by last_name";
                // create prepared statement
                myStmt = myConn.prepareStatement(sql);
            }
            
            // execute statement
            myRs = myStmt.executeQuery();
            
            // retrieve data from result set row
            while (myRs.next()) {
                
                // retrieve data from result set row
                int id = myRs.getInt("id");
                String firstName = myRs.getString("first_name");
                String lastName = myRs.getString("last_name");
                String email = myRs.getString("email");
                
                // create new student object
                Student tempStudent = new Student(id, firstName, lastName, email);
                
                // add it to the list of students
                students.add(tempStudent);            
            }
            
            return students;
        }
        finally {
            // clean up JDBC objects
            close(myConn, myStmt, myRs);
        }
    }

In this method, we need to check "theSearchName", this is the user input. We need to make sure it is not empty. If it is not empty then we will use it in the search query.  If it is empty, then we'll just ignore it and simply return all of the students.

For the condition when "theSearchName" is not empty, then we use it to compare against the first name or last name. We also make use of the "like" clause and the "%" wildcard characters. This will allow us to search for substrings. For example, if we have students with last name of "Patel", "Patterson" ... then we can search for "Pat" and it will match on those names.  

Also, notice the query uses the lower case version of the values to make a case insensitive search. If you'd like to make a case sensitive search, then simply remove the lower references.

You can read more on the SQL "like" clause here:
https://www.w3schools.com/SQl/sql_like.asp

---

4. Test the app

Once you've made all of the updates then you can test your application.

The app will now have the search form at the top. You can enter a name to search and the app will give you the desired results.

Congrats!