5 min read

Adding a web client to your project

There are several ways to test our Hibernate application. The simplest of all is adding a web application, which is packaged in an enterprise application along with the Hibernate application. Create a new dynamic web project named HibernateWeb.

The first step, before adding servlets and JSPs is linking the HibernateProject libraries to your web application, otherwise, you will not be able to reference the Hibernate POJOs. Right-click on your project and select Properties. Reach the Java Build Path option and select the tab Projects. From there add HibernateProject.

JBoss AS 5 Development

Let’s move on. This project will contain a main servlet that acts as a controller, and a few JPSs for the client view. We will start by adding com.packtpub.hibernateWeb.HibernateServlet to our project.

In the following snippet, you can see the core section of the servlet. Here, we will not detail the Controller logic, which is straightforward if you have some rudiments of the MVC pattern; rather we want to highlight the most interesting part of it, which is how to query and persist Hibernate objects.

public class HibernateServlet extends HttpServlet {
private SessionFactory getSessionFactory() {
return (SessionFactory)getServletContext().
getAttribute("sessionFactory");
}
public void init() { [1]
if (getSessionFactory() != null) {
return;
}
InitialContext ctx;
try {
ctx = new InitialContext();
factory = (SessionFactory)ctx.
lookup("java:/hibernate/SessionFactory");
getServletContext().setAttribute("sessionFactory", factory);
}
catch (NamingException e) {
e.printStackTrace();
}
}
private String saveEmployee(HttpServletRequest request) {
Session hsession=null;
String name=request.getParameter("name");
String salary=request.getParameter("salary");
String departmentId=request.getParameter("departmentId");
try {
hsession = getSessionFactory().openSession();
hsession.beginTransaction();
Query query = hsession.createQuery("from Department d where
d.departmentId = :departmentId"); [2]
query.setInteger("departmentId", new Integer(departmentId));
Department dep = (Department) query.uniqueResult();
Employee emp = new Employee();
emp.setDepartment(dep);
emp.setEmployeeName(name);
emp.setEmployeeSalary(Integer.parseInt(salary));
hsession.save(emp); [3]
hsession.getTransaction().commit();
}
catch (Exception e) {
// TODO Auto-generated catch block e.printStackTrace();
hsession.getTransaction().rollback();
}
finally {
if (hsession.isOpen())
hsession.close();
}
return employeeList(request);
}
private String employeeList(HttpServletRequest request) {
Session hsession=null;
Department dep;
try {
hsession = getSessionFactory().openSession();
Query query = hsession.createQuery("select p from Employee p
join fetch p.department c"); [4]
List <Employee>list = query.list();
request.setAttribute("employee", list);
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (hsession.isOpen())
hsession.close();
}
return "/listEmployees.jsp";
}
private String saveDepartment(HttpServletRequest request) {
String depName=request.getParameter("depName");
Session hsession=null;
Department dep;
try {
hsession = getSessionFactory().openSession();
hsession.beginTransaction();
dep = new Department();
dep.setDepartmentName(depName);
hsession.save(dep); [5]
hsession.getTransaction().commit();
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
hsession.getTransaction().rollback();
}
finally {
if (hsession.isOpen())
hsession.close();
}
return employeeList(request);
}
}

As you can see from the preceding code, we recover the SessionFactory from the JNDI tree in the init() [1] method of the servlet. Instances of SessionFactory are thread-safe and typically shared throughout an application, so we store it in the ServletContext and share it among all servlet instances.

The SessionFactory is subsequently used to start a Hibernate session, which is not thread-safe and should only be used for a single transaction or unit of work in an application.

In order to store our Employee, in the saveEmployee method, we first retrieve the corresponding Department from our schema [2], and finally the Employee is saved [3] and the transaction is committed.

The list of employees is fetched by the employeeList method. Notice we are using a join fetch statement to retrieve all the employees [4], which will be routed to the listEmployees.jsp view. Why? The answer is that with the default fetch mode (Lazy), once the Hibernate session is closed, the client will not be able to navigate through the department field of the Employee. The common solution to this issue is switching to the EAGER fetch mode that reads the related fields (in our case department) in memory, as soon as we query the Employee table.

You have more than one option to achieve this. One possible solution, if you don’t want to change the default fetch mode for the Employee table, is to build an ad hoc query that forces Hibernate to read also the fields in relation with the Employee table.

"select p from Employee p join fetch p.department c"

If you prefer to use the XML class files to configure the fetch mode, you can also change the lazy=”true” attribute in the employee-department relationship.

The last method, saveDepartment [5] takes care to persist a new Department in the corresponding table. We complete our excursus on the web tier with the listEmployees.jsp that is used to display a tabular view of the employees:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<script language="JavaScript">
function doSubmit(url) {
document.module.action = url;
document.module.submit();
}
</script>
<body>
<table border="1">
<tr>
<th>Name</th>
<th>Salary</th> <TH>department</th>
</tr>
<c:forEach items="${employee}" var="emp">
<tr>
<td> <c:out value="${emp.employeeName}"/> </td>
<td> <c:out value="${emp.employeeSalary}"/></td>
<td> <c:out value="${emp.department.departmentName}"/></td>
</tr>
</c:forEach>
</table>
<form name="module" method="POST">
<input type="button" value ="New Employee"
onClick="doSubmit('actionServlet?op=newEmployee')">
<input type="button" value ="New Department"
onClick="doSubmit('actionServlet?op=newDepartment')">
</form>
</body>
</html>

This page uses JSP 2.0 Expression Language (EL) to iterate through the list of employees, as highlighted in the last code snippet. We have also hightlighted the taglib directive, at the beginning of the page. This directive will be used to resolve the JSTL core set of libraries that ships with JBoss AS in the server/xxx/deploy/jbossweb.sar/jstl.jar library. (Eclipse does not contain references to this library when you create a web project; you have to add jstl.jar to your build path, otherwise Eclipse will mark it as an error. However, that’s only a visual annoyance because the JBoss Web container has got everything it needs to run JSTL.)

The complete web application is available on the Packtpub website (http://www.packtpub.com) and includes two additional JSPs for entering the employee (newEmployee.jsp) and department (newDepartment.jsp) data, plus one placeholder index.jsp that merely forwards to the Hibernate servlet.

JBoss AS 5 Development

LEAVE A REPLY

Please enter your comment!
Please enter your name here