DevelopJavaEE5App

Contents

Develop JavaEE 5 application with Visual JSF, EJB3 and JPA

Introduction

This document describes the End-to-End steps to develop a JEE5 web-based application using Visual JavaServer Faces (JSF), Enterprise Java Beans (Session Bean) and Java Persistence API (JPA) with the help of Netbeans IDE as the tool. This tutorial creates a web application called CustomerApp that performs the CRUD functions on the customer records provided by the Netbeans sample database served by the Glassfish built-in database server, JavaDB (Derby).

The objective of this tutorial is to demonstrate the ease of using several JEE5 technologies like Visual JSF, EJB3 and JPA with the help of Netbeans IDE and putting them together to create an enterprise-ready web-based application. Although the application is developed for demo purpose, its architecture represents the best practice in developing an Enterprise application, whereby modularity, scalability and reusability are taken into consideration.

File:1-1-Architecture.png

The application is organized into the various tiers: Presentation, Business, Data Access and Data, where each has an important role to play and are segregated from one another. This architecture encourages clean separation of responsibilities, reusability and scalability through the use of Enterprise Java Beans. With the use of JSF and JPA, GUI development becomes a breeze and developers are no longer bogged down by the tedious and error-prone chores of converting Relational data to OO which is natural in Java and vice versa.

So all-in-all, this demo not only demonstrates the use of the various JEE5 technologies, it also demonstrates the best-of-breed application architecture that can be used in a production system.

Contents

Tutorial Requirements

Before we proceed, make sure you review the requirements in this section.

Prerequisites

This tutorial assumes that you have some basic knowledge of, or programming experience with, the following technologies.

  • JavaServer Faces, Visual JavaServer Faces
  • Enterprise Java Beans 3 (EJB3)
  • Java Persistence API (JPA)
  • Basic knowledge of using Netbeans (will help to reduce the time required to do this tutorial)

Software needed for this Tutorial

Before you begin, you need to install the following software on your computer:

  • Netbeans IDE 6.7.1 (Java pack), ensure Visual JSF plugin is installed
  • Glassfish Enterprise Server v2.1 or v2.1.1
  • Sample database installed along with Netbeans

    File:1-2-DBSetup.png

Notes

  • The Glassfish Enterprise Server is optionally included in the Java pack of Netbeans IDE, Glassfish can be installed separately from the IDE and added later into Servers services in the IDE
  • A copy of the working solution is included here if needed.

Creating the Enterprise Application Projects

The first step in creating the application is to create the necessary projects in Netbeans.

  1. Choose “File > New Project” to open the New Project Wizard. Under Categories, select Java EE; under Projects select Enterprise Application. Click Next
  2. Select the project location and name the project, CustomerApp, and click Next
  3. Select the installed Glassfish server v2.1 or v2.1.1 as the server, and Java EE 5 as the Java EE Version, and click Finish
    Netbeans will create 3 projects namely CustomerApp (Enterprise Application project), CustomerApp-ejb (EJB project) and CustomerApp-war (Web project).

    File:1-3-CustomerApp.png

Creating the Entity Classes from the Database

Before anything else, we first need to create the Entity Classes and because in this demo, the Session Beans are responsible for manipulating the data, they will be created in the EJB project.

  1. In the Projects view, right-click on the CustomerApp-ejb project and select “New > Entity Classes from Database…”
  2. Select Data Source (Radio button) and in the corresponding dropdown list, select New Data Source…
  3. Specify the JNDI name to be “jdbc/sample”, and select “jdbc:derby://localhost:1527/sample [app on APP]” as the Database Connection and click OK
  4. Under the Available Tables list box, select CUSTOMER and click on Add button so that it appears in the Selected Tables list box (Note that the related table, DISCOUNT_CODE is also added automatically) and click Next

    File:1-4-NewEntityClass.png
  5. Click on the “Create Persistence Unit...” button, select “jdbc/sample” as the Data Source and leave the rest as default

    File:1-5-CreatePersistUnit.png
  6. Provide a package name, e.g. “com.customerapp.entity” in the Package field and click Next
  7. Change the Collection Type to “java.util.List” and click Finish
  8. Take note of the new classes created under the Source Packages in the Projects view

    File:1-6-EntityClasses.png
  9. Add the following code in the DiscountCode class
   /**
    * Default constructor
    */
   public DiscountCode()
   {
       this.discountCode = new Character('N');
       this.rate = new BigDecimal(0.0);
       //Added the above 2 lines so that the variables are not null when used by the IDE to
       //display default values in the Visual JSF pages
   }
10. Add the following code in the Customer class
    /**
     * Default constructor
     */
    public Customer()
    {
        this.discountCode = new DiscountCode();
    }

    /**
     * This method is added here (Customer entity class) because we want to
     * include this field (discount rate) as a column in the Customer Listing
     * table later.
     */
    public BigDecimal getDiscountRate()
    {
        if (discountCode != null)
        {
            return discountCode.getRate();
        }
        return new BigDecimal(0.0);
    }

Creating the Session Bean, CustomerSession to provide the CRUD methods for Customer objects

Now that we have the Entity classes, the next thing is to create the Session (Stateless) Bean that will manipulate and provide the CRUD functionalities on the Customer objects. In this demo, the client that uses these functions are the JSF pages. One of the benefits of doing this (i.e. to provide the CRUD functionalities in the EJB layer) is reusability because the same functions can be used by more than 1 JSF pages, other EJBs, Enterprise Application Clients and Web Services Clients when exposed as web services. Other benefits include scalability because the EJB container can easily be tuned and scaled up when load increases.

  1. In the Projects view, right-click on the CustomerApp-ejb project and select “New > Session Bean”
  2. Specify the EJB Name as CustomerSession and the package as “com.customerapp.ejb”, and keep the rest of the options as default, and click Finish

    File:1-7-NewSessionBean.png
  3. From the Projects view, navigate to the source of the newly created Session Bean (skeleton) by double clicking on the CustomerSessionBean item

    File:1-8-SessionBean.png
  4. In the code editor, right-click and select “Persistence > Use Entity Manager”; the “@PersistenceContext” notation is inserted automatically, so now the EntityManager is ready to be used
  5. Create the business methods for the Session Bean: Create, Retrieve, Update and Delete; right-click in the code editor (find an appropriate placeholder for the method), select Insert Code..., under the Generate list, select Add Business Method…
  6. In the Add Business Method... dialog, provide the Name, Return Type and Parameters for the method

    File:1-9-AddBizMethod.png
  7. Repeat the steps for the rest of the CRUD functions.
  8. Edit the methods so that they implement the intended functions as shown below
@Stateless
public class CustomerSessionBean implements CustomerSessionLocal
{
    @PersistenceContext
    private EntityManager em;

    public void create(Customer customer)
    {
        em.persist(customer);
    }

    public List<Customer> retrieve()
    {
        Query query = em.createNamedQuery("Customer.findAll");
        return query.getResultList();
    }

    public Customer retrieve(String customerId)
    {
        Query query = em.createNamedQuery("Customer.findByCustomerId");
        query.setParameter("customerId", new Integer(customerId));
        return (Customer)query.getSingleResult();
    }
    
    public Customer update(Customer customer)
    {
        return em.merge(customer);
    }

    public void delete(Customer customer)
    {
        Customer managedCustomer = em.merge(customer);
        em.remove(managedCustomer);
    }

    /**
     * Included here for convenience rather than creating a new Session Bean
     * @return List<DiscountCode>
     */
    public List<DiscountCode> getDiscountCodes()
    {
        Query query = em.createNamedQuery("DiscountCode.findAll");
        return query.getResultList();
    }
}
Up to this point, the tasks required to be done in the EJB project are completed, we will move on to the next tier, JSF pages.

Preparing the Web Project to use Visual JSF

In this section, you will create the JSF pages to present the screens to perform the CRUD functions. To achieve this, we will be creating 3 web pages:

  • CustomerList – listing of all Customer records in the database in a tabular form
  • CustomerDetails – view/edit the details of a selected Customer record and deletion
  • CustomerNew – creation of a new Customer record

Before creating the web pages, ensure the Visual Web JavaServer Faces framework is added to the Web project, CustomerApp-war.

  1. In the Projects view, right-click on the Web project, CustomerApp-war, and select Properties (last item)
  2. Under the Categories items, select Frameworks, and ensure the Visual Web JavaServer Faces is added to the Used Frameworks list, and name the Default Java Package as “com.customerapp.web”

    File:1-10-WarProjectProperties.png

Creating the Customer Listing Web Page

Now, we are ready to create the first web page that lists the Customer records in the database in a tabular form.

  1. In the Projects view, right-click on the Web project, CustomerApp-war, and select “New > Visual Web JSF Page...”, specify CustomerList as the File Name
  2. Go to the Java view (by clicking on the button labeled, “Java” near the top of the editor pane) of the new created page (CustomerList), right-click within the class and select “Insert Code…”
  3. Under the Generate list, select “Call Enterprise Bean...”. Expand the CustomerApp-ejb project and select the CustomerSessionBean and click OK
  4. Notice the automatically generated variable that represents an instance of the session bean, at the top of the class,
   @EJB
   private CustomerSessionLocal customerSessionBean;
5. Manually add the following code at the end of the class
   /**
    * Return a list of all customers found in the database. This becomes a
    * property that can be used by the JSF page to bind to the data table.
    * @return
    */
   public List<Customer> getCustomers()
   {
       //Call Session Bean
       return customerSessionBean.retrieve();
   }
6. Go back to the Design view of the JSF page, and drag a Data Table from the palette into the editor pane

File:1-11-CustomerListDesign.png
7. Right-click on the table (title bar), and select “Table Layout…”
8. Select “customers (CustomerList)” from the Get Data From dropdown list and select the column fields you want to display in the table. The existence of this data is the result of step 5 (added getCustomers() method in the class). The sequence of the columns and their names to be displayed can be specified in this dialog. Click OK when done.

File:1-12-TableLayout.png
9. Drag a Button from the palette into the editor below the table and change the ID to newCustomer and label to “New Customer”. The screen should look like this now

File:1-13-CustomerListDesign2.png

10. To create an action handler for the new button, double-click on the button, and the editor will bring you to a newly generated method, newCustomer_action() in the Java view, just take note of it for now.
11. Next, we want to be able to navigate to the Customer Details page from the list, so drag a Hyperlink from the Palette and drop it into the Customer ID column of the table.
12. Go to the JSP view and notice the hyperlink tag is added to the Customer ID column. Edit the code so that the hyperlink displays the Customer ID as the text and CustomerDetails.jsp (a new page that will be created later) as the target URL with the parameter, custId. The result should look like this
    <webuijsf:tableColumn headerText="Customer ID" id="tableColumn1" sort="customerId">
        <webuijsf:hyperlink id="hyperlink1" text="#{currentRow.value['customerId']}"  
            url="CustomerDetails.jsp?custId=#{currentRow.value['customerId']}"/>
    </webuijsf:tableColumn>
13. Up to this point, we are ready to see the result of the artifacts created so far. In the Projects view, right-click on the CustomerApp project and select Clean and Build, and select Deploy (Ensure all the projects have the same Glassfish v2.1/2.1.1 server as the target server). To confirm, navigate to the Enterprise Applications folder in the Glassfish server under the Services view and check if the application, CustomerApp exist

File:1-14-Glassfish.png

14. Open the browser and go to URL, http://localhost:8080/CustomerApp-war/faces/CustomerList.jsp and you should see the following screen

File:1-15-CustomerList.png

Creating the Customer Details and New Web Pages

Now that we have completed the listing page, let's move on to create the details page where users can view/edit the customer details as well as to delete it.

  1. For convenience reasons, the fields in the CustomerDetails page will be bounded to the Customer object stored in the Session. To allow this, open the class, SessionBean1 in the editor and add the following codes:
    /**
     * Store the Customer object here and used by the CustomerDetails page to
     * display and update the attributes
     */
    private Customer customerDetails = null;

    public Customer getCustomer()
    {
        return customerDetails;
    }

    public void setCustomer(Customer customer)
    {
        this.customerDetails = customer;
    }
2. In the Projects view, right-click on the Web project, CustomerApp-war, and select “New > Visual Web JSF Page...”, specify CustomerDetails as the File Name
3. Go to the Java view (by clicking on the button labeled, “Java” near the top of the editor pane) of the new created page (CustomerDetails), right-click within the class and select “Insert Code…”
4. Under the Generate list, select “Call Enterprise Bean...”, expand the CustomerApp-ejb project and select the CustomerSessionBean and click OK
5. Notice the automatically generated variable that represents an instance of the session bean, at the top of the class,
   @EJB
   private CustomerSessionLocal customerSessionBean;
6. Look for the method, prerender(), and add the following codes in the method:
   @Override
   public void prerender()
   {
       String customerId = getFacesContext().getExternalContext().
               getRequestParameterMap().get("custId");
       if (customerId != null)
       {
           //Get the customer object and bind it to the Session
           Customer customer = customerSessionBean.retrieve(customerId);
           getSessionBean1().setCustomer(customer);
       }
   }
7. Go back to the Design view and create the UI by dragging and dropping the components from the Palette to the Editor. Arrange the components so that they look like this

File:1-16-CustomerDetailsDesign.png
8. To bind the text fields to the attributes in the Customer object, right-click on the text field component in the editor, e.g. Customer ID, and select “Bind to Data...”. In the “Bind to Data” dialog, navigate to and select the tree item, #{SessionBean1.customer.customerId} as shown below, and click OK

File:1-17-BindToData.png

Repeat the steps for all the fields except for the Discount Code dropdown. Things are slightly different for the Discount Code dropdown list because the available values for the list is fixed, we will bind the data to the ApplicationBean1 instead, i.e. all pages and sessions will be using the same list.
9. Open the ApplicationBean1 class in the editor and right-click within the class and select “Insert Code…”
10. Under the Generate list, select “Call Enterprise Bean...”. Expand the CustomerApp-ejb project and select the CustomerSessionBean and click OK
11. At the end of the class, add the following codes:
    /**
     * This returns an array of discount options that can be used to bind to a
     * dropdown list, e.g. the discount code dropdown list in CustomerDetails
     * @return Option[] discountCodes
     */
    public com.sun.webui.jsf.model.Option[] getDiscountCodes()
    {
        com.sun.webui.jsf.model.Option[] discountOptions = null;
        List<DiscountCode> discountList = customerSessionBean.getDiscountCodes();
        if (discountList != null && discountList.size() > 0)
        {
            int i = 0;
            discountOptions = new com.sun.webui.jsf.model.Option[discountList.size()];
            for (DiscountCode dc : discountList)
            {
                discountOptions[i++] = new Option(dc.getDiscountCode(),
                        dc.getDiscountCode() + " (" + dc.getRate() + "%)");
            }
        }
        return discountOptions;
    }
12. Go back to the Design view and bind the Discount Code dropdown list to this property. Right-click on the dropdown list component and select Bind to Data…
13. In the “Bind to Data” dialog, navigate to and select the tree item, #{ApplicationBean1.discountCodes} as shown below, and click OK

File:1-18-BindToData2.png
14. The above only binds the fixed list of discount codes to the dropdown list, but to display the selected value for the customer details, we need to define the selected value for the field
15. In the Design view of CustomerDetails, select the Discount Code dropdown list component. In the Properties view, scroll to the property, “selected” as shown below and click on the “...” button

File:1-19-CustomerDetailsDesign2.png
16. In the “Bind to Data” dialog, navigate to and select the tree item, #{SessionBean1.customer.discountCode.discountCode}, and click OK
17. Next we are ready to add in the action handlers for the 3 buttons: Update, Delete and Cancel. In the Design view, double-click on the Update button and you will be brought to the newly generated method in the Java view. Repeat for the Delete ad Cancel buttons and edit the codes so that it looks like this:
    /**
     * Action handler to handle the Update button action
     * @return String status
     */
    public String update_action()
    {
        Customer updatedCustomer =
                customerSessionBean.update(getSessionBean1().getCustomer());
        getSessionBean1().setCustomer(updatedCustomer);
        return "SAVED";
    }

    /**
     * Action handler to handle the Delete button action
     * @return String status
     */
    public String delete_action()
    {
        customerSessionBean.delete(getSessionBean1().getCustomer());
        getSessionBean1().setCustomer(null);
        return "DELETED";
    }

    /**
     * Action handler to handle the Cancel button action
     * @return String status
     */
    public String cancel_action()
    {
        return "CANCEL";
    }
18. Like in all cases, you would want to warn the user for any deletion, so we can prompt a confirmation dialog when user clicks on the delete button. In the Design view of the CustomerDetails, select the Delete button component, and in the Properties view, scroll down to the property, “onClick”. Select the “...” button and in the dialog, enters the JavaScript in the space provided as shown below

File:1-20-DeletJavaScript.png
19. Up to this point, we have completed the tasks that we need to do for the CustomerDetails page, and we can move on to the CustomerNew page. Fortunately, there is no need to create the page from scratch, we can make use of the copy & paste function in Netbeans to create the new page. Simply perform a right-click Copy on the CustomerDetails page from the Projects view and Paste it into the Web Pages folder. Then do a “Refactor > Rename” to rename the page from CustomerDetails_1 to CustomerNew.
20. In the new CustomerNew page, go to the Java view and edit the source code so that it looks like this:
    @Override
    public void prerender()
    {
        //bind an empty Customer object to the session
        getSessionBean1().setCustomer(new Customer());
    }

    /**
     * Action handler for the Create button action
     * @return String status
     */
    public String create_action()
    {
        customerSessionBean.create(getSessionBean1().getCustomer());
        return "CREATED";
    }

    /**
     * Action handler for the Cancel button action
     * @return String status
     */
    public String cancel_action()
    {
        return "CANCEL";
    }
21. Now that we have all the pages ready, we need to define the page flow. In the Projects view, navigate to the faces-config.xml file in the Configuration Files folder of the CustomerApp-war project and define the flows in the Page Flow Editor as shown below

File:1-21-PageFlow.png
Finally, the application is completed and we are ready to try it out.
22. In the Projects view, right-click on the CustomerApp project and select “Clean and Build”, and then select Deploy
23. Run the start page again, http://localhost:8080/CustomerApp-war/faces/CustomerList.jsp, and from the listing, click on the first Customer ID (1) in the table, and the details will be displayed as follows

File:1-22-CustomerDetails.png
24. Try out the rest of the functions: Update, Delete, Create, etc

Summary

Congratulation, by now you should have a fully working application with the CRUD functionalities. Using the same methods, you can expand the application into a full-fledge enterprise application with little effort. If you cannot get your application to work like how it is supposed to be, not to worry, you can get a copy of the working solution from here.

This tutorial demonstrates the use of various JEE5 technologies (Visual JSF, EJB3 & JPA) to build an enterprise-ready web-based application. Although the same application can be achieved easily by using Visual JSF and JPA alone, but it may not be as scalable and reusable as what is being done here. In this tutorial, the application is segregated into different tiers where each does what they do best: presentation, business logics and data access. This promotes the principle of separation of concerns and each tier can change without effecting the other, e.g. we can change the Visual JSF piece to use ICEfaces as the presentation tier if needed later.

Good luck with your next JEE5/6 application!

--Christopherlam 06:27, 8 December 2009 (UTC)

See Also

For other related resources, see the followings:

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