Developing Applications with JBoss and Hibernate: Part 2

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.

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.

Packaging and deploying the application

Y our enterprise application is complete. We need to package it in an EAR archive so that the web application will be able to interact with the Hibernate POJOs. Create a new Enterprise Application project from the Java EE folder. You will be prompted to select the projects that will be included as modules. Select both the HibernateProject and the web application HibernateWeb.

If you have ever worked with JBoss AS and Hibernate, then you might argue that right now something is missing. You’re indeed right. Before release 5.0 of the JBoss Application Server, Hibernate classes and mapping files had to be packaged in a JBoss AS custom .har archive. The suffix was determinant, as JBoss AS was able to classify the package as a Hibernate resource.

As HAR archives are not Java EE standard components, you have to declare it in a JBoss AS-specific configuration file named jboss-app.xml that sits in the META-INF folder of our EAR.

<!DOCTYPE jboss-app PUBLIC "-//JBoss//DTD J2EE Application 1.5//EN"
"http://www.jboss.org/j2ee/dtd/jboss-app_5_0.dtd">
<jboss-app>
<module>
<har>HibernateApplication.har</har>
</module>
</jboss-app>

While this approach is still advisable if you want to grant backward compatibility to your applications, with release 5.0 of the Application Server you now have a handy quicker solution. As the new VFS of JBoss AS is able to detect the nature of your application by scanning deployment descriptors, it’s enough to pack your Hibernate application in a plain Java ARchive (JAR). JBoss AS will discover the .hbm.xml mapping files and look for the corresponding Java classes. If successful, the package will be deployed as a Hibernate application straightaway.

The corollary of this theorem is that you can leave out, as well, the JBoss AS configuration file jboss-app.xml, which is not necessary any more. The only update required is to your application.xml, where your Hibernate application is declared as a Java module in order to make it available to other enterprise modules.

<application>
<module>
<web>
<web-uri>HibernateWeb.war</web-uri>
<context-root>HibernateWeb</context-root>
</web>
</module>
<module>
<java>HibernateProject.jar</java>
</module>
</application>

This is how your Enterprise ARchive should look like before deploying it:

Now deploy your application in the usual way, by adding the project to JBoss AS projects and then choosing Full Publish. The application server will then produce a few log pages; if the binding of classes is successful, you will find the following among your logs:

16:46:18,949 INFO [HbmBinder] Mapping class: com.packtpub.hibernate.Employee ->employee
16:46:19,261 INFO [HbmBinder] Mapping class: com.packtpub.hibernate.Department -> department
16:46:19,277 INFO [HbmBinder] Mapping collection: com.packtpub.hibernate.Department.employees -> employee

In order to test your application, simply recall your JSP default page, using the HibernateWeb context. In our example:

http://localhost:8080/HibernateWeb/

Using the wizard to generate EJB 3

Hibernate tool capabilities are not limited to Hibernate programming. By using the reverse engineering option, you can also generate EJB 3.0 classes in a matter of seconds. Recall the Reverse Engineering Configuration:

If you Check the Generate EJB3 annotations checkbox along with Domain code, then the outcome of your reverse engineering process would be simple Java classes with entity annotations. That’s a huge saving of time, especially if your database schema is rather complex. You can still adjust your entity beans to your needs once they are generated.

Hibernate and EJB: Friends or opponents?

At this stage, you might wonder when it’s more appropriate to use EJB from your projects and when it’s better to stay on the Hibernate framework.

The premise of this debate is that EJB and Hibernate are not fully comparable because they are semantically different. EJBs live in a container, which provides services, such as transactions, concurrent access control, security, instance pooling, and others. On the other hand, Hibernate is classified as an object-relational mapping tool and it is independent from a server container.

So, if comparing EJB and Hibernate is technically a mistake, you can actually compare the Java Persistence API and Hibernate, which are, in some ways, two antagonist technologies. The most important factor, which is in favor of JPA, is that it is a standard. Using industry-standard components allows the business vastly more flexibility when it’s necessary to change its business model, to reorchestrate itself, and to collaborate dynamically.

Technically speaking, it is also important to stress that an EJB-centric approach is the appropriate implementation technology for two types of applications:

  • Applications that use distributed transactions initiated by remote clients
  • Applications that are heavily message-oriented and need message-driven beans

On the other hand, Hibernate framework has reached a vast community of developers and it offers the benefit of peacefully coexisting in various deployment environments, from application servers to standalone applications.

At the end of the day, the choice between the two technologies might be to preserve your well-tested applications backed by Hibernate Persistence and to definitely consider switching to JPA when you are designing a new project from the ground up. What about using them together instead?

Using Hibernate with EJB

A plausible scenario is that some time ago, you designed the persistence layer of your application with Hibernate. Now you need to expose some functionalities of your application through RMI or Web Services.

The good news is that persistent classes that are mapped using Hibernate *.hbm.xml files are supported by JBoss AS EJB 3 implementation. The EJB3 deployer will search the archive for any .hbm.xml files and add them to the definition of the underlying Hibernate SessionFactory. Let’s see how you can leverage Hibernate objects from the EJB environment.

Injecting key Hibernate objects

If you have been through the Hibernate web application carefully, you might advocate that it is not a pure MVC application, as we are accessing the persistence layer from within the servlet.

This approach can be useful for a learner who wants an easy-to-catch example of Hibernate. However, you can create a clean separation of roles between the controller and the model tier, also by introducing an EJB as intermediary.

From inside your Hibernate project, add another stateless session bean named com.packtpub.hibernate.HibernateDAOBean implementing a local interface com.packtpub.hibernate.HibernateDAOLocal.

Following is a code snippet of the bean implementing the saveEmployee method:

@Stateless
@LocalBinding(jndiBinding="HibernateDAO/local")
public class HibernateDAOBean implements HibernateDAO {
@PersistenceUnit(unitName="hibernateUnit") [1]
SessionFactory factory;
public void saveEmployee(String name,String salary,String
departmentId) {
Session hsession=null;
try {
hsession = factory.openSession();
Query query = hsession.createQuery("from Department d where
d.departmentId = :departmentId");
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);
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new EJBException(e.getMessage());
}
finally {
if (hsession.isOpen())
hsession.close();
}
}

The most interesting point in this example is that you have injected the Hibernate SessionFactory in your bean by means of the persistence unit named hibernateUnit. Therefore, you have to equip your application with a JPA persistence.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.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_1_0.xsd">
<persistence-unit name="hibernateUnit" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/MySqlDS</jta-data-source>
<properties>
<property name="hibernate.dialect"
value="org.hibernate.dialect.MySQLDialect"/>
</properties>
</persistence-unit>
</persistence>

We leave as exercise to the reader to complete the EJB with all other methods. On the web tier, you will do a clear cut of all the persistence stuff, just taking care to invoke the EJB with the parameters collected from the request. Look how simple and effective your servlet method saveEmployee has become:

@EJB(mappedName = "HibernateDAO/local")
HibernateDAO hibernateDAO;
private String saveEmployee(HttpServletRequest request) {
Session hsession=null;
String name=request.getParameter("name");
String salary=request.getParameter("salary");
String departmentId=request.getParameter("departmentId");
try {
hibernateDAO.saveEmployee(name,salary,departmentId);
}
catch (Exception e) {
e.printStackTrace();
}
return employeeList(request);
}

A snapshot of the complete Hibernate EJB-driven project follows here:

As you can see, using Hibernate API works much the same way as the EntityManager interface. This example reveals another difference with our former web application. Here the EJB must not attempt to manage the life cycle of the Hibernate session; this is done internally by the EJB container, which is in charge of commiting or rolling back the transaction, following the EJB container’s policies.

Summary

Hibernate is a flexible framework that can be used in any Java application environment. In our excursus, we have showed how to develop a sample application that is geared toward a managed environment. In the last two sections of this article, we have compared the Hibernate framework with the JPA persistence standard, showing how the two technologies can be coupled in a single application.

Popularity: 2% [?]

Related posts:

  1. Developing Applications with JBoss and Hibernate: Part 1 In this article, by Francesco Marchioni, we will introduce Hibernate,...
  2. Как да присвоите съдаржание от файл с променлива от Java Ще използваме DataInputStream за да преобразуваме , съдържанието в байтове....

Related posts brought to you by Yet Another Related Posts Plugin.

You can leave a response, or trackback from your own site.

16 Responses to “Developing Applications with JBoss and Hibernate: Part 2”

  1. Ceallach F казва:

    Hi – very great website you have created. I enjoyed reading this posting. I did want to issue a remark to tell you that the design of this site is very aesthetically delightful. I used to be a graphic designer, now I am a copy editor for a merchandising firm. I have always enjoyed playing with information processing systems and am attempting to learn computer code in my spare time (which there is never enough of lol).

  2. admin казва:

    This site was only for bulgaria , but now it will have more and more english publications , so you and other players you can learn . It will have forum to , to comment and ask questions .

  3. Andrew Pelt казва:

    There is so much information here! I’m trying to remember all of it so I can put it to work.

  4. affiliate millionaire казва:

    Hi,I’m taking some time to write you a comment. I hope you don’t mind I’ve bookmarked your page, your post is genuinely helpful for me. Nathaly x

  5. home mortgages казва:

    Comfortabl y, the article is really the best on this laudable topic. I concur with your conclusions and will thirstily look forward to your incoming updates. Just saying thanks will not just be sufficient, for the extraordinary lucidity in your writing. I will at once grab your rss feed to stay abreast of any updates. Admirable work and much success in your business efforts!

  6. kevin казва:

    Comfortabl y, the post is in reality the sweetest on this deserving topic. I harmonise with your conclusions and will eagerly look forward to your incoming updates. Just saying thanks will not just be sufficient, for the fantasti c clarity in your writing. I will instantly grab your rss feed to stay informed of any updates. Genuine work and much success in your business enterprize!

  7. Luffie казва:

    I am running Windows XP SP3 and am connected to the internet through a Comcast modem and Belkin router. It says my internet connection is excellent and this problem does not occur on the other laptop in the house. I have tried many things and there are no viruses or firewall problems. I decided to run IE’s diagnostic thing. It said there was some problem, that I was told could be solved by using Winsock XP Fix (because whenever IE tried to fix it, it claimed it fixed it and to restart my computer, but then when I would restart, the problem would still occur and be detected). After using Winsock XP Fix, the problem stopped for a few hours, but is now back again and this program does not solve it anymore. Any help is appreciated, thank you. santoramaa

  8. Martin J. Nobleman казва:

    Hey, I like your site. I was wondering if you would do a review post of my product at http://www.publicdomainpayday.com

  9. Jermaine Sugimoto казва:

    We are sure do know NOW how to do it,, very informative.i have bookmarked your site and will return again

  10. home equity казва:

    Substantially, the post is really the freshest on this notable topic. I concur with your conclusions and will thirstily look forward to your next updates. Saying thanks will not just be enough, for the exceptional clarity in your writing. I will immediately grab your rss feed to stay informed of any updates. Genuine work and much success in your business efforts!

  11. home equity loans казва:

    Comfortabl y, the article is really the greatest on this valuable topic. I fit in with your conclusions and will eagerly look forward to your upcoming updates. Just saying thanks will not just be adequate, for the exceptional lucidity in your writing. I will at once grab your rss feed to stay informed of any updates. Solid work and much success in your business efforts!

  12. Laura казва:

    Comfortabl y, the article is really the sweetest on this deserving topic. I agree with your conclusions and will eagerly look forward to your approaching updates. Just saying thanks will not just be enough, for the wonderful lucidity in your writing. I will at once grab your rss feed to stay abreast of any updates. Gratifying work and much success in your business endeavors!

  13. home equity loans казва:

    Considerably, the article is in reality the greatest on this laudable topic. I concur with your conclusions and will eagerly look forward to your incoming updates. Saying thanks will not just be enough, for the exceptional clarity in your writing. I will immediately grab your rss feed to stay privy of any updates. De lightful work and much success in your business enterprize!

  14. Forex Critics казва:

    The Foreign Exchange (Forex) is a wonderful market to trade in, but it’s very easy to lose a bundle if you are just starting out. For those considering taking the plunge for the first time, my advice is to seek as much information as possible, such as at this website, or one of the more popular free forex information sites such as http://www.forex-critics.com/blog — Good luck.

  15. Seema Quintania казва:

    Really Good Articles/posts that you have on this site. Thanks

  16. to domain name казва:

    hi guys…

    hi guysI would like to thank you for the efforts you have made in writing this article. I am hoping the same best work from you in the future as well and i have start my own blog now, , thanks for your effort…

Leave a Reply

Задвижван с помощта на WordPress | Compare Cell Phone Plans at iCellPhonePlans.com | Thanks to Cheap Palm Pixi, Bromoney and Wordpress Themes