Generating a JavaServer Faces CRUD Application from a Database
In this tutorial, you use the NetBeans IDE to generate and deploy a web application
that displays data from a database.
The tutorial demonstrates how to generate a web application with CRUD (Create, Read, Update, Delete)
functionality that uses the Java Persistence API (JPA) to manage the database transaction.
In the tutorial you first create entity classes based on tables in a database and then
create JavaServer Faces (JSF) pages from the entity classes using the JSF Pages from Entity Classes wizard.
The JSF Pages from Entity Classes wizard enables you to quickly and easily
generate JSF pages for working with a database based on the entity classes in your project.
The wizard also gives you the option to enable Ajax functionality in the generated JSF pages.
The code generated by the wizard has the following features:
The code is easy to maintain and customize
Handles all relationship types, generated and non-generated IDs,
and embedded IDs, including embedded ID fields that correspond to foreign key columns
Embedded ID fields are shown as read-only where appropriate
Includes required checks to prevent non-nullable column violations and
orphan checks to prevent non-nullable column violations in related entities
(by leveraging nullable or optional annotation elements in the entity classes)
Includes checks to verify that the current entity is correct
in order to prevent errors if a user deviates from the normal page flow
(for example, when working in multiple browser tabs)
Forgoes per-property code in certain files in case you later need to modify your database schema
Fields can easily be removed from the generated JSPs to simplify customization
Graceful handling of situations when a user attempts to operate on an entity that has been deleted by another user
or attempts to create an entity that already exists
Pages can be styled easily
In addition to generating JSF pages for you,
the JSF Pages from Entity Classes wizard incorporates the functionality of the
JPA Controller Classes from Entity Classes wizard.
If you want to create JPA controller classes for entity classes but do not want JSF pages
generated for you, you can use the JPA Controller Classes from Entity Classes wizard
rather than the JSF Pages from Entity Classes wizard.
Note. For the solution project to this tutorial (using the MySQL database), download ConsultingAgency.zip.
Note. The GlassFish application server is included in the NetBeans download.
Creating the Database
This tutorial uses a consulting agency database called consult.
The database is not included when you install the IDE so you need to
first create the database to follow this tutorial.
The consult database was designed to demonstrate the scope of IDE support for handling a variety of database structures.
The database is thus not intended as an example of recommended database design or best-practice.
Instead, it attempts to incorporate many of the relevant features that are potentially found in a database design.
For example, the consult database contains all possible relationship types, composite primary keys,
and many different data types. See the tables below for a more detailed overview of the database structure.
Note.
If you created a Java DB version of the consult database using an older script, you should run the
derby_drop_consult_v1.sql script to drop the tables before creating the database again.
Note. This tutorial uses the JavaDB database server but you can also complete the
tutorial using the MySQL database server.
To create the database in MySQL, download and extract the
mysql-consult.zip archive.
The archive contains SQL scripts for creating and populating the consult database.
For more information on configuring the IDE to work with MySQL, see the
Connecting to a MySQL Database tutorial.
Download derby-consult.zip and extract the archive to your local system.
When you extract the archive you will see the SQL scripts for creating and populating the database.
The archive also has scripts for dropping tables.
In the Services window, expand the Databases node, right-click the JavaDB node and choose Start Server.
Right-click the Java DB node and choose Create Database.
Type consult as the Database Name, User Name, and Password in the Create Java DB dialog. Click OK.
A new node appears under the Databases node (jdbc:derby://localhost:1527/consult [consult on CONSULT]).
Right-click the new node and choose Connect.
Choose File > Open File from the main menu and navigate to the extracted file derby_create_consult_v2.sql. Click Open.
The file automatically opens in the the SQL editor.
Make sure that the consult database is selected in the Connection drop-down list in the SQL editor toolbar
and click the Run SQL button.
When you click Run SQL, the following output appears in the Output window.
Note. If at any time you want to clear the database, you can drop the consult schema and tables
by running the derby_drop_consult_v2.sql script included in the archive.
Viewing the Database Structure
To see the if the tables were created correctly, expand the Tables node under the database connection node.
You can expand a table node to see the table columns, indexes and any foreign keys.
You can right-click a column and choose Properties to view additional information about the column.
Note. If you do not see any tables under the Tables node, right-click the Tables node and choose Refresh.
If you look at the structure of the consult database you can see that the database
contains tables that have a variety of relationships and various field types.
When creating entity classes from a database, the IDE automatically generates the appropriate code for the
various field types.
The following table describes the tables found in the consult database.
Database Table
Description
Design Features
CLIENT
A client of the consulting agency
Non-generated, composite primary key (whose fields do not constitute a foreign key)
CONSULTANT
An employee of the consulting agency whom clients can hire on a contract basis
Includes a resume field of type LONG VARCHAR
CONSULTANT_STATUS
A consultant's status with the consulting agency (for example, Active and Inactive are possible statuses)
Non-generated primary key of type CHAR
RECRUITER
An employee of the consulting agency responsible for connecting clients and consultants
PROJECT
A project that a client staffs with consultants of the consulting agency
Non-generated, composite primary key that includes two fields constituting a foreign key to the CLIENT table
BILLABLE
A set of hours worked by a consultant on a project, for which the consulting agency bills the relevant client
Includes an artifact field of type CLOB
ADDRESS
A client's billing address
PROJECT_CONSULTANT
Join table indicating which consultants are currently assigned to which projects
Cross-references PROJECT and CONSULTANT, the former having a composite primary key
The consult database includes a variety of relationships.
When creating entity classes from a database, the IDE automatically generates the properties of the appropriate Java type
based on the SQL type of the columns.
The following table describes the entity relationships for the consult database.
(The inverse relationships are not shown.)
Entity
Related Entity
Relationship Information
Description
CLIENT
RECRUITER
nullable one-to-one with manual editing; nullable one-to-many if not edited
CLIENT has many RECRUITERs and RECRUITER has zero or one CLIENT (if not manually edited)
CLIENT
ADDRESS
non-nullable one-to-one
CLIENT has one ADDRESS and ADDRESS has zero or one CLIENT
CLIENT
PROJECT
non-nullable one-to-many; in a Project entity, the value of the client field is part of the Project's primary key
CLIENT has many PROJECTs and PROJECT has one CLIENT
CONSULTANT
PROJECT
many-to-many
CONSULTANT has many PROJECTs and PROJECT has many CONSULTANTs
CONSULTANT
BILLABLE
non-nullable one-to-many
CONSULTANT has many BILLABLEs and BILLABLE has one CONSULTANT
CONSULTANT_STATUS
CONSULTANT
non-nullable one-to-many
CONSULTANT_STATUS has many CONSULTANTs and CONSULTANT has one CONSULTANT_STATUS
CONSULTANT
RECRUITER
nullable one-to-many
CONSULTANT has zero or one RECRUITER and RECRUITER has many CONSULTANTs
BILLABLE
PROJECT
non-nullable one-to-many
BILLABLE has one PROJECT and PROJECT has many BILLABLEs
Now that the database is created, you can create the web application and use the Entity Classes from Database wizard to
generate entity classes based on the database tables.
Creating the Web Application Project
In this exercise you create a web project and add the JavaServer Faces framework to the project.
When you create the project, you will select JavaServer Faces in the Frameworks panel of the New Project wizard.
Choose File > New Project (Ctrl-Shift-N).
Select Web Application from the Java Web category. Click Next.
Type ConsultingAgency for the project name and set the project location.
Deselect the Use Dedicated Folder option, if selected.
For this tutorial there is little reason to copy project libraries to a dedicated folder because
you will not need to share libraries with other users.
Click Next.
Set the server to GlassFish and set the Java EE Version to Java EE 5. Click Next.
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.
When you click Finish, the IDE creates the web application project and opens welcomeJSF.jsp in the editor.
You can close welcomeJSF.jsp because you will not need to edit this file.
Generating the Entity Classes from the Database
After you create the database and the database connection is registered with the IDE, you can use the
Entity Classes from Database wizard to quickly generate entity classes based on the tables in the database.
The IDE can generate entity classes for each table that you select, and can also generate any necessary
entity classes for related tables.
In the Projects window, right-click the ConsultingAgency node, and choose New > Entity Classes from Database.
Select New Data Source from the Data Source drop-down list to open the Create Data Source dialog.
Type jdbc/consult as the JNDI Name and select jdbc:derby://localhost:1527/consult [consult on CONSULT]
as the Database Connection. Click OK to close the dialog box and return to the wizard.
The tables in the consult database appear in the Available Tables listbox.
Click Add All in the wizard. Click Next.
Type jpa.entities as the Package.
Make sure that the checkbox to generate named queries is selected.
Click Create Persistence Unit to open the Create Persistence Unit dialog box.
Click Create in the dialog box to create the persistence unit and return to the wizard.
Note. You can keep the default values for the persistence unit.
Click Next.
Keep the default values in the Mapping Options page of the wizard. Click Finish.
You can use the Mapping Options page of the wizard if you want to further customize
the annotations or collection type in the generated entities.
For this tutorial the default values are sufficient.
When using the wizard to create entity classes from a database, the IDE examines the relationships between the tables.
In the Projects window, if you expand the jpa.entities Source Package node
you can see that the IDE generated an entity class for each table except for
the PROJECT_CONSULTANT table.
The IDE did not create an entity class for PROJECT_CONSULTANT because the table is a join table.
The IDE also generated two additional classes for the tables with composite primary keys: CLIENT and PROJECT.
The primary key classes for these tables (ClientPK.java and ProjectPK.java) have PK appended to the name.
If you look at the generated code for the entity classes you can see that the wizard added
@GeneratedValue annotations to the auto-generated ID fields and @Basic(optional = "false") annotations to some of the fields in the entity classes.
Based on the @Basic(optional = "false") annotations, the JSF Pages from Entity Classes wizard can generate code that
includes checks to prevent non-nullable column violations for those fields.
Editing the Entity Classes
If desired, you can now edit the generated entity classes.
In this exercise you will modify the implementations of the toString method in the entity classes.
In the Client and Recruiter classes you will also modify the annotations to change the relationship between clients and recruiters
from one-to-many to one-to-one.
Because a nullable one-to-many relationship already exists between recruiters and consultants,
for demonstration purposes in this tutorial you will establish a nullable one-to-one relationship
between clients and recruiters.
Note. This section of the tutorial is optional and you do not need to
make any changes to the entity classes before you generate the JSF pages with the JSF Pages from Entity Classes wizard.
Editing Address.java
Open the Address entity class and make the following changes.
Modify the return statement of the toString method to return the full address:
return line1 + ", " + line2 + ", " + city + ", " + region + ", " + country + ", " + postalCode;
You can use the IDE's code completion to help you add the fields.
Fix your imports, if necessary, and save your changes.
Editing Billable.java
Open the Billable entity class and make the following changes.
Modify the return statement of the toString method to return the description, consultant id and project:
Fix your imports, if necessary, and save your changes.
Editing Client.java
Modify the @OneToMany annotation on the recruiterCollection field to
make the relationship one-to-one and change the field from a Collection to Recruiter recruiter.
Modify the getters and setters for Collection<Recruiter> recruiterCollection
according to the changes in the name of the field. The new getter and setter will look like the following:
public Recruiter getRecruiter() {
return recruiter;
}
public void setRecruiter(Recruiter recruiter) {
this.recruiter = recruiter;
}
It might be simpler to delete the getter and setter for Collection<Recruiter> recruiterCollection
and then generate a new getter and setter for Recruiter recruiter using the Insert Code dialog.
To create a new getter and setter, right-click in the source code and choose Insert Code (Alt-Insert)
and then select Getter and Setter.
Select recruiter in the Generate Getter and Setter dialog box and click Generate.
Modify the return statement of the toString method to return String.valueOf(clientPK).
public String toString() {
return String.valueOf(clientPK);
}
Fix your imports, if necessary, and save your changes.
Editing ClientPK.java
Modify the return statement of the toString method to return the client name and department number.
Fix your imports, if necessary, and save your changes.
Editing Recruiter.java
Modify the @ManyToOne annotation on the client field to
mark the relationship as one-to-one.
@OneToOne
private Client client;
Modify the return statement of the toString method to return the email.
public String toString() {
return email;
}
Fix your imports, if necessary, and save your changes.
Generating JSF Pages From Entity Classes
Now that the entity classes are created, you can create the web interface for displaying and modifying the data.
You will use the JSF Pages from Entity Classes wizard to generate JavaServer Faces pages.
The code generated by the wizard includes checks based on the annotations in the entity classes.
The wizard also gives you the option to enable Ajax functionality in the application by extending
the JavaServer Faces technology with Dynamic Faces technology.
For each entity class the wizard generates the following:
a JPA controller class
a JSF controller class
a JSF converter class
a directory containing four JSP files (Detail.jsp, Edit.jsp, List.jsp, New.jsp)
managed bean elements, converter elements and navigation rules for the entity in faces-config.xml
The wizard also generates the following classes used by the controller classes:
exception classes used by the JPA controllers
utility classes used by the JSF controllers
To generate the JSF pages:
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.
The Available Entity Classes box lists the seven entity classes in the project.
The box does not list the embeddable classes (ClientPK.java and ProjectPK.java).
Click Add All to move all the classes to the Selected Entity Classes box. Click Next.
Type jpa.controllers for the JPA Controller Package.
Type jsf for the JSF Classes Package.
Select Ajax-enable generated pages.
Click Finish.
When you click Finish, the IDE creates the JPA controller classes in the jpa.controllers package
and the JSF converter and JSF controller classes in the jsf package.
Each JPA controller class handles the operations for the corresponding entity class, including creating, editing, and destroying instances of the entity class via the Java Persistence API.
Each JSF converter class implements the javax.faces.convert.Converter interface defined by JavaServer Faces and performs the work of converting instances of the corresponding entity class to String objects and vice versa.
Each JSF controller class is specific to the corresponding generated JSP and includes code that invokes methods in the appropriate JPA controller class and demonstrates which exceptions to catch.
Note. In general, when modifying your application you will want to modify the controller logic in the JSF controller classes and use the generated code as an example.
If you expand the Web Pages node, you can see that the IDE generated a folder for each of the entity classes.
Each folder contains the files Detail.jsp, Edit.jsp, List.jsp and New.jsp.
The IDE also modified welcomeJSF.jsp by inserting links to each of the List.jsp pages.
If you expand the Source Packages node you can see the controller, converter, exception, and utility classes that the wizard generated.
If you expand the Configuration Files node and open faces-config.xml in the XML editor,
you can see that the IDE inserted the managed-bean and converter elements for each of the controller and converter classes.
The IDE also inserted a navigation-rule element for each JSP, indicating the logical outcome that causes the application to
navigate to that JSP.
Enabling Ajax in the Application
The final pane of the JSF Pages from Entity Classes wizard gives you the option to
select Ajax-enable generated pages to enable Ajax functionality in the application
through the Dynamic Faces extension to the JSF framework.
The wizard adds the required JSF Extensions libraries to the project and configures the application's deployment descriptor
to enable the Ajax lifecycle.
For more about Dynamic Faces JSF Extensions see the JavaServer Faces Technology Extensions site.
If you select the option the wizard performs the following actions.
Adds JSF Extensions libraries to the project
(jsf-extensions-common, jsf-extensions-dynamic-faces, commons-logging, and shale-remoting)
that are required for using Dynamic Faces technology in the project.
Modifies web.xml to configure FacesServlet to use the Ajax lifecycle by adding
an entry for the javax.faces.LIFECYCLE_ID initialization parameter
and setting the value to com.sun.faces.lifecycle.PARTIAL.
Generates the JSP fragment file AjaxScripts.jspf in the WEB-INF/jspf directory.
AjaxScripts.jspf renders script tags for JavaScript files contained in the Dynamic Faces libraries.
The application contains a JavaScript file jsfcrud.js in the Web Pages directory.
The jsfcrud.js file checks if Dynamic Faces is enabled by checking if the script tags for the Dynamic Faces JavaScript files were rendered.
If Dynamic Faces is enabled then the form is configured to send Ajax requests.
After enabling Ajax in the application with Dynamic Faces extensions, you can modify the application to
add further functionality provided by Dynamic Faces extensions.
Note. If you want to disable Ajax in the application later,
you can comment out the contents of AjaxScripts.jspf
by adding <%-- to the beginning of the file and --%> to the end of the file.
Generating JPA Controller Classes From Entity Classes
In the generated web application the JPA controller methods are accessed by methods in the JSF controller class.
When you use the JSF Pages from Entity Classes wizard the IDE automatically generates JPA controller classes for each of
the selected entities.
But the use of JPA controller classes is not restricted to JSF web applications.
You can use JPA controller classes in other applications that use the Java Persistence API
(for example, in desktop applications) to work with entity classes and manage entity persistence.
The JPA Controller Classes from Entity Classes wizard enables you to easily
create JPA controller classes in projects.
To create JPA controller classes, open the New File wizard and choose JPA Controller Classes from Entity Classes
in the Persistence category.
In the wizard you specify the entity classes for which you want the JPA controller classes and then
specify where you want the IDE to create the files.
The wizard also automatically creates exception classes used by the JPA controller classes.
If you update your database schema you can run the Entity Classes from Database and JPA Controllers from
Entity Classes wizards again to regenerate the classes.
If desired, after you create the JPA controller classes, you can run the JSF Pages from Entity Classes wizard and specify
the package of the existing JPA controller classes, in which case the existing JPA controller classes will be leveraged
rather than regenerated.
Adding Data to the Database
Now that you have finished creating the application, you can deploy and run the application.
The Consulting Agency database you created is unpopulated.
You need to add data to the database either by adding data through
the web interface or by running an SQL script.
After you add the data you will see
how the relationships between the tables function.
Adding Data With an SQL Script
If you do not want to add the data through the web forms,
you can run the derby_insert_data_consult_v2.sql script included in the derby-consult.zip archive.
Open derby_insert_data_consult_v2.sql by choosing File > Open File from the main menu.
The file automatically opens in the the SQL editor.
Note. If you are using the MySQL database server, open
the mysql_insert_data_consult_v2.sql file included in the mysql-consult.zip archive.
Make sure that the consult database is selected in the Connection drop-down list in the SQL editor toolbar
and click the Run SQL button in the toolbar.
You can see the result of the script execution in the Output window.
Click Run Main Project in the main toolbar.
Your default web browser opens to the local address http://localhost:8080/ConsultingAgency/.
Adding Data With the Web Interface
You can add data to the database by launching the application in your browser and
then adding data through the web forms.
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/ConsultingAgency/.
Click Show All Address Items and click New Address.
Add the following data in the New Address form.
Field
Value
Line1
100 Data Street
Line2
Suite 432
City
San Francisco
Region
California
Country
USA
PostalCode
94103
Click Create.
Click Index to return to the index page.
Click Show All Client Items and click New Client.
Add the following data in the New Client form.
Field
Value
ClientDepartmentNumber
2000
ClientName
Big Data Corp.
ContactEmail
ContactPassword
accounting
BillingAddress
100 Data Street
Click Create and then Index to return to the index page.
Click Show All Project Items and click New Project.
Add the following data in the New Project form.
Field
Value
ProjectName
Secret Project
ContactEmail
ContactPassword
project.manager
Click Create and then Index to return to the index page.
Click Show All ConsultantStatus Items and then click New ConsultantStatus.
Add the following data in the New ConsultantStatus form.
Field
Value
StatusId
A
Description
Active
Click Create and then Index to return to the index page.
Click Show All Consultant Items and then click New Consultant.
Add the following data in the New Consultant form.
Field
Value
Email
Password
janet.smart
HourlyRate
80
BillableHourlyRate
120
ProjectCollection
Secret Project
StatusId
A, Active
Note. Make sure you select Secret Project in the list box
for ProjectCollection.
Click Create and then Index to return to the index page.
Click Show All Billable Items and then click New Billable.
Add the following data in the New Billable form.
Field
Value
StartDate
2008-10-13 00:00:00.0
EndDate
2008-10-17 00:00:00.0
Hours
40
HourlyRate
80
BillableHourlyRate
120
Description
begin gathering requirements
ConsultantId
Project
Secret Project
Click Create and then click New Billable.
Add the following data in the New Billable form.
This time you will type finish gathering requirements in the Description field.
Field
Value
StartDate
2008-10-20 00:00:00.0
EndDate
2008-10-24 00:00:00.0
Hours
40
HourlyRate
80
BillableHourlyRate
120
Description
finish gathering requirements
ConsultantId
Project
Secret Project
Click Create and return to the index page.
Click Show All Recruiter Items and click New Recruiter.
Add the following data in the New Recruiter form.
Field
Value
Email
Password
bob
ConsultantCollection
Note. Make sure you select in the list box
for ConsultantCollection. Leave the Client drop down list empty.
Click Create and then Index to return to the index page.
After adding data to the database you can navigate through the generated pages to see the relationships between
the tables.
Exploring Functionality in the Generated Code
After you populate the database you can see examples of how the code generated by the wizard is based on
the properties of the database fields.
Read-only Primary Key Fields
If a field in the database is a primary key, the wizard generates code to prevent the user from editing the field
in the generated forms.
The following examples illustrate instances where the primary key field is read-only.
If you navigate to the New Client page you can see that the ProjectCollection field is read-only.
If the application permitted an attempt to change the Client associated with an existing Project,
the operation would fail because the Client associated with a Project is part of the Project's primary key.
You can verify this in the SQL script by examining the project_pk primary key and the project_fk_client foreign key.
If you navigate to the Editing Project Page you can see that the Client field is read-only.
Again, the field is read-only because the Client associated with a Project is part of the Project's primary key.
Generated Error Checks
The generated code can check if a user action would result in an error.
For example, if a table has a column that cannot be null, the code can check if an action would
result in a non-null violation for the column and instead display an error message.
After you populate the database you can see examples of the generated checks by trying to edit the data in the forms.
You will receive an error message if you attempt to do the following actions.
Create another Project item, again specifying Secret Project as the ProjectName,
and completing the ContactEmail and Client fields.
An error message appears indicating that the item already exists.
Create another Address item, but leave all the fields blank.
Error messages appear indicating the required fields.
Edit the "" Consultant item by deselecting "finish gathering requirements"
in the BillableCollection list.
An error message appears indicating that the Billable item that you deselected must be retained
because its consultantId field cannot be null.
Destroy the "Secret Project, Big Data Corp., Dept. 2000" Project item.
An error message appears indicating that the Project item cannot be destroyed because the Project item's
associated Billable items have a project field that cannot be null.
Destroy an item that has already been destroyed by another user.
An error message appears indicating that the item no longer exists,
and the List.jsp page subsequently does not display the item.
Note. You can do this if you use two different browsers (e.g., Firefox and Internet Explorer)
and navigate to the same page (e.g., the Listing Billable Items page) in each browser.
Destroy one of the Billable items in one of the browsers and then try to destroy the same item in the other browser.