JsfCrudGeneratorConsultingAgency

JSF CRUD Generator Features

You can also find a version of this tutorial on netbeans.org at Generating a JavaServer Faces CRUD Application from a Database

The following runtime features have been added to the JSF CRUD Generator in NetBeans 6.1:

  • Vastly improved screen flow yields an intuitive user experience.
  • Simpler generated code is easier to maintain and customize.
  • Required checks prevent non-nullable column violations.
    Note: This feature requires including nullable or optional annotation elements in the entity classes. In NetBeans 6.1, the developer needs to perform this step manually for the relationship fields, since the Entity Classes from Database wizard does not generate them. Similarly, the developer needs to apply @GeneratedValue annotations manually as necessary on ID fields, since the Entity Classes from Database wizard does not generate them.
  • Orphan checks prevent non-nullable column violations in related entities.
  • Checks that verify the correct current entity prevent errors in case a user deviates from the normal interaction flow (for example, by working in multiple browser tabs).
  • Graceful handling of a user's attempt to operate on an entity that has been deleted by another user.
  • Graceful handling of a user's attempt to create a preexisting entity.
  • Correct handling of 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.
  • Fields can easily be removed from the generated JSPs, if such customization is desired.
  • Pages can be easily styled.

For general information on the JSF CRUD Generator, see JsfCrudGenerator. Note that the attachments to this page (JsfCrudGeneratorConsultingAgency) are newer. For information on enhancements in NetBeans 6.5, see JsfCrudGenerator65.

The Consulting Agency Database

The consulting agency database was designed to test the JSF CRUD Generator in NetBeans 6.1. Curiously, it is not intended as an example of recommended database design; rather, it attempts to incorporate as many relevant features potentially found in a database design as possible. For example, it contains all possible relationship types, composite primary keys, many different data types, etc.

The consulting agency database includes the following tables:

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 consulting agency database includes the following relationships. The inverse relationships are not shown here.

Database Table Related Table Relationship Information
CLIENT RECRUITER nullable one-to-one with manual editing; nullable one-to-many without
CLIENT ADDRESS non-nullable one-to-one
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
CONSULTANT PROJECT many-to-many
CONSULTANT BILLABLE non-nullable one-to-many
CONSULTANT_STATUS CONSULTANT non-nullable one-to-many
RECRUITER CONSULTANT nullable one-to-many
PROJECT BILLABLE non-nullable one-to-many


Creating the Database

  1. In the Services window, expand Databases, right-click on Java DB, and select Create Database.
  2. Enter consult as the Database Name, User Name, and Password in the Create Java DB dialog, and click OK. A new node under Databases appears (
    jdbc:derby://localhost:1527/consult [ConsultOnCONSULT]
    ).
  3. Right-click on the new node, and select Connect.
  4. Under the new node, right-click on the Tables node, and select Execute Command. A SQL Command editing window appears.
  5. In the SQL Command editing window, paste the contents of the attached File:Create-consult JsfCrudGeneratorConsultingAgency.sql create-consult JsfCrudGeneratorConsultingAgency.sql. Note: Attached is also a File:Drop-consult JsfCrudGeneratorConsultingAgency.sql drop-consult JsfCrudGeneratorConsultingAgency.sql script, for dropping the constraints and tables.
  6. In the SQL Command editing window, click the Run SQL toolbar button. No errors should result.

Creating the Project

Note: Attached is a ConsultingAgency_JsfCrudGeneratorConsultingAgency.zip file containing the ConsultingAgency project with the entities already generated and edited. You can skip this section as well as the Generating the Entities and Editing the Entities sections below if you use that project.

  1. Select File > New Project. Select Web in the Categories section and Web Application in the Projects section. Click Next.
  2. Enter ConsultingAgency as the Project Name. Select a location for the project, and click Next.
  3. Select Glassfish V2 as the Server, and click Next.
  4. Select the JavaServer Faces framework (not Visual Web JavaServer Faces), and click Finish.

Generating the Entities

Note: Attached is a ConsultingAgency_JsfCrudGeneratorConsultingAgency.zip file containing the ConsultingAgency project with the entities already generated and edited. You can skip this section if you use that project.

  1. In the Projects window, right-click on the ConsultingAgency node, and select New > Entity Classes from Database.
  2. In the Data Source dropdown, select New Data Source. The Create Data Source dialog appears.
  3. Enter jdbc/consult as the JNDI name and
    jdbc:derby://localhost:1527/consult [ConsultOnCONSULT]
    as the Database Connection. Click OK to close the dialog. The database tables appear in the Available Tables listbox.
  4. Click Add All. Then click Next.
  5. Enter entities as the Package. Then click Create Persistence Unit. The Create Persistence Unit dialog opens.
  6. Click Create to close the Create Persistence Unit dialog.
  7. Click Finish.
  8. Click the Save All toolbar button.
  9. In the Projects window, expand ConsultingAgency > Source Packages > entities. The IDE has generated an entity class for each table, except for the PROJECT_CONSULTANT table, since it is a join table. Also, the embeddable classes ClientPK and ProjectPK have been generated, since the CLIENT and PROJECT tables have composite primary keys.

Editing the Entities

Note: Attached is a ConsultingAgency_JsfCrudGeneratorConsultingAgency.zip file containing the ConsultingAgency project with the entities already generated and edited. You can skip this section if you use that project.

Note: If you are doing this section rather than using the attached ConsultingAgency project, certain individual steps below can be skipped during demos (for example, evangelist demos) for the sake of simplicity. These are marked as "(optional during demos)." Steps not so marked are shown in bold below for easier readability. In a tutorial, however, please include all steps, and be sure not to denote any steps as optional or differentiated via bold text.

The IDE has generated the entities, but they lack @GeneratedValue annotations and optional annotation elements.

Modify the entity classes as follows:

  • Address
  • Add an annotation
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    beneath the {@Id} annotation.
  • (optional during demos) In the toString method, change the return statement to
    return line1 + ", " + line2 + ", " + city + ", " + region + ", " + country + ", " + postalCode;
    .
  • Right-click and choose Fix Imports.
  • Billable
  • Add an annotation
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    beneath the {@Id} annotation.
  • Change the
    @ManyToOne
    annotation on the consultantId field to {@ManyToOne(optional = false)}.
  • Change the
    @ManyToOne
    annotation on the project field to {@ManyToOne(optional = false)}.
  • (optional during demos) In the toString method, change the return statement to
    description + ", " + consultantId + ", " + project;
    .
  • Right-click and choose Fix Imports.
  • Client
  • (optional during demos) Change the
    @OneToMany(mappedBy = "client")
    annotation on the recruiterCollection field to {@OneToOne(mappedBy = "client")}.
  • (optional during demos) Replace the recruiterCollection field with
    private Recruiter recruiter;
    .
  • (optional during demos) Replace the getRecruiterCollection method with
    public Recruiter getRecruiter() {return recruiter;} 
    .
  • (optional during demos) Replace the setRecruiterCollection method with
    public void setRecruiter(Recruiter recruiter) {this.recruiter = recruiter;} 
    .
  • Change the
    @OneToOne
    annotation on the billingAddress field to {@OneToOne(optional = false)}.
  • (optional during demos) In the toString method, change the return statement to
    return String.valueOf(clientPK);
    .
  • ClientPK
  • (optional during demos) In the toString method, change the return statement to
    clientName + ", Dept. " + clientDepartmentNumber;
    .
  • Consultant
  • Add an annotation
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    beneath the {@Id} annotation.
  • Change the
    @ManyToOne
    annotation on the statusId field to {@ManyToOne(optional = false)}.
  • (optional during demos) In the toString method, change the return statement to
    return email;
    .
  • Right-click and choose Fix Imports.
  • ConsultantStatus
  • (optional during demos) In the toString method, change the return statement to
    statusId + ", " + description;
    .
  • Project
  • Change the
    @ManyToOne
    annotation on the client field to {@ManyToOne(optional = false)}.
  • (optional during demos) In the toString method, change the return statement to
    return (projectPK == null ? "(unnamed project)" : projectPK.getProjectName()) + ", " + client;
    .
  • Recruiter
  • Add an annotation
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    beneath the {@Id} annotation.
  • (optional during demos) Change the
    @ManyToOne
    annotation on the client field to {@OneToOne}.
  • (optional during demos) In the toString method, change the return statement to
    return email;
    .
  • Right-click and choose Fix Imports.
  • Click the Save All toolbar button.

Here you apply a @GeneratedValue annotation to any ID field that corresponds to an autogenerated primary key database column. When you created the database tables, you indicated some of the primary key columns as autogenerated via the GENERATED ALWAYS AS IDENTITY keywords. Here you also apply the annotation element optional = false on all non-nullable many-to-one and one-to-one relationships. This will cause the IDE to generate required checks when you run the JSF Pages from Entity Classes wizard, which you will do in the Generating a JavaServer Faces Application section below. By generating required checks, you prevent the user from attempting to persist a null value in a non-nullable database column. You also customize the implementations of the toString method in the entity classes.

A more subtle modification you make is changing the relationship between clients and recruiters from one-to-many to one-to-one. A nullable one-to-many relationship already exists between recruiters and consultants. Therefore, you can take the opportunity to establish a nullable one-to-one relationship between clients and recruiters in order to observe and test that relationship's functionality.

Generating a JavaServer Faces Application

  1. In the Projects window, right-click the ConsultingAgency node, and select New > JSF Pages from Entity Classes. The New JSF Pages from Entity Classes dialog appears.
  2. Seven Entity classes display in the Available Entity Classes listbox. Click Add All. Then click Next.
  3. Change the package to beans, and click Finish.
  4. Click the Save All toolbar button.
  5. In the Projects window, expand ConsultingAgency > Source Packages > beans. The IDE has generated a controller and converter class for each entity class, resulting in a total of 14 classes in the beans package. Each controller class handles operations for the corresponding entity class, including creating, editing, and destroying instances of the entity class via the Java Persistence API. Each 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.
  6. Expand the ConsultingAgency > Web Pages node. The IDE has generated a folder containing Detail.jsp, Edit.jsp, List.jsp, and New.jsp for each entity class. The IDE has also inserted links to the various List.jsp pages in the welcomeJSF.jsp page.
  7. Expand the ConsultingAgency > Configuration Files node, double-click faces-config.xml, and click the XML button in the editing toolbar to show the XML source. The IDE has inserted managed-bean and converter elements for each controller and converter class. The IDE also has inserted a navigation-rule element for each JSP, indicating the logical outcome that causes the application to navigate to that JSP.

Running the Application

Note: Obviously, these steps need not be followed exactly during demos.

  1. In the Projects window, right-click the project node and choose Run to build, deploy, and launch the web application.
    Your browser navigates to http://localhost:8080/ConsultingAgency/.

    In the following steps, you create the various entities.

  2. Create an Address item, this time completing the Line1, City, Region, Country, and PostalCode fields.
  3. Create a Client item, specifying Big Data Corp. as the ClientName, 2000 as the DepartmentNumber, and completing the ContactEmail and BillingAddress fields.
  4. Create a Project item, specifying Secret Project as the ProjectName, and completing the ContactEmail and Client fields.
  5. Create a ConsultantStatus item, specifying A as the StatusId and Active as the Description.
  6. Create a Consultant item, specifying janet.smart@jsfcrudconsultants.com as the Email, Secret Project, Big Data Corp., Dept. 2000 as a member of ProjectCollection, A, Active as the StatusId, and completing the HourlyRate and BillableHourlyRate fields. Be sure to highlight Secret Project, Big Data Corp., Dept. 2000 before clicking Create.
  7. Create a Billable item, specifying begin gathering requirements as the Description and completing the Hours, HourlyRate, BillableHourlyRate, ConsultantId, and Project fields.
  8. Create another Billable item, specifying finish gathering requirements as the Description and completing the Hours, HourlyRate, BillableHourlyRate, ConsultantId, and Project fields.
  9. Create a Recruiter item, specifying bob@jsfcrudconsultants.com as the Email and janet.smart@jsfcrudconsultants.com as a member of the ConsultantCollection. Leave the Client field blank. Be sure to highlight janet.smart@jsfcrudconsultants.com before clicking Create.

    In the following steps, you observe subtle cases where fields appear as read-only.

  10. Navigate to the New Client page.
    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 consult_project_pk primary key and the consult_project_fk_client_name foreign key.
  11. Navigate to the Editing Project Page.
    The Client field is read-only. Again, this is because the Client associated with a Project is part of the Project's primary key.

    In the following steps, you explore operations that produce error messages.

  12. Attempt to 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.
  13. Attempt to create another Address item, but leaving all fields blank when doing so.
    Error messages appear indicating required fields.
  14. Attempt to edit the janet.smart@jsfcrudconsultants.com Consultant item, deselecting finish gathering requirements, janet.smart@jsfcrudconsultants.com, Secret Project, Big Data Corp., Dept. 2000 as a member of the BillableCollection.
    An error message appears indicating that the deselected Billable item must be retained, since its consultantId field is not nullable.
  15. Attempt to destroy the Secret Project, Big Data Corp., Dept. 2000 Project item.
    An error message appears indicating that the Project item cannot be destroyed, since its associated Billable items have a non-nullable project field.

    In the following steps, you attempt to destroy an entity that has already been destroyed by another user.

  16. Navigate to the Listing Billable Items page.
  17. Open an instance of a different browser. For example, if you have been working in Firefox, you could open an instance of Internet Explorer.
  18. In the new browser instance, destroy both Billable items.
  19. In the original browser instance, attempt to destroy one of the Billable items.
    An error message appears indicating that the Billable item no longer exists, and the list of Billables now indicates that no Billable items are found.

Styling the Application

  1. In the IDE, select File > New File. Select Web in the Categories section and Cascading Style Sheet in the File Types section. Click Next.
  2. Enter jsfcrud as the CSS File Name. Click Finish.
  3. Again, select File > New File. Select Web in the Categories section and Cascading Style Sheet in the File Types section. Click Next.
  4. Enter jsfcrudlist as the CSS File Name. Click Finish.
  5. In the Projects window, expand the Web Pages node.
    The IDE has created the jsfcrud.css and jsfcrudlist.css files.
  6. Edit the two stylesheets to match the contents of the jsfcrud.css and jsfcrudlist.css files contained in the attached stylesheets_JsfCrudGeneratorConsultingAgency_JsfCrudGeneratorConsultingAgency.zip file.
  7. In the Projects window, right-click on the ConsultingAgency node, and select Set as Main Project.
  8. From the Edit menu, select Replace in Projects. Enter <head> in the Containing Text field, <head><link rel="stylesheet" type="text/css" href="../jsfcrud.css" /> in the Replace With field, and New.jsp, Edit.jsp, Detail.jsp in the File Name Patterns field. Select Main Project under Scope and select Case Sensitive under Options.
  9. Click Find. Review the results and click Replace.
  10. Again, from the Edit menu, select Replace in Projects. Enter <head> in the Containing Text field, <head><link rel="stylesheet" type="text/css" href="../jsfcrudlist.css" /> in the Replace With field, and List.jsp in the File Name Patterns field. Select Main Project under Scope and select Case Sensitive under Options.
  11. Click Find. Review the results and click Replace.
  12. Again, from the Edit menu, select Replace in Projects. Enter <head> in the Containing Text field, <head><link rel="stylesheet" type="text/css" href="./jsfcrud.css" /> in the Replace With field, and welcomeJSF.jsp in the File Name Patterns field. Select Main Project under Scope and select Case Sensitive under Options.
  13. Click Find. Review the results and click Replace.
  14. Run the application again to see the effect of the stylesheets.

Customizing the Application

The IDE generates fields in the JSPs for all relationships. One way you might want to customize the generated application is to remove some fields, such as the fields of an entity for which no database column actually exists in the corresponding database table. For example, a ConsultantStatus item can have many Consultant items; accordingly, the CONSULTANT table has a foreign key (consult_consultant_fk_status_id) on the table's status_id column that references the corresponding column in the CONSULTANT_STATUS table. Conversely, there is no consultant_id column in the CONSULTANT_STATUS table. For this reason, you might want to remove the ConsultantCollection fields from the ConsultantStatus item pages.

You can remove the ConsultantCollection field from the Editing ConsultantStatus page simply by removing the following JSP code:

<h:outputText value="ConsultantCollection:"/>
 <h:selectManyListbox id="consultantCollection" value="#{consultantStatus.consultantCollectionOfConsultantStatus}" title="ConsultantCollection" size="6" >
 <f:selectItems value="#{consultant.consultantsAvailableSelectMany}"/>
 </h:selectManyListbox>

You can easily remove the ConsultantCollection field from the ConsultantStatus Detail and New ConsultantStatus pages in the same manner.

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