How to Create a Java EE 6 Application with JSF 2, EJB 3.1, JPA, and NetBeans IDE 6.8
Develop a web-based app based on technologies in the JEE6 specs such as Enterprise Java Beans 3.1 and JPA with the help of NetBeans IDE 6.8.
Join the DZone community and get the full member experience.
Join For FreeThere are many articles and tutorials out there that discuss how to use the individual technologies in Java EE 6, e.g., JSF 2, EJB 3.1, JPA, etc, to develop an application, but I haven't seen one that puts together the said technologies and showcases them in one tutorial with an end-to-end demonstration. As such, I thought I would create one here for the benefit of those who are new to JEE6 and NetBeans IDE 6.8 and those who are seriously looking at NetBeans IDE 6.8 as a tool for developing their enterprise applications.
This article aims to provide detailed steps to develop a web-based application based on technologies in the JEE6 specs, i.e., JavaServer Faces 2.0 (JSF), Enterprise Java Beans 3.1 (Session Bean and Message-Driven Bean) and Java Persistence API (JPA) with the help of NetBeans IDE 6.8 as the development & deployment tool. The example in this tutorial creates a web application called "CustomerApp" that performs only the Retrieve and Update functions of CRUD on the customer records provided by the NetBeans Sample database served by the Glassfish built-in database server, JavaDB (Derby). In addition to the above-mentioned technologies from JEE6, PrimeFaces for JSF2 will also be used as the Ajax-based Framework for the Web UI portion which is lacking in the stack. So, this tutorial also discusses how PrimeFaces can be integrated into NetBeans IDE and to enable Ajax capabilities for Web projects.
The objective of this tutorial is to demonstrate the ease of using the various JEE6 technologies and putting them together to create an enterprise-ready web-based application. Although the application is developed for demo purposes, its architecture represents the best practices in developing an enterprise application, whereby modularity, scalability, and reusability are taken into consideration.
The architecture of the application is shown in the above diagram, where it is organized into various tiers: Presentation, Business, Data Access and Data, where each has an important role to play and is segregated from one another. This architecture encourages a 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 JEE6 technologies, it also demonstrates the best-of-breed application architecture that can be used in a production system.
Contents
The rest of this article consists of the following sections:
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 (JSF) with Facelets
- Enterprise Java Beans (EJB) 3/3.1
- Java Persistence API (JPA)
- Basic knowledge of using NetBeans IDE will help to reduce the time required to do this tutorial
Software needed for this Tutorial
Before you begin, you need to download and install the following software on your computer:
- NetBeans IDE 6.8 (Java pack), http://www.netbeans.org
- Glassfish Enterprise Server v3, https://glassfish.dev.java.net
- PrimeFaces Component Library, http://www.primefaces.org
- Sample database installed along with NetBeans IDE:
Notes:
- The Glassfish Enterprise Server is included in the Java pack of NetBeans IDE, however, 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 if needed.
Creating the Enterprise Application Project
The approach for developing the demo app, CustomerApp, will be from the back end, i.e., the artifacts and services needed by the front-end UI will be created first, then working forward to the User Interface, i.e., the Ajax-based Web UI will be done last.
The first step in creating the application is to create the necessary projects in NetBeans IDE.
- Choose "File > New Project" to open the New Project Wizard. Under Categories, select Java EE; under Projects select Enterprise Application. Click Next.
- Select the project location and name the project, CustomerApp, and click Next.
- Select the installed Glassfish v3 as the server, and Java EE 6 as the Java EE Version, and click Finish.
NetBeans IDE will create 3 projects, namely CustomerApp (Enterprise Application project), CustomerApp-ejb (EJB project), and CustomerApp-war (Web project).
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.
- In the Projects window, right-click on the CustomerApp-ejb project and select "New > Entity Classes from Database..."
- Select Data Source (Radio button) and in the corresponding dropdown list, select "New Data Source..."
- 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.
- 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
- Click on the "Create Persistence Unit..." button, select "jdbc/sample" as the Data Source; leave the rest as default and click Create:
- Provide a package name, e.g. "com.customerapp.entity" in the Package field and click Next.
- Change the Collection Type to "java.util.List" and click Finish.
- Take note of the new classes created under the Source Packages in the Projects window:
Creating the Enterprise Java Beans (Session & Message-Driven)
Now that we have the Entity classes, the next task is to create the Session (Stateless) Bean, CustomerSession that will manipulate and provide the RU 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 functionalities in the EJB layer) is reusability because the same functions can be used by more than one 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.
We will also create a Message-Driven Bean (MDB), NotificationBean here to demonstrate its use for asynchronous messaging. In this tutorial, we want to send out notifications upon a successful update of a Customer record. For simplicity, we are just sending the updated Customer object to the Queue, so that the MDB can pick it up and process it in a separate thread.
- In the Projects window, right-click on the CustomerApp-ejb project and select "New > Session Bean..."
- In the New Session Bean dialog, specify the EJB Name as CustomerSession, the package as "com.customerapp.ejb", Session Type as Stateless and leave Create Interface unchecked, i.e. no Interface (New in EJB 3.1), and click Finish.
- In the Projects window again, right-click on the CustomerApp-ejb project and select "New > Message-Driven Bean..."
- In the New Message-Driven Bean dialog, specify the EJB Name as NotificationBean and the package as "com.customerapp.mdb", click on the "Add..." button of the Project Destination option.
- In the Add Message Destination dialog, specify the Destination Name as NotificationQueue and keep the Destination Type as Queue and click OK.
Click Finish to complete the creation of the MDB. - From the Projects window, navigate to the source of the newly created Session Bean (skeleton) by double clicking on the CustomerSessionBean item:
- In the code editor, right-click and select "Persistence > Use Entity Manager"; the "@PersistenceContext" notation is inserted automatically, so now the EntityManager, with variable name, em is ready to be used.
- Create the business methods for the Session Bean: Retrieve and Update; right-click in the code editor, select Insert Code..., under the Generate list, select Add Business Method...
- In the Add Business Method... dialog, provide the Name, Return Type and Parameters for the method:
- Repeat the steps for the Update function and notice the skeletons created for the 2 methods.
- Edit the methods so that they implement the intended functions as shown below:
For the purpose of the demo, we will send the updated Customer object to the destination queue.@Stateless@LocalBeanpublic class CustomerSessionBean{ @PersistenceContext private EntityManager em; /** * Returns a list of Customer objects in the database * @return List<Customer> */ public List<Customer> retrieve() { Query query = em.createNamedQuery("Customer.findAll"); return query.getResultList(); } /** * Update the customer record * @param customer object to be updated * @return Customer */ public Customer update(Customer customer) { return em.merge(customer); }}
- In the code editor, right-click and select "Insert Code...", and "Send JMS Message" from the Generate list.
- In the Send JMS Message dialog, select "jms/NotificationQueue" as the Project Destination and click OK. *Notice the 2 auto-generated methods, createJMSMessageForjmsNotificationQueue and sendJMSMessageToNotificationQueue.
- In the update method, insert code to call the sendJMSMessageToNotificationQueue after the em.merge() statement and modify the createJMSMessageForjmsNotificationQueue method to send ObjectMessage instead:
@Resource(name = "jms/NotificationQueue")private Queue notificationQueue;@Resource(name = "jms/NotificationQueueFactory")private ConnectionFactory notificationQueueFactory;public Customer update(Customer customer){ Customer updated = em.merge(customer); try { sendJMSMessageToNotificationQueue(updated); } catch (JMSException ex) { Logger.getLogger(CustomerSessionBean.class.getName()).log(Level.SEVERE, null, ex); } System.out.println("Customer updated in CustomerSessionBean!"); return updated;}private Message createJMSMessageForjmsNotificationQueue(Session session, Object messageData) throws JMSException{ //Modified to use ObjectMessage instead ObjectMessage tm = session.createObjectMessage(); tm.setObject((Serializable) messageData); return tm;}private void sendJMSMessageToNotificationQueue(Object messageData) throws JMSException{ Connection connection = null; Session session = null; try { connection = notificationQueueFactory.createConnection(); session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer messageProducer = session.createProducer(notificationQueue); messageProducer.send(createJMSMessageForjmsNotificationQueue(session, messageData)); } finally { if (session != null) { try { session.close(); } catch (JMSException e) { Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Cannot close session", e); } } if (connection != null) { connection.close(); } }}
- In the Message-Driven Bean, NotificationBean, edit the onMessage method to simply print the details of the updated Customer object to show that it receives the message.
Note that typically you would not want to process the message in the MDB itself: for best practices, the MDB should invoke methods in another Session Bean to perform the processing. But, for purposes of demonstration in this tutorial, we are stopping at the MDB:public void onMessage(Message message){ try { Object msgObj = ((ObjectMessage)message).getObject(); if (msgObj != null) { Customer customer = (Customer)msgObj; System.out.println("Customer with the following details has been updated:"); StringBuilder sb = new StringBuilder(); sb.append("Customer ID="); sb.append(customer.getCustomerId()); sb.append(", "); sb.append("Name="); sb.append(customer.getName()); sb.append(", "); sb.append("Email="); sb.append(customer.getEmail()); System.out.println(sb.toString()); } } catch (JMSException ex) { Logger.getLogger(NotificationBean.class.getName()).log(Level.SEVERE, null, ex); }}
Up to this point, the tasks required to be done in the EJB project are completed, we will move on to the next tier, Presentation, i.e. the JSF pages.
Preparing the Web Project to Use JSF 2.0 & PrimeFaces
Because JSF 2.0 is very new (at the time of writing this article), there are not many choices of Ajax-based frameworks that works with it. I have found PrimeFaces to be the most complete and suitable for this demo as it has implemented the dataTable UI component and it seems to be the easiest to integrate into the NetBeans IDE.
Before creating the web pages, ensure the JavaServer Faces framework is added to the Web project, CustomerApp-war.
- In the Projects window, right-click on the Web project, CustomerApp-war, and select Properties (last item).
- Under the Categories items, select Frameworks, and ensure the JavaServer Faces is added to the Used Frameworks list:
Before we are able to use PrimeFaces components in our facelets, we need to include its library in NetBeans IDE and set up a few things.
- Download the PrimeFaces library (primefaces-2.0.0.RC.jar) from http://www.primefaces.org/downloads.html and store it somewhere on the local disk.
- To allow future projects to use PrimeFaces, I chose to create a Global library in NetBeans for PrimeFaces.
- Select "Tools > Libraries" from the NetBeans IDE main menu.
- In the Library Manager dialog, choose "New Library" and provide a name for the library, e.g. "PrimeFaces2".
- With the new "PrimeFaces2" library selected, click on the "Add JAR/Folder..." button and select the jar file that was downloaded earlier and click OK to complete:
- Next, we need to add the newly created library, PrimeFaces2 to the Web project:
- Select the Web project, CustomerApp-war, from the Project window, right-click and select "Properties".
- Under the Libraries category, click on the "Add Library..." button (on the right), and choose the PrimeFaces2 library and click OK to complete:
- Because we will be using Facelets in our demo, we will update the XHTML template in NetBeans so that all the XHTML files created subsequently will already have the required namespaces and resources needed for the development.
- Choose "Tools > Templates" from the NetBeans menu.
- In the Template Manager dialog, select "Web > XHTML" and click the "Open in Editor" button.
- Edit the content of the file so that it looks like this:
<?xml version="1.0" encoding="${encoding}"?><#assign licenseFirst = "<!--"><#assign licensePrefix = ""><#assign licenseLast = "-->"><#include "../Licenses/license-${project.license}.txt"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.prime.com.tr/ui"> <h:head> <meta http-equiv="Content-Type" content="text/html; charset=${encoding}"/> <title>TODO supply a title</title> <p:resources /> </h:head> <h:body> <p> TODO write content </p> </h:body></html>
- Lastly, we need to add the following statements in the web.xml file of the Web project for PrimeFaces to work correctly:
<servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> <url-pattern>*.jsf</url-pattern></servlet-mapping><servlet> <servlet-name>Resource Servlet</servlet-name> <servlet-class> org.primefaces.resource.ResourceServlet </servlet-class></servlet><servlet-mapping> <servlet-name>Resource Servlet</servlet-name> <url-pattern>/primefaces_resource/*</url-pattern></servlet-mapping><context-param> <param-name>com.sun.faces.allowTextChildren</param-name> <param-value>true</param-value></context-param>
At this point, we are done setting up and configuring the environment for PrimeFaces to work in NetBeans. We will next create the Customer Listing and Details views.
In the sections below, you will create the JSF pages to present the screens to perform the Read/Update functions. To achieve this, we will be creating 2 web pages:
- CustomerList - listing of all Customer records in the database in a tabular form
- CustomerDetails - view/edit the details of the selected Customer record
Creating the Customer Managed Bean
Before creating the JSF pages, we first create the managed bean which will be providing the required services for the JSF pages that will be created later.
- In the Projects window, right-click on the Web project, CustomerApp-war, and select "New > JSF Managed Bean...", specify CustomerMBean as the Class Name, "com.customerapp.web" as the Package Name, customer as the Name, and the scope to be session.
- In the code editor of the newly created class, CustomerMBean, right-click and select "Insert Code...", and "Call Enterprise Bean..." under the Generate list.
- In the "Call Enterprise Bean" dialog, expand the CustomerApp-ejb project and select the CustomerSessionBean and select the No Interface option (anyway the Local and Remote options should be disabled because we created the Session Bean with no interface) for Referenced Interface, and click OK.
- Notice the automatically generated variable, customerSessionBean that represents an instance of the session bean, at the beginning of the class declaration.
Add the rest of the methods (properties and action handlers) and its implementations in the class as shown below, they will be used by the JSF pages later:@ManagedBean(name="customer")@SessionScopedpublic class CustomerMBean{ @EJB private CustomerSessionBean customerSessionBean; private Customer customer; public CustomerMBean() { } /** * Returns list of customer objects to be displayed in the data table * @return */ public List getCustomers() { return customerSessionBean.retrieve(); } /** * Returns the selected Customer object * @return */ public Customer getDetails() { //Can either do this for simplicity or fetch the details again from the //database using the Customer ID return customer; } /** * Action handler - user selects a customer record from the list * (data table) to view/edit * @param customer * @return */ public String showDetails(Customer customer) { this.customer = customer; return "DETAILS"; } /** * Action handler - update the changes in the Customer object to the * database * @return */ public String update() { System.out.println("###UPDATE###"); customer = customerSessionBean.update(customer); return "SAVED"; } /** * Action handler - goes to the Customer listing page * @return */ public String list() { System.out.println("###LIST###"); return "LIST"; }}
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.
- In the Projects window, right-click on the Web project, CustomerApp-war, and select "New > XHTML...", specify CustomerList as the File Name.
Note: If the item "XHTML..." doesn't appear in your menu list, select "New > Others..." instead, then in the New File dialog, select Web under Categories and you should be able to see the XHTML file type on the right. - For convenience sake, we are going to create the initial table from the palette instead of coding from scratch. In the code editor, drag item, "JSF Data Table from Entity" from the palette and drop it in between the <h:body></h:body> tags of the newly generated file, CustomerList.xhtml:
- A dialog with the title, "JSF Table from Entity" appears; select "com.customerapp.entity.Customer" as the Entity Bean, and "customer.customers" as the Managed Bean property and click OK.
Note: The result of this are lines of codes automatically generated to display a default list of the Customer objects. - At this point, we are ready to see the result of the first web page created so far. In the Projects window, right-click on the CustomerApp project and select Clean and Build, and select Deploy. To confirm that the deployment is successful, navigate to the Applications folder in the Glassfish server under the Services window and check if the application, CustomerApp, exists:
- Open the browser and go to URL, http://localhost:8080/CustomerApp-war/CustomerList.jsf and you should see the following screen:
Note: The screen is very raw and without any beautification because up to now, it is still plain vanilla JSF. So we will next modify the page to show only the columns of interest and to use PrimeFaces dataTable where pagination is made possible. - To use PrimeFaces dataTable in the CustomerList.xhtml page, simply replace the <h:dataTable> and <h:column> tags to <p:dataTable> and <p:column> respectively and modify the rest of the code to look like the following:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.prime.com.tr/ui"> <h:head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>Customer Listing</title> <p:resources /> </h:head> <h:body> <h:form> <h2><h:outputText value="Customer Listing"/></h2> <p:dataTable var="item" value="#{customer.customers}" id="customerList" paginator="true" rows="10"> <p:column> <f:facet name="header"> <h:outputText value="Customer ID" /> </f:facet> <h:commandLink action="#{customer.showDetails(item)}" value="#{item.customerId}"/> </p:column> <p:column> <f:facet name="header"> <h:outputText value="Name"/> </f:facet> <h:outputText value="#{item.name}"/> </p:column> <p:column> <f:facet name="header"> <h:outputText value="CreditLimit"/> </f:facet> <h:outputText value="#{item.creditLimit}"/> </p:column> <p:column> <f:facet name="header"> <h:outputText value="Discount %"/> </f:facet> <h:outputText value="#{item.discountCode.rate}"/> </p:column> <p:column> <f:facet name="header"> <h:outputText value="State"/> </f:facet> <h:outputText value="#{item.state}"/> </p:column> <p:column> <f:facet name="header"> <h:outputText value="City"/> </f:facet> <h:outputText value="#{item.city}"/> </p:column> <p:column> <f:facet name="header"> <h:outputText value="Zip"/> </f:facet> <h:outputText value="#{item.zip}"/> </p:column> <p:column> <f:facet name="header"> <h:outputText value="Phone"/> </f:facet> <h:outputText value="#{item.phone}"/> </p:column> <p:column> <f:facet name="header"> <h:outputText value="Email"/> </f:facet> <h:outputText value="#{item.email}"/> </p:column> </p:dataTable> </h:form> </h:body></html>
The result of the changes should look like this:
Now that we have the listing page, let's move on to create the details page.
Creating the Customer Details Web Page
Now we will create the page where the details of the selected customer is displayed and can be updated.
- In the Projects window, right-click on the Web project, CustomerApp-war, and select "New > XHTML...", specify CustomerDetails as the File Name.
- In the code editor, drag the item, "JSF Form from Entity" from the palette and drop it in between the <body></body> tags of the newly generated file, CustomerDetails.xhtml:
- A dialog with the title, "JSF Form from Entity" appears; select "com.customerapp.entity.Customer" as the Entity Bean, and "customer.details" as the Managed Bean property and click OK:
Note: The result of this are lines of code automatically generated to display the label and input field of all the attributes in the Customer object in a 2 column grid. - To enable the navigation from the Listing page to the Details and vice versa, you need to edit the faces-config.xml with the PageFlow editor and connect the 2 pages as shown in the diagram below:
Note: The strings LIST and DETAILS must match the return String of the list and showDetails methods in the CustomerMBean. - To see the result, save and deploy the application, go to the Customer listing page at URL, http://localhost:8080/CustomerApp-war/CustomerList.jsf, and click on the Customer ID on the first row in the table:
Again, this looks very raw, so let's try to spice it up a little and include the Update function as well. - The Discount Codes is a fixed list in the database, so it makes sense to present it in the form of a dropdown list for user to select for Update. So we will bind the value of the of the Discount Codes dropdown list to a new property, customer.discountCodes in CustomerMBean which returns an array of SelectItem(Object value, String label):
Note: the value of each SelectItem is the Discount Code of type Character, as such, the value to be bound to the Discount Code needs to be of type Character for the preselect to work when the details of a customer is being displayed. So we will need to create the getter and setter methods for a new property, discount in the Customer Entity class, which uses Character as the argument:/** * Returns an array of SelectItem to be displayed in the DiscountCode * Dropdown list in the CustomerDetails page * @return */public javax.faces.model.SelectItem[] getDiscountCodes(){ SelectItem[] options = null; List discountCodes = customerSessionBean.getDiscountCodes(); if (discountCodes != null && discountCodes.size() > 0) { int i = 0; options = new SelectItem[discountCodes.size()]; for (DiscountCode dc : discountCodes) { options[i++] = new SelectItem(dc.getDiscountCode(), dc.getDiscountCode() + " (" + dc.getRate() + "%)"); } } return options;}
//New getter and setter methods for discount in Customer.javapublic Character getDiscount(){ return this.discountCode.getDiscountCode();}public void setDiscount(Character code){ this.discountCode = new DiscountCode(code);}
- Bind this new property, "customer.details.discount" to the value of the <h:selectOneMenu> of the Discount Code field in the CustomerDetails.xhtml:
<h:selectOneMenu id="discountCode" value="#{customer.details.discount}"> <f:selectItems value="#{customer.discountCodes}"/> </h:selectOneMenu>
- Make the rest of the changes to the XHTML page with the help of the code completion feature of NetBeans IDE:
- Add the Command buttons, for Update and Back.
- Rearrange the rows and use a different background color for the panelGrid.
- Add a PrimeFaces component at the end of the page, <p:messages>, which displays FacesMessage created in the Managed Bean, e.g., a success message upon a successful update:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.prime.com.tr/ui"> <h:head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>Customer Details</title> <p:resources /> </h:head> <h:body> <h2><h:outputText value="Customer Details"/></h2> <h:form> <h:panelGrid columns="2" bgcolor="#eff5fa"> <h:outputLabel value="Customer ID:"/> <h:inputText id="customerId" value="#{customer.details.customerId}" disabled="true"/> <h:outputLabel value="Customer Name:"/> <h:inputText id="customerName" value="#{customer.details.name}"/> <h:outputLabel value="Credit Limit:"/> <h:inputText id="creditLimit" value="#{customer.details.creditLimit}"/> <h:outputLabel value="Discount Code"/> <h:selectOneMenu id="discountCode" value="#{customer.details.discount}"> <f:selectItems value="#{customer.discountCodes}"/> </h:selectOneMenu> <h:outputLabel value="Email:"/> <h:inputText id="email" value="#{customer.details.email}"/> <h:outputLabel value="Phone:"/> <h:inputText id="phone" value="#{customer.details.phone}"/> <h:outputLabel value="Fax:"/> <h:inputText id="fax" value="#{customer.details.fax}"/> <h:outputLabel value="Address (Line 1):"/> <h:inputText id="address1" value="#{customer.details.addressline1}"/> <h:outputLabel value="Address (Line 2):"/> <h:inputText id="address2" value="#{customer.details.addressline2}"/> <h:outputLabel value="State:"/> <h:inputText id="state" value="#{customer.details.state}"/> <h:outputLabel value="City:"/> <h:inputText id="city" value="#{customer.details.city}"/> <h:outputLabel value="Zip:"/> <h:inputText id="zip" value="#{customer.details.zip}"/> </h:panelGrid> <h:commandButton id="back" value="Back" action="#{customer.list}"/> <h:commandButton id="update" value="Update" action="#{customer.update}"/> </h:form> <p:messages showDetail="true" /> </h:body></html>
- Modify the update method of the CustomerMBean class to create a FacesMessage upon a successful update to demonstrate the use of the PrimeFaces <p:messages> component:
The result of the changes should look like this after clicking on the Update button:public String update() { customer = customerSessionBean.update(customer); FacesContext context = FacesContext.getCurrentInstance(); context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Sucessful", "Record successfully saved!")); return "SAVED"; }
Note: after performing the Update function, you should see something similar to the following in the log file, server.log:
Note: The statement "Customer updated in CustomerSessionBean" although printed in the Session Bean (ThreadID=28) after invoking the send JMS message, appears before the next two lines which are printed in the Message-Driven Bean in ThreadID=20.[#|2009-11-30T14:42:50.550+0800|INFO|glassfishv3.0|...|_ThreadID=28;_ThreadName=Thread-1;|Customer updated inCustomerSessionBean!|#][#|2009-11-30T14:42:50.950+0800|INFO|glassfishv3.0|...|_ThreadID=20;_ThreadName=Thread-1;|Customer with the following details has been updated:|#][#|2009-11-30T14:42:50.950+0800|INFO|glassfishv3.0|...|_ThreadID=20;_ThreadName=Thread-1;|Customer ID=1, Name=JumboCom 2, Email=jumbocom@gmail.com|#]
Summary
Congratulations. At this point you should have a fully working application with the RU functionalities. Using the same approach and methods, you can expand the application into a full-fledged 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 .
This tutorial demonstrates the use of various JEE6 technologies (JSF2.0, EJB3 & JPA) to build an enterprise-ready web-based application. Although the same application can be achieved easily by using 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 Presentation tier to use [http://www.icefaces.org ICEfaces] as the Ajax framework if needed later.
Good luck with your next Java EE application!
See Also
For other related resources, see the followings:
- Develop Java EE 5 application with Visual JSF, EJB3 and JPA
- Develop Java EE 6 application with JSF2, EJB3 and JPA using NetBeans IDE 6.8
- Securing Java EE 6 application with JEE Security and LDAP
- Develop Ajax-based JSF2 applications with PrimeFaces using NetBeans IDE 6.8
Opinions expressed by DZone contributors are their own.
Comments