JsfCrudGenerator61Jukebox

Jukebox Exercise

The following is a brief exercise in which you generate and customize a JavaServer Faces application for a simple database. The steps below are for NetBeans 6.1. You can also simply download the attached Jukebox61_JsfCrudGenerator61Jukebox.zip, which contains the completed Jukebox project and SQL.

Creating the Database

  1. In the Services window, right-click on the MySQL Server at localhost:3306 node and select Create Database.
  2. In the Create MySQL Database dialog, enter Jukebox for the Database Name. Also, grant full access to an existing user on your system. Click OK.
  3. In the New Database Connection dialog, make sure all fields are completed, including the Password field, and click OK. Click OK when prompted in the Advanced tab.
  4. In the Services window, expand the jdbc:mysql://localhost:3306/jukebox node, right-click on the Tables node, and select Execute Command.
  5. In the editor, paste the following SQL and click the Run SQL toolbar button.
CREATE TABLE genre ( id INT, description VARCHAR(20), PRIMARY KEY (id) )ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE music ( id INT, title VARCHAR(72), artist VARCHAR(72), year INT NOT NULL, genre INT NOT NULL, PRIMARY KEY (id), KEY idx_music_fk (genre), CONSTRAINT `music_fk` FOREIGN KEY (genre) REFERENCES genre (id) )ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO genre VALUES (1, 'Rock'); INSERT INTO genre VALUES (2, 'Pop'); INSERT INTO genre VALUES (3, 'Classical'); INSERT INTO genre VALUES (4, 'Folk'); INSERT INTO genre VALUES (5, 'Jazz'); INSERT INTO music VALUES (1, 'Money for Nothing', 'Dire Straits', 1984, 2); INSERT INTO music VALUES (2, 'Hey, Joe', 'Jimi Hendrix', 1966, 1); INSERT INTO music VALUES (3, 'Like a Virgin', 'Madonna', 1984, 2); INSERT INTO music VALUES (4, 'Yesterday', 'Beatles', 1965, 2); INSERT INTO music VALUES (5, 'Country Roads', 'John Denver', 1971, 4); INSERT INTO music VALUES (6, 'Toccata and Fugue', 'Johan Sebastian Bach', 1703, 3);
  1. In the services window, right-click the Tables node and select Refresh to confirm that the music and genre tables have been created.

Creating the Project

  1. From the main menu, choose File > New Project.
  2. In the New Project wizard, select Web from the Categories list, select Web Application from the Projects list, and click Next.
  3. Name the project Jukebox, choose a location for the project, and click Next.
  4. Select Glassfish V2 for the Server, Java EE 5 for the Java EE Version, and click Next.
  5. Select the JavaServer Faces checkbox in the Frameworks panel. Click Finish. Note: When selecting the framework, be sure to select the JavaServer Faces framework, not Visual Web JavaServer Faces.

Generating the Entity classes

  1. In the Projects window, right-click the Jukebox node, and choose New > Entity Classes from Database.
  2. Select New Data Source from the Data Source drop-down list to open the Create Data Source dialog.
  3. Type jdbc/jukebox as the JNDI Name and select jdbc:derby://localhost:1527/jukebox as the Database Connection. Click OK to close the dialog box and return to the wizard.
  4. Click Add All in the wizard. Click Next.
  5. Type jpa.entities as the Package.
  6. Click Create Persistence Unit to open the Create Persistence Unit dialog box. You can keep the default values for the persistence unit. Click Create in the dialog box to create the persistence unit and return to the wizard.
  7. Click Finish


The IDE creates the Genre and Music entity classes in the jpa.entities package.

Generating a JavaServer Faces Application from the Entity Classes

  1. Right-click the project node in the Projects window and choose New > JSF Pages from Entity Classes to open the New JSF Pages from Entity Classes wizard.
  2. Click Add All to move the entity classes to the Selected Entity Classes pane of the wizard. Click Next.
  3. Type pages for the JSF Pages Folder and jsf for the Package. Click Finish.


The IDE creates the GenreController, GenreConverter, MusicController, and MusicConverter classes in the jsf package. Beneath the Web Pages node, the IDE creates a pages folder containing the genre and music folders, each of which contains four pages: Detail.jsp, Edit.jsp, List.jsp, and New.jsp.

You can run the application to see its Create, Read, Update, and Delete functionality. Simply click Run Main Project in the main toolbar. Your default web browser opens to the local address http://localhost:8080/Jukebox. For example, you can create, edit, and then destroy a genre or music item.

In the following sections, you customize the application by adding search functionality and refining the user interface.

Implementing toString in the Entity Classes

  1. In the toString method of the Genre class, change the return statement to the following:

return (description != null && description.length() > 0) ? description : "Genre " + id;


  1. In the toString method of the Music class, change the return statement to the following:

return (title != null && title.length() > 0) ? title : "Song " + id;

Creating the Genre Search.jsp

In the following steps, you create a search criteria page for the Genre entity based on the entity's New.jsp.

  1. In the Projects window, expand the Web Pages > pages > genre node.
  2. Right-click the New.jsp node and select Copy. Right-click the genre node and select Paste. The IDE creates a page called New_1.jsp.
  3. Right-click the New_1.jsp node and select Rename.
  4. In the Rename dialog, type Search and click OK.
  5. Double-click the Search.jsp node to edit the file.
  6. Change <title>New Genre</title> to <title>Search Genre Items</title>.
  7. Change

    New Genre

    to

    Search Genre Items

    .
  8. Remove <h:inputHidden id="validateCreateField" validator="#{genre.validateCreate}" value="value"/>.
  9. Change <h:inputText id="id" value="#{genre.genre.id}" title="Id" required="true" requiredMessage="The id field is required." /> to <h:inputText id="id" value="#{genre.genre.id}" title="Id" />.
  10. Remove the following:
<h:outputText value="MusicCollection:"/> <h:selectManyListbox id="musicCollection" value="#{genre.musicCollectionOfGenre}" title="MusicCollection" size="6" > <f:selectItems value="#{music.musicsAvailableSelectMany}"/> </h:selectManyListbox>
  1. Change <h:commandLink action="#{genre.create}" value="Create"/> to <h:commandLink action="#{genre.search}" value="Search"/>.
  2. Remove the following:
<h:commandLink action="#{genre.listSetup}" value="Show All Genre Items" immediate="true"/> <br />

Creating the Music Search.jsp

In the following steps, you create a search criteria page for the Music entity based on the entity's New.jsp.

  1. In the Projects window, expand the Web Pages > pages > music node.
  2. Right-click the New.jsp node and select Copy. Right-click the music node and select Paste. The IDE creates a page called New_1.jsp.
  3. Right-click the New_1.jsp node and select Rename.
  4. In the Rename dialog, type Search and click OK.
  5. Double-click the Search.jsp node to edit the file.
  6. Change <title>New Music</title> to <title>Search Music Items</title>.
  7. Change

    New Music

    to

    Search Music Items

    .
  8. Remove <h:inputHidden id="validateCreateField" validator="#{music.validateCreate}" value="value"/>.
  9. Remove the following:
<h:outputText value="Id:"/> <h:inputText id="id" value="#{music.music.id}" title="Id" required="true" requiredMessage="The id field is required." />
  1. Change <h:inputText id="year" value="#{music.music.year}" title="Year" required="true" requiredMessage="The year field is required." /> to <h:inputText id="year" value="#{music.music.year}" title="Year" />.
  2. Change <h:commandLink action="#{music.create}" value="Create"/> to <h:commandLink action="#{music.search}" value="Search"/>.
  3. Remove the following:
<h:commandLink action="#{music.listSetup}" value="Show All Music Items" immediate="true"/> <br />

Editing the Genre Detail.jsp, Edit.jsp, and New.jsp

  1. In genre > Detail.jsp, change <h:commandLink action="#{genre.listSetup}" value="Show All Genre Items"/> to <h:commandLink action="#{genre.searchSetup}" value="Search Genre Items"/>.
  2. In both genre > Edit.jsp and genre > New.jsp, change <h:commandLink action="#{genre.listSetup}" value="Show All Genre Items" immediate="true"/> to <h:commandLink action="#{genre.searchSetup}" value="Search Genre Items" immediate="true"/>.

Editing the Genre List.jsp

In genre > List.jsp, make the following changes.

  1. Change <title>Listing Genre Items</title> to <title>Genre Results</title>.
  2. Change

    Listing Genre Items

    to

    Genre Results

    .
  3. After </h:panelGroup>, add the following:
<br /> <h:commandLink action="#{genre.searchSetup}" value="Modify Criteria"/>
  1. Before <a href="/Jukebox/faces/welcomeJSF.jsp">Index</a>, add
    .

Editing the Music Detail.jsp, Edit.jsp, and New.jsp

  1. In music > Detail.jsp, change <h:commandLink action="#{music.listSetup}" value="Show All Music Items"/> to <h:commandLink action="#{music.searchSetup}" value="Search Music Items"/>.
  2. In both music > Edit.jsp and genre > New.jsp, change <h:commandLink action="#{music.listSetup}" value="Show All Music Items" immediate="true"/> to <h:commandLink action="#{music.searchSetup}" value="Search Music Items" immediate="true"/>.

Editing the Music List.jsp

In music > List.jsp, make the following changes.

  1. Change <title>Listing Music Items</title> to <title>Music Results</title>.
  2. Change

    Listing Music Items

    to

    Music Results

    .
  3. After </h:panelGroup>, add the following:
<br /> <h:commandLink action="#{music.searchSetup}" value="Modify Criteria"/>
  1. Before <a href="/Jukebox/faces/welcomeJSF.jsp">Index</a>, add
    .

Editing welcomeJSF.jsp

In Web Pages > welcomeJSF.jsp, make the following changes.

  1. Change <title>JSP Page</title> to <title>Jukebox Application</title>.
  2. Change

    <h:outputText value="JavaServer Faces" />

    to

    <h:outputText value="Jukebox Application" />

    .
  3. Change <h:commandLink action="#{music.listSetup}" value="Show All Music Items"/> to <h:commandLink action="#{music.searchSetup}" value="Search Music Items"/>.
  4. Change <h:commandLink action="#{genre.listSetup}" value="Show All Genre Items"/> to <h:commandLink action="#{genre.searchSetup}" value="Search Genre Items"/>.

Editing faces-config.xml

  1. In the Projects window, expand the Configuration Files node.
  2. Double-click the faces-config.xml node.
  3. Click the XML tab to edit the raw XML source.
  4. After the navigation rule for the genre_detail outcome, add the following:
<navigation-rule> <navigation-case> <from-outcome>genre_search</from-outcome> <to-view-id>/pages/genre/Search.jsp</to-view-id> </navigation-case> </navigation-rule>
  1. After the navigation rule for the music_detail outcome, add the following:
   <navigation-rule>
       <navigation-case>
           <from-outcome>music_search</from-outcome>
           <to-view-id>/pages/music/Search.jsp</to-view-id>
       </navigation-case>
   </navigation-rule>

Editing GenreController.java

  1. In the Projects window, expand the Source Packages > jsf node.
  2. Double-click the GenreController.java node to edit the file.
  3. Add the following member field:
private Map<String,Object> searchParameters = null;
  1. Change the first line of the getGenresAvailable(boolean) method to the following:

List<Genre> allGenres = getGenres(true, null);


  1. Add the searchSetup() and search() methods as follows:
  public String searchSetup() {
       reset(false);
       genre = new Genre();
       return "genre_search";
   }
   public String search() {
       searchParameters = new HashMap<String,Object>();
       Integer id = genre.getId();
       if (id != null) {
           searchParameters.put("id", id);
       }
       String description = genre.getDescription();
       if (description != null && description.trim().length() > 0) {
           searchParameters.put("description", description);
       }
       reset(true, false);
       return "genre_list";
   }

  1. Change the getGenres() and getGenres(boolean) methods to the following:
   public List<Genre> getGenres() {
       if (genres == null) {
           genres = getGenres(false, searchParameters);
       }
       return genres;
   }
   
   private List<Genre> getGenres(boolean all, Map<String,Object> searchParametersToUse) {
       EntityManager em = getEntityManager();
       try {
           String query = getQueryForParameters("select object(o) from Genre as o", searchParametersToUse);
           Query q = em.createQuery(query);
           if (searchParametersToUse != null) {
               for (String name : searchParametersToUse.keySet()) {
                   q.setParameter(name, searchParametersToUse.get(name));
               }
           }
           if (!all) {
               q.setMaxResults(batchSize);
               q.setFirstResult(getFirstItem());
           }
           return q.getResultList();
       } finally {
           em.close();
       }
   }

  1. Change the getItemCount() method to the following:
   public int getItemCount() {
       if (itemCount == -1) {
           EntityManager em = getEntityManager();
           try {
               String query = getQueryForParameters("select count(o) from Genre as o", searchParameters);
               Query q = em.createQuery(query);
               if (searchParameters != null) {
                   for (String name : searchParameters.keySet()) {
                       q.setParameter(name, searchParameters.get(name));
                   }
               }
               itemCount = ((Long) q.getSingleResult()).intValue();
           } finally {
               em.close();
           }
       }
       return itemCount;
   }

  1. Change the first line of next() method to the following:

reset(false, false);


  1. Change the first line of the prev() method to the following:

reset(false, false);


  1. Replace the reset(boolean) method with the following:
   private void reset(boolean resetFirstItem) {
       reset(resetFirstItem, true);
   }
   private void reset(boolean resetFirstItem, boolean resetSearchParameters) {
       genre = null;
       genres = null;
       itemCount = -1;
       if (resetFirstItem) {
           firstItem = 0;
       }
       if (resetSearchParameters) {
           searchParameters = null;
       }
   }

  1. Add the following method:
   private String getQueryForParameters(String baseQuery, Map<String,Object> searchParametersToUse) {
       if (searchParametersToUse == null) {
           return baseQuery;
       }
       StringBuffer where = new StringBuffer();
       if (searchParametersToUse.containsKey("id")) {
           where.append("o.id = :id");
       }
       if (searchParametersToUse.containsKey("description")) {
           if (where.length() > 0) {
               where.append(" and ");
           }
           where.append("o.description = :description");
       }
       if (where.length() > 0) {
           baseQuery += " where " + where;
       }
       return baseQuery;
   }

  1. Right-click and select Fix Imports. Click Save All on the main toolbar.

Editing MusicController.java

  1. In the Projects window, double-click the Source Packages > jsf > MusicController.java node to edit the file.
  2. Add the following member field:
private Map<String,Object> searchParameters = null;
  1. Change the first line of the getMusicsAvailable(boolean) method to the following:

List<Music> allMusics = getMusics(true, null);


  1. Add the searchSetup() and search() methods as follows:
   public String searchSetup() {
       reset(false);
       music = new Music();
       return "music_search";
   }
   public String search() {
       searchParameters = new HashMap<String,Object>();
       Integer id = music.getId();
       if (id != null) {
           searchParameters.put("id", id);
       }
       String title = music.getTitle();
       if (title != null && title.trim().length() > 0) {
           searchParameters.put("title", title);
       }
       String artist = music.getArtist();
       if (artist != null && artist.trim().length() > 0) {
           searchParameters.put("artist", artist);
       }
       int year = music.getYear();
       if (year > 0) {
           searchParameters.put("year", new Integer(year));
       }
       Genre genre = music.getGenre();
       if (genre != null) {
           searchParameters.put("genre", genre);
       }
       reset(true, false);
       return "music_list";
   }

  1. Change the getMusics() and getMusics(boolean) methods to the following:
   public List<Music> getMusics() {
       if (musics == null) {
           musics = getMusics(false, searchParameters);
       }
       return musics;
   }
   public List<Music> getMusics(boolean all, Map<String,Object> searchParametersToUse) {
       EntityManager em = getEntityManager();
       try {
           String query = getQueryForParameters("select object(o) from Music as o", searchParametersToUse);
           Query q = em.createQuery(query);
           if (searchParametersToUse != null) {
               for (String name : searchParametersToUse.keySet()) {
                   q.setParameter(name, searchParametersToUse.get(name));
               }
           }
           if (!all) {
               q.setMaxResults(batchSize);
               q.setFirstResult(getFirstItem());
           }
           return q.getResultList();
       } finally {
           em.close();
       }
   }

  1. Change the getItemCount() method to the following:
   public int getItemCount() {
       if (itemCount == -1) {
           EntityManager em = getEntityManager();
           try {
               String query = getQueryForParameters("select count(o) from Music as o", searchParameters);
               Query q = em.createQuery(query);
               if (searchParameters != null) {
                   for (String name : searchParameters.keySet()) {
                       q.setParameter(name, searchParameters.get(name));
                   }
               }
               itemCount = ((Long) q.getSingleResult()).intValue();
           } finally {
               em.close();
           }
       }
       return itemCount;
   }

  1. Change the first line of next() method to the following:

reset(false, false);


  1. Change the first line of the prev() method to the following:

reset(false, false);


  1. Replace the reset(boolean) method with the following:
   private void reset(boolean resetFirstItem) {
       reset(resetFirstItem, true);
   }
   private void reset(boolean resetFirstItem, boolean resetSearchParameters) {
       music = null;
       musics = null;
       itemCount = -1;
       if (resetFirstItem) {
           firstItem = 0;
       }
       if (resetSearchParameters) {
           searchParameters = null;
       }
   }

  1. Add the following method:
   private String getQueryForParameters(String baseQuery, Map<String,Object> searchParametersToUse) {
       if (searchParametersToUse == null) {
           return baseQuery;
       }
       StringBuffer where = new StringBuffer();
       if (searchParametersToUse.containsKey("id")) {
           where.append("o.id = :id");
       }
       if (searchParametersToUse.containsKey("title")) {
           if (where.length() > 0) {
               where.append(" and ");
           }
           where.append("o.title = :title");
       }
       if (searchParametersToUse.containsKey("artist")) {
           if (where.length() > 0) {
               where.append(" and ");
           }
           where.append("o.artist = :artist");
       }
       if (searchParametersToUse.containsKey("year")) {
           if (where.length() > 0) {
               where.append(" and ");
           }
           where.append("o.year = :year");
       }
       if (searchParametersToUse.containsKey("genre")) {


           if (where.length() > 0) {
               where.append(" and ");
           }
           where.append("o.genre = :genre");
       }
       if (where.length() > 0) {
           baseQuery += " where " + where;
       }
       return baseQuery;
   }

  1. Right-click and select Fix Imports. Click Save All on the main toolbar.

Deploying the Application

Click Run Main Project in the main toolbar. The IDE saves all changed files, rebuilds the application, and deploys the application to the server. Your default web browser opens to the local address http://localhost:8080/Jukebox/.

Experiment with searching music and genre items as well as creating, editing, and destroying them.

Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo