Thursday, August 12, 2010

Hibernate JPA 2.0 on glassfish v3 with Netbeans IDE setup tutorial

After it took me almost a day to get Hibernate working properly on GF I thought I'd write here how it's done.

In this tutorial I used the following products:
  • NetBeans 6.9.1 - get the JEE version at least
  • Glassfish 3.0.1
  • Mysql
and libraries:
  • Hibernate 3.5.3
  • Slf4j-1.5.8 (you need to get the same version as the API module distributed with hibernate - in this case  slf4j-api-1.5.8.jar)
  • Log4j 1.2.16
  • mysql-connector-java-5.1.11-bin.jar - this is used in GF to connect to MySQL databases.
Make sure you get all of the above before proceding.
From now on I'll assume you have NetBeans, Glassfish & MySql installed and working properly.

Creating a database
Use the following sql dump to create a test database:

/*
SQLyog Ultimate v8.3 
MySQL - 5.0.77 : Database - tutorial
*********************************************************************
*/


/*!40101 SET NAMES utf8 */;

/*!40101 SET SQL_MODE=''*/;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`tutorial` /*!40100 DEFAULT CHARACTER SET latin1 */;

USE `tutorial`;

/*Table structure for table `employee` */

DROP TABLE IF EXISTS `employee`;

CREATE TABLE `employee` (
  `employeeId` int(11) NOT NULL auto_increment,
  `employeeName` varchar(100) default NULL,
  PRIMARY KEY  (`employeeId`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

/*Data for the table `employee` */

insert  into `employee`(`employeeId`,`employeeName`) values (1,'John Doe'),(2,'Frank Bates'),(3,'Alex Smith');

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;


Also, don't forget to create a user with full access to this DB.



Creating a JNDI datasource in GF

  • First, if you haven't already copy the mysql connector (mysql-connector-java-5.1.11-bin.jar) to <glassfish-installation>/glassfish/lib folder
  • Next, we need a connection pool: go to GF Administration->Resources->JDBC->Connection Pool, click New. 
Complete the following:
- Name: tutorialPool
- Resource type: javax.sql.ConnectionPoolDatasource
- Database vendor: MySQL

Click Next. If you are unlucky you'll get a really loooong list of properties. Don't panic! You don't need to complete all :) Just these:

- password: database username password
- ServerName: the hostname (most likely "localhost")
- URL and Url: jdbc:mysql://<hostname>:3306/tutorial (ex: jdbc:mysql://localhost:3306/tutorial)
- User: database username

Click finish. Now click again on "tutorialPool" from the pool list and in the General Tab, click "Ping". If you get "Ping succeded" we're cool!

  • Let's create the JNDI datasource. Go to GF Administration->Resources->JDBC->JDBC Resources, click New; JNDI Name: jdbc/tutorial, Pool Name: tutorialPool. Click OK and you're done!
Log4j
Glassfish v3 and later + log4j seem to have some sort of classloader problem: log4j library is loaded by different classloaders and this causes some kind of conflict if you deploy log4j with your application. The only solution I could find was to copy log4j-1.2.16.jar to <glassfish-installation>/glassfish/domains/domain1/lib. So please do this before proceding.

Creating an Enterprise Project
If you haven't already, start NetBeans and restart Glassfish to make sure it loaded the new classes.

In NB go to File->New Project->Java EE->Enterprise Application. Click Next, choose a location, and name the project "ejbTutorial". Next. Select Glassfish 3.0.1 (if it's not in the list use the "Add" button to install it). Select Java EE  version 6, check "Enable context and dependency injection", create EJB module, create Web APP module. Finish.

Preparing the Hibernate Library
NetBeans has the option of organizing jars into collections called libraries. Let's define one for Hibernate:
go to Tools->Libraries, New Library; name it "Hibernate-3.5.3".

With this library selected add to classpath the following jars:
- <hibernate-dist-folder>/hibernate3.jar
- <hibernate-dist-folder>/lib/required/antlr-2.7.6.jar
- <hibernate-dist-folder>/lib/required/commons-collections-3.1.jar
- <hibernate-dist-folder>/lib/required/dom4j-1.6.1.jar
- <hibernate-dist-folder>/lib/required/javassist-3.9.0.GA.jar
- <hibernate-dist-folder>/lib/required/jta-1.1.jar
- <hibernate-dist-folder>/lib/required/slf4j-api-1.5.8.jar
- <hibernate-dist-folder>/lib/jpa/hibernate-jpa-2.0-api-1.0.0.Final.jar
- <sl4j-dist-folder>/sl4j-log4j12-1.5.8.jar

you can add the sources and javadoc if you wish (for Hibernate it is actually recommended to add the javadoc in order to see it while using the autocomplete feature)

Adding the library(ies) to your project
Right click ejbTutorial-ejb project, select Properties->Libraries. Add the Hibernate-3.5.3 library we created earlier. Also make sure you remove EclispeLink library from Processor tab.
In order for log4j to work we need the configuration file log4j.properties somewhere in our classpath. One good example is found in <hibernate-distribution>/project/etc. Copy this file to ejbTutorial-ejb/src/conf.

One useful logger is SQL. Uncomment the following line from log4j.properties

log4j.logger.org.hibernate.type=debug

At this point we should be done with the project configuration. Let's add some entities & ejbs and test our project.

Creating entities from database
NB has a very nice feature which saves us from a lot of manual labor :). Make sure GF is started.
  • Right click ejbTutorial-ejb project, New->Other->Persistence, select "Entity classes from database" click "Next".
  • In Datasource field select "jdbc/tutorial". If you're asked to confirm the JDBC settings, just click OK. If everything is ok you should see the "employee" table in the left pane. Click on the table name and click add to select it. Click Next.
  • On the next screen enter a package name (let's say "entities"), check Generate named query annotations for persistent fields & Create persistent unit. Click Next and Finnish.
Now we have a nice annotated entity class corresponding to our employee table. Isn't that nice? :)
This wizard created the persistence provider configuration file also (persistence.xml). Let's edit this one:
We can use the design mode to change the persistence provider to Hibernate(JPA 2.0). The resulting xml should look like this:

<?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="ejbTutorial-ejbPU" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>jdbc/tutorial</jta-data-source>
    <properties/>
  </persistence-unit>
</persistence>

Creating the EJBs facade
We can use another wizard to create a session bean which we'll inject in our servlet.

  • Right click ejbTutorial-ejb project, New->Persistence->Session beans for entity classes. Click Next.
  • Select the entities.Employee class and click Add. Next.
  • Name the package ejbs. Create a Remote or Local interface. Click Finnish.
Creating a servlet and testing our application
  • Right click ejbTutorial-web project, New->Web->Servlet
  • Name it EmployeesServlet, package servlets.
  • Check Add information to deployment descriptor. Finnish!
  • Open EmployeesServlet and put the cursor right after the class opening bracket. Go to Source->Insert Code->Call Enterprise Bean, navigate to ejbTutorial-ejb/EmployeeFacade; OK.
  • Edit processRequest method to look like:

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
      response.setContentType("text/html;charset=UTF-8");
      PrintWriter out = response.getWriter();
      try {
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Servlet EmployeesServlet</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>Employee List</h1>");
        List<Employee> employeeList = employeeFacade.findAll();

        for (Employee employee : employeeList) {
          out.println(employee.getEmployeeName() + "<br/>");
        }
        out.println("</body>");
        out.println("</html>");

      } finally {
        out.close();
      }
    } 


  • Deploy the application and go to http://localhost:8080/ejbTutorial-war/EmployeesServlet. If everything was ok you should see a list of names.
Logging and log noise level :)
  • To see any kind of logging from Hibernate you need to set Glassfish Logger Level (Admin Panel->Configuration->Logger Settings)  set to INFO for at least these classes: java.util.logging.ConsoleHandler & javax.enterprise.system
  • You can tweak log4j.properties to hide/display all kind of info about hibernate. The example configuration is well comented so you shouldn't have problems.

9 comments:

  1. Please, where is the link of the hibernate library's jar

    ReplyDelete
  2. Hi, I tried your tutorials since I've actually been looking for something like this. I am having a little problem with the AbstractFacade.java which is automatically created when the Employeefacade is created. Initially I did not know where the problem was until I tried the project again but this time without adding the Hibernate libraries to my project and the error did not appear. The problem actually occurs in the AbstractFacade class as mentioned earlier and this is the error I get:

    cannot find symbol
    symbol: method getCriteriaBuilder()
    location: interface javax.persistence.EntityManager

    I am using netbeans 7.1, Mysql and Glassfish 3.1. The point is I really need to use the Hibernate in my application. Could you please help me out on what to do please. Thanks in advance...eriakort8@gmail.com

    ReplyDelete
    Replies
    1. You have to look for all the jar files having the persistence class, in your project library, and delete them, EXCEPT THOSE YOU NEED, then add them again to your project. I had the same problem and that solved it.

      Delete
  3. Just perfect!! Thank you

    ReplyDelete
  4. Hi How i connect the netbeans 7 and 8 to the mysql
    please explain step by step

    ReplyDelete
  5. Hi
    How i can connect the hibernate with netbeans 7,8 with mysql

    ReplyDelete
  6. https://www.youtube.com/watch?v=4d79Rj-n710

    ReplyDelete