Saturday, May 25, 2013

EJB/JSF Master Detail Web Application in Eclipse

Every Developer deals with database knows very well how the Master_Detail page is the basics in web Application that connects to database.As we explained in the previous post we will use the sample hr schema of Oracle Database to develop a JSF Datatable that lists all the departments of HR,when you press show employees button in any department you navigate to another page that lists all the employees of the selected department.

Because this is the first post of developing EJB/JSF web application,I will explain in detail every aspect of the application including how to connect to Oracle Database from your Eclipse, how to generate Entity classes from database tables, how to create EJB project ,how to add JPA capabilities to your project and so on. Note that in the following posts, I will not repeat all this as you can go back to the previous posts to learn more.At the end of the post you will find the source code of the sample application built using Eclipse.

Connect to Oracle database using Eclipse:

In the lower panel of eclipse you could find Data Source Explorer as in the figure


 Note that If you don't see Data Source Explorer here, then in eclipse menubar, click on Window -> Open Perspective -> other -> Database Development ,this will open the Data Source Explorer in left panel.To switch back to your Project Explorer, click on Window -> Open Perspective -> other -> Java EE (default).

In the Data Source Explorer right-click on Database Connections and click New.In Connection Profile window select Oracle and in the name field write hrConn; click Next


On the upper right corner click on New Driver Definition button


In New Driver Definition window, select Oracle Thin Driver and then click JAR List tab.


In JAR List tab, select the default driver and click on Edit JAR/Zip... button. Select the jar file ojdbc6.jar which you have downloaded in the previous post here, click Open and then click Ok.
In the General tab under Properties, fill in the login details to be able to connect to your database as in the figure:


Check Save password, and click on Test Connection and you will see ping successful message. Click Finish.

In the next step we'll use this database connection and create Departments and Employees entity classes using JPA 2.0 and Eclipselink.

 Create the EJB project :

In our application,there are two main projects EJB Project that will hold our business logic and JSF project that represent the user Interface, let's create our EJB Project and enable JPA capabilities for it.

From your eclipse menubar click on file->New->EJB Project and name the project MasterDetailEJB as in the figure:


Click in the “Finish” button.

Generate Entity Classes For Our Project:


In order to use JPA capabilities to generate our entity classes, you have to add JPA Facet to our Project Facets.Right-click your project in project explorer and click properties. In the project facets, on the left-hand side click on Project Facets and from the Project Facets’ list check JPA. This will prompt a link Further Configuration available in lower part of the window.Click on Further configuration available.



In the JPA Facet Window select EclipseLink 2.3.x under Platform.In JPA implementation Click on Disable Library Configuration.Glassfish 3.1.2 Server ships with EclipseLink,so you don't have to configure it.

Under Connection Select hrConn database which you have previously created. Also, check 'Add driver library to build path'. Finally it should look Like the following figure:



Click Ok. Finally in the Project Facets click Ok and you are done

Next, we'll create data model for our project in which we'll create entity classes from Departments and Employees tables.In the project explorer, right-click on ejbModule and click New -> other.From the wizard list under JPA click JPA Entities form Tables


In Select Tables window,choose hrConn from connection and select Departments and Employees Tables. Check Update class list in persistence.xml and click Next.Click Next again


in the Key generator field select identity from the list.This is important to select your key generator as Identity, this will cause your entity class to automatically generate primary key.Under Domain Java Class name your package model.entities and click next


 In Customize Individual Entities wizard select Departments and change the class Name to DepartmentEntity  and repeat the previous step to change the Employees to EmployeeEntity as in the figure then click finish


The DepartmentEntity.java and the EmployeeEntity.java classes are created under the package model.entities..We will add a named query for the department entity to get all the departments and another named query for the employee entity to get all the employees for the selected department.The code after adding the named queries should look like the following:

DepartmentEntity:
 package model.entities;  
 import java.io.Serializable;  
 import javax.persistence.*;  
 import java.util.List;  
 /**  
  * The persistent class for the DEPARTMENTS database table.  
  *   
  */  
 @Entity  
 @Table(name = "DEPARTMENTS")  
 @NamedQueries({ @NamedQuery(name = "Departments.findAll", query = "SELECT d FROM DepartmentEntity d") })  
 public class DepartmentEntity implements Serializable {  
      private static final long serialVersionUID = 1L;  
      @Id  
      @GeneratedValue(strategy = GenerationType.IDENTITY)  
      @Column(name = "DEPARTMENT_ID")  
      private long departmentId;  
      @Column(name = "DEPARTMENT_NAME")  
      private String departmentName;  
      @Column(name = "LOCATION_ID")  
      private java.math.BigDecimal locationId;  
      // bi-directional many-to-one association to Employee  
      @ManyToOne  
      @JoinColumn(name = "MANAGER_ID")  
      private EmployeeEntity employee;  
      // bi-directional many-to-one association to Employee  
      @OneToMany(mappedBy = "department")  
      private List<EmployeeEntity> employees;  
      public DepartmentEntity() {  
      }  
      public long getDepartmentId() {  
           return this.departmentId;  
      }  
      public void setDepartmentId(long departmentId) {  
           this.departmentId = departmentId;  
      }  
      public String getDepartmentName() {  
           return this.departmentName;  
      }  
      public void setDepartmentName(String departmentName) {  
           this.departmentName = departmentName;  
      }  
      public java.math.BigDecimal getLocationId() {  
           return this.locationId;  
      }  
      public void setLocationId(java.math.BigDecimal locationId) {  
           this.locationId = locationId;  
      }  
      public EmployeeEntity getEmployee() {  
           return this.employee;  
      }  
      public void setEmployee(EmployeeEntity employee) {  
           this.employee = employee;  
      }  
      public List<EmployeeEntity> getEmployees() {  
           return this.employees;  
      }  
      public void setEmployees(List<EmployeeEntity> employees) {  
           this.employees = employees;  
      }  
 }  
EmployeeEntity:
 package model.entities;  
 import java.io.Serializable;  
 import javax.persistence.*;  
 import java.math.BigDecimal;  
 import java.util.Date;  
 import java.util.List;  
 /**  
  * The persistent class for the EMPLOYEES database table.  
  *   
  */  
 @Entity  
 @Table(name = "EMPLOYEES")  
 @NamedQueries({ @NamedQuery(name = "Employees.findbydept", query = "select emp from EmployeeEntity as emp where emp.department.departmentId = :theId order by emp.employeeId") })  
 public class EmployeeEntity implements Serializable {  
      private static final long serialVersionUID = 1L;  
      @Id  
      @GeneratedValue(strategy = GenerationType.IDENTITY)  
      @Column(name = "EMPLOYEE_ID")  
      private long employeeId;  
      @Column(name = "COMMISSION_PCT")  
      private BigDecimal commissionPct;  
      private String email;  
      @Column(name = "FIRST_NAME")  
      private String firstName;  
      @Temporal(TemporalType.DATE)  
      @Column(name = "HIRE_DATE")  
      private Date hireDate;  
      @Column(name = "JOB_ID")  
      private String jobId;  
      @Column(name = "LAST_NAME")  
      private String lastName;  
      @Column(name = "PHONE_NUMBER")  
      private String phoneNumber;  
      private BigDecimal salary;  
      // bi-directional many-to-one association to Department  
      @OneToMany(mappedBy = "employee")  
      private List<DepartmentEntity> departments;  
      // bi-directional many-to-one association to Department  
      @ManyToOne  
      @JoinColumn(name = "DEPARTMENT_ID")  
      private DepartmentEntity department;  
      // bi-directional many-to-one association to Employee  
      @ManyToOne  
      @JoinColumn(name = "MANAGER_ID")  
      private EmployeeEntity employee;  
      // bi-directional many-to-one association to Employee  
      @OneToMany(mappedBy = "employee")  
      private List<EmployeeEntity> employees;  
      public EmployeeEntity() {  
      }  
      public long getEmployeeId() {  
           return this.employeeId;  
      }  
      public void setEmployeeId(long employeeId) {  
           this.employeeId = employeeId;  
      }  
      public BigDecimal getCommissionPct() {  
           return this.commissionPct;  
      }  
      public void setCommissionPct(BigDecimal commissionPct) {  
           this.commissionPct = commissionPct;  
      }  
      public String getEmail() {  
           return this.email;  
      }  
      public void setEmail(String email) {  
           this.email = email;  
      }  
      public String getFirstName() {  
           return this.firstName;  
      }  
      public void setFirstName(String firstName) {  
           this.firstName = firstName;  
      }  
      public Date getHireDate() {  
           return this.hireDate;  
      }  
      public void setHireDate(Date hireDate) {  
           this.hireDate = hireDate;  
      }  
      public String getJobId() {  
           return this.jobId;  
      }  
      public void setJobId(String jobId) {  
           this.jobId = jobId;  
      }  
      public String getLastName() {  
           return this.lastName;  
      }  
      public void setLastName(String lastName) {  
           this.lastName = lastName;  
      }  
      public String getPhoneNumber() {  
           return this.phoneNumber;  
      }  
      public void setPhoneNumber(String phoneNumber) {  
           this.phoneNumber = phoneNumber;  
      }  
      public BigDecimal getSalary() {  
           return this.salary;  
      }  
      public void setSalary(BigDecimal salary) {  
           this.salary = salary;  
      }  
      public List<DepartmentEntity> getDepartments() {  
           return this.departments;  
      }  
      public void setDepartments(List<DepartmentEntity> departments) {  
           this.departments = departments;  
      }  
      public DepartmentEntity getDepartment() {  
           return this.department;  
      }  
      public void setDepartment(DepartmentEntity department) {  
           this.department = department;  
      }  
      public EmployeeEntity getEmployee() {  
           return this.employee;  
      }  
      public void setEmployee(EmployeeEntity employee) {  
           this.employee = employee;  
      }  
      public List<EmployeeEntity> getEmployees() {  
           return this.employees;  
      }  
      public void setEmployees(List<EmployeeEntity> employees) {  
           this.employees = employees;  
      }  
}
Now we have created our entity classes. Before creating our business logic or our enterprise java beans called EJBs,we will first configure our persistence.xml file to access the Data Source that we create in our glassfish in the previous post here

Open your persistence.xml, which you will find under JPA Content folder and in the navigation options of xml file click on Source. Make these few changes to make the file look like the following :
 <?xml version="1.0" encoding="UTF-8"?>  
 <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">  
      <persistence-unit name="MasterDetailPU" transaction-type="JTA">  
      <jta-data-source>jdbc/hrConn</jta-data-source>  
           <class>model.entities.DepartmentEntity</class>  
           <class>model.entities.EmployeeEntity</class>  
      </persistence-unit>  
 </persistence>  
In the code above we have specified a persistence unit named MasterDetailPU.As transaction type we have used JTA (Java Transaction API) as JTA DataSource, we have specified jdbc/hrConn, that we have created in our glassfish 3.1.2 in the previous post and finally we have specified our entities classes, which is to be mapped.

Now we'll create our EJB. In order to create enterprise java beans, right click on ejbModule package and click New -> Other. From Wizards' list select Session Bean (EJB 3.x) under EJB and click Next.


Give 'model.ejb ' as package name. Give DepartmentBean as class Name. Select 'State type' as 'Stateless' and click finish.


Delete the default constructor and make the code look like the following; in the code import all the necessary packages.

DepartmentBean:
 package model.ejb;  
 import java.util.List;  
 import javax.ejb.LocalBean;  
 import javax.ejb.Stateless;  
 import javax.persistence.EntityManager;  
 import javax.persistence.PersistenceContext;  
 import model.entities.DepartmentEntity;  
 /**  
  * Session Bean implementation class DepartmentBean  
  */  
 @Stateless  
 @LocalBean  
 public class DepartmentBean {  
      @PersistenceContext(unitName = "MasterDetailPU")  
      private EntityManager em;  
      public List<DepartmentEntity> findAllDept() {  
           return em.createNamedQuery("Departments.findAll").getResultList();  
      }  
 }  
So simple as that. EJBs has made life easier for us.In the above code, we have created a persistence context, that will take care of our entities, and then we have create our entity manager, that will perform actions on entity classes.You don't need to open and close and commit your transactions anymore. Entity manager will take care of all that.

In our method which will return a list of departments, we have called our namedquery that we have created in DepartmentEntity using em.createNamedQuery,then we have executed our query,and we have returned our DepartmentList.

Repeat the previous step to create EmployeeBean sessionbean and write a method that take the DepartmentId as an argument and return a list of employees for that department.The Code of the session bean should look like the following

EmployeeBean:
 package model.ejb;  
 import java.util.List;  
 import javax.ejb.LocalBean;  
 import javax.ejb.Stateless;  
 import javax.persistence.EntityManager;  
 import javax.persistence.PersistenceContext;  
 import model.entities.EmployeeEntity;  
 /**  
  * Session Bean implementation class EmployeeBean  
  */  
 @Stateless  
 @LocalBean  
 public class EmployeeBean {  
      @PersistenceContext(unitName = "MasterDetailPU")  
      private EntityManager em;  
      public List<EmployeeEntity> getEmployeesForDepartment(Long departmentId) {  
           List<EmployeeEntity> Emp;  
           Emp = em.createNamedQuery("Employees.findbydept")  
                     .setParameter("theId", departmentId).getResultList();  
           return Emp;  
      }  
 }  
Now that we have created our business logic, let us create our User Inteface or JSF project  that will handle the web logic 

Create The JSF Project: 

From your eclipse menubar click on file->New->Dynamic Web Project,name the Project MasterDetailJSF and from the Configuration choose JavaServer Faces v2.0 project as in the figure.click next then next


Check generate web.xml deployment descriptor.click next


Choose Disable Library Configuration.Glassfish already ships with JSF 2.0 built-in, so we don't need to specify anything.At URL Mapping Patterns, select the default /faces/* and click Remove to remove it. Prefix patterns end up to be less maintainable.Click Add... to add a new pattern with the value *.xhtml. Finally click finish


Add the EJB Project to JSF Project in the Build Path:
Now we need our JSF project to see the business model and be able to access it.To do this we should add the EJB project in the build path for our JSF project,to do this right click the JSF project, go to Java Build Path property and click add as in the figure


Check your MasteDetailEJB project and click ok then ok


Now we we'll create our managed beans to access our EJB methodand develop the web logic.Right click on src package and create a new class by clicking New -> class. Give the package name as beans. Give the class name as Departmentweb, and click finish.


Departmentweb.java
 package beans;  
 import java.io.Serializable;  
 import java.util.List;  
 import javax.annotation.PostConstruct;  
 import javax.ejb.EJB;  
 import javax.faces.application.FacesMessage;  
 import javax.faces.bean.ManagedBean;  
 import javax.faces.bean.ViewScoped;  
 import javax.faces.context.FacesContext;  
 import model.ejb.DepartmentBean;  
 import model.entities.DepartmentEntity;  
 @ManagedBean  
 @ViewScoped  
 public class Departmentweb implements Serializable {  
      /**  
       *   
       */  
      private static final long serialVersionUID = 1L;  
      @EJB  
      private DepartmentBean departmentBean;  
      private List<DepartmentEntity> Departments;  
      public List<DepartmentEntity> getAllDepartments() {  
           if (Departments == null) {  
                loadDepartments();  
           }  
           return Departments;  
      }  
      private void loadDepartments() {  
           try {  
                Departments = departmentBean.findAllDept();  
           } catch (Exception e) {  
                FacesContext.getCurrentInstance().addMessage("",  
                          new FacesMessage("Error while getting Department list"));  
                // Always log stacktraces (with a real logger).  
                e.printStackTrace();  
           }  
      }  
      /**  
       * ------If the page content is very large and the session has not been  
       * previously created some response may have been written so the solution is  
       * to create the session before the Facelet (/JSP) page is printed-----  
       */  
      @PostConstruct  
      void initialiseSession() {  
           FacesContext.getCurrentInstance().getExternalContext().getSession(true);  
      }  
}
In the previous code, we have injected our EJB class DepartmentBean by using the annotation @EJB. This annotation allows us to access EJBs directly in our ManagedBean class.As you see in the previous code we have called our findAllDept() method directly from DepartmentBean.java class.

Repeat the previous step to create the Employeeweb managedbean as follows:

Employeeweb.java
 package beans;  
 import java.io.Serializable;  
 import java.util.List;  
 import javax.annotation.PostConstruct;  
 import javax.ejb.EJB;  
 import javax.faces.application.FacesMessage;  
 import javax.faces.bean.ManagedBean;  
 import javax.faces.bean.ViewScoped;  
 import javax.faces.context.FacesContext;  
 import model.entities.EmployeeEntity;  
 import model.ejb.EmployeeBean;  
 @ManagedBean  
 @ViewScoped  
 public class Employeeweb implements Serializable {  
      /**  
       *   
       */  
      private static final long serialVersionUID = 1L;  
      @EJB  
      private EmployeeBean employeeBean;  
      private Long selectedDepartmentId;  
      public Long getSelectedDepartmentId() {  
           return selectedDepartmentId;  
      }  
      public void setSelectedDepartmentId(Long selectedDepartmentId) {  
           this.selectedDepartmentId = selectedDepartmentId;  
      }  
      public List<EmployeeEntity> getEmployeeList() {  
           List<EmployeeEntity> employees = null;  
           try {  
                employees = employeeBean  
                          .getEmployeesForDepartment(selectedDepartmentId);  
           } catch (Exception e) {  
                FacesContext.getCurrentInstance().addMessage("",  
                          new FacesMessage("Error while fetching Employees"));  
           }  
           return employees;  
      }  
      @PostConstruct  
      void initialiseSession() {  
           FacesContext.getCurrentInstance().getExternalContext().getSession(true);  
      }  
 }  
In this bean we will define selectedDepartmentId variable that will be used as an argument for our method that will take the selectedDepartmentId variable and return a list of employees for this department, you may ask now how we will set this variable?Do not worry we will do this in our page through <f:viewParam> approach which will set the Department id in our bean

now it’s the time to develop our web pages and display the Data by accessing our managed beans

Create template in JSF 2.0 to manage facelets:

A commonly used practice during the design phase of an application is to create a single page template that all other pages will be derived from.Let's see how to do that. Right click on the web content folder and click New -> XHTML Page if XHTML option doesn't show here, click New -> Other, and under GlassFish select XHTML Page as in the figure

Name the page as template and click finish.Our Template would look like the following:
 <?xml version='1.0' encoding='UTF-8' ?>  
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
 <html xmlns="http://www.w3.org/1999/xhtml"  
      xmlns:h="http://java.sun.com/jsf/html"  
      xmlns:ui="http://java.sun.com/jsf/facelets"  
      xmlns:f="http://java.sun.com/jsf/core">  
 <ui:insert name="metadata" />  
 <h:head>  
      <title><ui:insert name="title">Master Detail</ui:insert></title>  
      <h:outputStylesheet library="style" name="main.css" />  
 </h:head>  
 <body>  
      <table width="100%" border="0">  
           <tr>  
                <td height="81"><h1 align="center">JSF Master Detail  
                          Application</h1></td>  
           </tr>  
      </table>  
      <table border="0">  
           <tr>  
                <td width="40%"></td>  
                <td><ui:insert name="content" /></td>  
           </tr>  
      </table>  
 </body>  
 </html>  
The template exposes three spots for templated content:
metadata: at the very top of the page, content at the very bottom of the page,and title, which is simply the content of the HTML <title> element.

then we come to the <h:head> section. This section has a <ui:insert> for the title, with a default value of Master Detail, and it includes a stylesheet using 
 <h:outputStylesheet library="style" name="main.css" />  
(This is an example of a usage of a resource library)


Following the head is a table that spans the width of the page.This table provides a common page header for application pages

Create the Dept Page:


Now it’s the time to create our Departments page and display the list of departments.Right-click on WebContent folder and create xhtml page called dept.xhtml, and make the code look like the following:
 <?xml version='1.0' encoding='UTF-8' ?>  
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
 <html xmlns="http://www.w3.org/1999/xhtml"  
      xmlns:h="http://java.sun.com/jsf/html"  
      xmlns:f="http://java.sun.com/jsf/core"  
      xmlns:ui="http://java.sun.com/jsf/facelets">  
 <h:body>  
      <ui:composition template="/template.xhtml">  
           <ui:define name="content">  
                <h3>All Departments</h3>  
                <h:form>  
                     <h:dataTable value="#{departmentweb.allDepartments}" var="dept"  
                          border="1" cellpadding="2" cellspacing="0">  
                          <h:column>  
                               <f:facet name="header">DepartmentId</f:facet>  
                #{dept.departmentId}  
                </h:column>  
                          <h:column>  
                               <f:facet name="header">Department Name </f:facet>  
               #{dept.departmentName}  
               </h:column>  
                          <h:column>  
                               <f:facet name="header">Take action</f:facet>  
                               <h:link id="emp" value="View Emp" outcome="employeeView">  
                                    <f:param name="id" value="#{dept.departmentId}" />  
                               </h:link>  
                          </h:column>  
                     </h:dataTable>  
                </h:form>  
           </ui:define>  
      </ui:composition>  
 </h:body>  
 </html>  
This page is using our template or act as a template client for template.xhtml so we use <ui:composition template="/template.xhtml"> to do that. Here we define the content part in the content facelets and create h:Data Table component.We access our managed bean and display a list for all departments.We use a <h:link> with <f:param> to store the Id of the selected department

Create Employees Page:
 <?xml version='1.0' encoding='UTF-8' ?>  
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
 <html xmlns="http://www.w3.org/1999/xhtml"  
      xmlns:h="http://java.sun.com/jsf/html"  
      xmlns:f="http://java.sun.com/jsf/core"  
      xmlns:ui="http://java.sun.com/jsf/facelets"  
      xmlns:c="http://java.sun.com/jsp/jstl/core">  
 <h:body>  
      <ui:composition template="/template.xhtml">  
           <ui:define name="metadata">  
                <f:metadata>  
                     <f:viewParam name="id" required="true"  
                          value="#{employeeweb.selectedDepartmentId}"  
                          requiredMessage="No Department selected"  
                          validatorMessage="Invalid Department id selected">  
                          <f:validateLongRange minimum="1" />  
                     </f:viewParam>  
                </f:metadata>  
           </ui:define>  
           <ui:define name="content">  
                <h:form>  
                     <h:dataTable value="#{employeeweb.employeeList}" var="emp"  
                          border="1" cellpadding="2" cellspacing="0"  
                          rendered="#{employeeweb.employeeList.size()>0}">  
                          <h:column>  
                               <f:facet name="header">First Name</f:facet>  
             #{emp.firstName}  
              </h:column>  
                          <h:column>  
                               <f:facet name="header">LastName</f:facet>  
               #{emp.lastName}  
            </h:column>  
                          <h:column>  
                               <f:facet name="header">Salary</f:facet>  
               #{emp.salary}  
               </h:column>  
                          <h:column>  
                               <f:facet name="header">Job ID</f:facet>  
               #{emp.jobId}  
               </h:column>  
                          <h:column>  
                               <f:facet name="header">Department Id</f:facet>  
               #{emp.department.departmentId}  
               </h:column>  
                     </h:dataTable>  
                     <br />  
                     <h:panelGroup rendered="#{employeeweb.employeeList.size()==0}">  
                Sorry No Employees For this Department  
               </h:panelGroup>  
                     <h:link outcome="dept" value="back to All departments" />  
                </h:form>  
           </ui:define>  
      </ui:composition>  
 </h:body>  
 </html>  
This page uses also the template.xhtml and has <ui:define> elements for the metadata and content spots.<f:metadata> section declares a <f:viewParam> named id.This is the other side of the <h:link> on the dept.xhtml page.First we store the selected department id  by using <f:param> in the table page then we use <f:viewParam> In the other page to convey the selected Department id and set it in Employeeweb managed bean.

For the content section we display a DataTable that lists all the Employees for the selected department. Also we use the rendered  property to display the table when the selected department has employees, otherwise we display a message that there are no employees for the selected department.

Finally the web.xml for our Application should look like that :
 <?xml version="1.0" encoding="UTF-8"?>  
 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
      xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"  
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
      id="WebApp_ID" version="3.0">  
      <display-name>MasterDetailJSF</display-name>  
      <welcome-file-list>  
           <welcome-file>dept.xhtml</welcome-file>  
      </welcome-file-list>  
      <servlet>  
           <servlet-name>Faces Servlet</servlet-name>  
           <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>  
           <load-on-startup>1</load-on-startup>  
      </servlet>  
      <servlet-mapping>  
           <servlet-name>Faces Servlet</servlet-name>  
           <url-pattern>*.xhtml</url-pattern>  
      </servlet-mapping>  
 </web-app>  
Packing our Application in an Ear File and Running it:

Now Let us create an EAR to unite our projects.From the Eclipse menubar click on File -> New -> Other ->EnterpriseApplication Project

Click next

Check  the two projects and check generate application.xml deployment Descriptor.click finish

Now we need to add the Ear to our server.Just select the Ear File and Run as->Run on server ->select your Glassfish Server and then ok


To access our Application use the URL:http://localhost:8080/MasterDetailJSF (note that 8080 is the port of my Glassfish server you may use a different port depending on the configuration of your Glassfish)

You will see a Data table that lists all the Departments(I wrote the pages with a simple css for simplicity )


 Click View Emp for any department and you will navigate to a page that will lists all the Employees for the selected Department

As we said earlier you will see only a simple message if you choose a Department that hasn't  any Employees 


To download the source code for this post click here.open your eclipse and click file->import ->under general select existing projects into workspace


Select the source code you downloaded and click finish.You will see the three projects in the project explorer. Select the Ear project and right click then run it on your glassfish (note that your glassfish should also be 3.1.2 to be able to run it)

If you have any questions please post it below

See you soon and happy JSF Developing

3 comments:

  1. great job!!! congratulations from Brasil

    ReplyDelete
  2. great tutorial, I learned that the trough tutorial discussion http://stackoverflow.com/questions/19130663/master-detail-in-jsf, master-detail relationships always create doubts among developers and is rare quality tutorials on the subject in web or memo books, congratulations, already abusing your goodwill, that this same tutorial with the saves and updates the master and detail kkkk

    Congratulations from Brazil (2)

    ReplyDelete