Tutorial on how to set up a Hibernate Tomcat JNDI DataSource.

Hello and welcome to the tutorial on the usage of Hibernate Tomcat JNDI DataSource. Previously, we explored how to utilize Hibernate ORM tool in a standalone java application. Today, we will discover how to incorporate Hibernate with DataSource in the Tomcat servlet container. Implementing Hibernate in a web application is simple. We only need to configure the DataSource properties in the hibernate configuration file. Before anything else, it is necessary to establish a test database and JNDI DataSource in the Tomcat container.

Database setup for Hibernate’s DataSource JNDI example.

I am currently utilizing MySQL for my example. The below script is executed in order to create a basic table and insert certain values into it. The filename of the script is employee.sql.

CREATE TABLE `Employee` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `role` varchar(20) DEFAULT NULL,
  `insert_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8;

INSERT INTO `Employee` (`id`, `name`, `role`, `insert_time`)
VALUES
	(3, 'Pankaj', 'CEO', now());
INSERT INTO `Employee` (`id`, `name`, `role`, `insert_time`)
VALUES
	(14, 'David', 'Developer', now());

The name of the Database schema is TestDB.

How to configure a DataSource for Tomcat using JNDI?

In order to set up the Tomcat container to initialize the DataSource, modifications are required in both the server.xml and context.xml files of Tomcat.

<Resource name="jdbc/MyLocalDB" 
      global="jdbc/MyLocalDB" 
      auth="Container" 
      type="javax.sql.DataSource" 
      driverClassName="com.mysql.jdbc.Driver" 
      url="jdbc:mysql://localhost:3306/TestDB" 
      username="scdev" 
      password="scdev123" 
      
      maxActive="100" 
      maxIdle="20" 
      minIdle="5" 
      maxWait="10000"/>

Include the mentioned resource in the GlobalNamingResources element within the server.xml file, as well as in the context.xml file.

<ResourceLink name="jdbc/MyLocalDB"
              global="jdbc/MyLocalDB"
              auth="Container"
              type="javax.sql.DataSource" />

To enable applications to access the JNDI resource named jdbc/MyLocalDB, you must include the ResourceLink mentioned above in the context.xml file. After restarting the server, there should be no errors in the tomcat server logs. If any configurations are incorrect, such as an incorrect password, the corresponding exception will be displayed in the server log. Additionally, ensure that the MySQL driver jar file is located in the tomcat lib directory. Otherwise, tomcat will be unable to establish a database connection and a ClassNotFoundException will be recorded in the logs. Now that our database and tomcat server JNDI setup is complete, let’s proceed with creating our web application using hibernate.

One possible paraphrase of the given phrase could be: “Dynamic Web Project with a Hibernate DataSource implementation.”

In Eclipse, start by creating a dynamic web project and then setting it up as a Maven project. The structure of our final project will resemble the image provided. Keep in mind that we are utilizing Tomcat-7 for deploying our project and have already incorporated it into the build path. This eliminates the necessity to individually add Servlet API dependencies. Since Tomcat-7 supports Servlet 3 specifications, we will utilize annotations for creating our servlets. If you are unfamiliar with the annotations used in Servlet 3, I recommend reviewing the Servlet Tutorial for Beginners. Now, let’s examine each component individually.

Maven dependencies for Hibernate.

This is the appearance of our ultimate pom.xml file.

<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>HibernateDataSource</groupId>
	<artifactId>HibernateDataSource</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	
	<dependencies>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>4.3.5.Final</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.0.5</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.3</version>
				<configuration>
					<warSourceDirectory>WebContent</warSourceDirectory>
					<failOnMissingWebXml>false</failOnMissingWebXml>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
				</configuration>
			</plugin>
		</plugins>
		<finalName>${project.artifactId}</finalName>
	</build>
</project>

I am currently utilizing the most recent version of Hibernate, which is 4.3.5.Final. The hibernate-core dependency has been added for Hibernate. In addition, we have included the mysql-connector-java dependency because we are using a MySQL database. Although the scope is provided since it is already included in the tomcat container libraries, it is recommended to include it. This way, when someone reviews the project dependencies, it will be evident that we are using a MySQL database.

Configuration of the DataSource in Hibernate.

Below is the appearance of our hibernate configuration file including the datasource, hibernate.cfg.xml.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
		"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
		"https://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.connection.datasource">java:comp/env/jdbc/MyLocalDB</property>
        <property name="hibernate.current_session_context_class">thread</property>
        
        <!-- Mapping with model class containing annotations -->
	<mapping class="com.scdev.servlet.hibernate.model.Employee"/>
    </session-factory>
</hibernate-configuration>

The hibernate.connection.datasource property is utilized to specify the name of the DataSource that Hibernate will use for performing database tasks.

Model Class Example for DataSource in Hibernate

The model class Employee is utilizing annotations, which can be observed in the hibernate configuration file. Here is an example of how our model bean looks: Employee.java.

package com.scdev.servlet.hibernate.model;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

@Entity
@Table(name="Employee", 
	   uniqueConstraints={@UniqueConstraint(columnNames={"ID"})})
public class Employee {

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="ID", nullable=false, unique=true, length=11)
	private int id;
	
	@Column(name="NAME", length=20, nullable=true)
	private String name;
	
	@Column(name="ROLE", length=20, nullable=true)
	private String role;
	
	@Column(name="insert_time", nullable=true)
	private Date insertTime;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getRole() {
		return role;
	}
	public void setRole(String role) {
		this.role = role;
	}
	public Date getInsertTime() {
		return insertTime;
	}
	public void setInsertTime(Date insertTime) {
		this.insertTime = insertTime;
	}
}

If you’re confused about any of the annotations used, you should take a look at the Model bean we used in the Hibernate Beginners Tutorial.

Using Hibernate with a DataSource and Tomcat’s JNDI Servlet Listener.

In order to utilize and handle the Hibernate SessionFactory effectively in the application, which includes both during the usage and destruction of the web application, it is necessary to initialize and destroy the SessionFactory appropriately. Thus, the ideal location to accomplish this is by implementing the HibernateSessionFactoryListener in the ServletContextListener implementation.

package com.scdev.servlet.hibernate.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.jboss.logging.Logger;

@WebListener
public class HibernateSessionFactoryListener implements ServletContextListener {

	public final Logger logger = Logger.getLogger(HibernateSessionFactoryListener.class);
	
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
    	SessionFactory sessionFactory = (SessionFactory) servletContextEvent.getServletContext().getAttribute("SessionFactory");
    	if(sessionFactory != null && !sessionFactory.isClosed()){
    		logger.info("Closing sessionFactory");
    		sessionFactory.close();
    	}
    	logger.info("Released Hibernate sessionFactory resource");
    }

    public void contextInitialized(ServletContextEvent servletContextEvent) {
    	Configuration configuration = new Configuration();
    	configuration.configure("hibernate.cfg.xml");
    	logger.info("Hibernate Configuration created successfully");
    	
    	ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
    	logger.info("ServiceRegistry created successfully");
    	SessionFactory sessionFactory = configuration
				.buildSessionFactory(serviceRegistry);
    	logger.info("SessionFactory created successfully");
    	
    	servletContextEvent.getServletContext().setAttribute("SessionFactory", sessionFactory);
    	logger.info("Hibernate SessionFactory Configured successfully");
    }
	
}

If you are not acquainted with servlet listeners, I recommend reading the Servlet Listener Tutorial.

Example of implementing a servlet using Hibernate with Tomcat and JNDI.

We will create a basic servlet that takes the employee ID as a request parameter and displays the employee’s information from the database. To retrieve the information, we will utilize Hibernate. The servlet will be named GetEmployeeByID.java.

package com.scdev.servlet.hibernate;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.jboss.logging.Logger;

import com.scdev.servlet.hibernate.model.Employee;

@WebServlet("/GetEmployeeByID")
public class GetEmployeeByID extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	public final Logger logger = Logger.getLogger(GetEmployeeByID.class);
       
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		int empId = Integer.parseInt(request.getParameter("empId"));
		logger.info("Request Param empId="+empId);
		
		SessionFactory sessionFactory = (SessionFactory) request.getServletContext().getAttribute("SessionFactory");
		
		Session session = sessionFactory.getCurrentSession();
		Transaction tx = session.beginTransaction();
		Employee emp = (Employee) session.get(Employee.class, empId);
		tx.commit();
		PrintWriter out = response.getWriter();
        response.setContentType("text/html");
        if(emp != null){
        out.print("<html><body><h2>Employee Details</h2>");
        out.print("<table border=\"1\" cellspacing=10 cellpadding=5>");
        out.print("<th>Employee ID</th>");
        out.print("<th>Employee Name</th>");
        out.print("<th>Employee Role</th>");
        
            out.print("<tr>");
            out.print("<td>" + empId + "</td>");
            out.print("<td>" + emp.getName() + "</td>");
            out.print("<td>" + emp.getRole() + "</td>");
            out.print("</tr>");
        out.print("</table></body><br/>");
        
        out.print("</html>");
        }else{
        	out.print("<html><body><h2>No Employee Found with ID="+empId+"</h2></body></html>");
        }
	}

}

I have a straightforward servlet class, where I use the @WebServlet annotation to specify the URI pattern for it.

An application that demonstrates the usage of Hibernate DataSource Tomcat JNDI is being tested.

Our application is now prepared and can be exported as a war file and deployed in the tomcat container. Here are a few screenshots of our application servlet in action. Please note that the empId request parameter is being passed in the request URL query string. Additionally, you will be able to view our application’s generated logs in the server logs.

May 08, 2014 8:14:16 PM org.hibernate.cfg.Configuration configure
INFO: HHH000043: Configuring from resource: hibernate.cfg.xml
May 08, 2014 8:14:16 PM org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: HHH000040: Configuration resource: hibernate.cfg.xml
May 08, 2014 8:14:16 PM org.hibernate.cfg.Configuration doConfigure
INFO: HHH000041: Configured SessionFactory: null
May 08, 2014 8:14:16 PM com.scdev.servlet.hibernate.listener.HibernateSessionFactoryListener contextInitialized
INFO: Hibernate Configuration created successfully
May 08, 2014 8:14:16 PM com.scdev.servlet.hibernate.listener.HibernateSessionFactoryListener contextInitialized
INFO: ServiceRegistry created successfully
May 08, 2014 8:14:16 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
May 08, 2014 8:14:17 PM org.hibernate.engine.jdbc.internal.LobCreatorBuilder useContextualLobCreation
INFO: HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4
May 08, 2014 8:14:17 PM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService
INFO: HHH000399: Using default transaction strategy (direct JDBC transactions)
May 08, 2014 8:14:17 PM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init>
INFO: HHH000397: Using ASTQueryTranslatorFactory
May 08, 2014 8:14:17 PM com.scdev.servlet.hibernate.listener.HibernateSessionFactoryListener contextInitialized
INFO: SessionFactory created successfully
May 08, 2014 8:14:17 PM com.scdev.servlet.hibernate.listener.HibernateSessionFactoryListener contextInitialized
INFO: Hibernate SessionFactory Configured successfully
May 08, 2014 8:14:32 PM com.scdev.servlet.hibernate.GetEmployeeByID doGet
INFO: Request Param empId=3
May 08, 2014 8:15:22 PM com.scdev.servlet.hibernate.GetEmployeeByID doGet
INFO: Request Param empId=3

If you choose to undeploy the application or halt the server, the server logs will display the destruction of the SessionFactory.

May 08, 2014 11:31:16 PM com.scdev.servlet.hibernate.listener.HibernateSessionFactoryListener contextDestroyed
INFO: Closing sessionFactory
May 08, 2014 11:31:16 PM com.scdev.servlet.hibernate.listener.HibernateSessionFactoryListener contextDestroyed
INFO: Released Hibernate sessionFactory resource

That concludes the Hibernate DataSource example for the tomcat container. I hope it is easy to comprehend and execute. Feel free to download the sample project using the link provided below and experiment with it to gain further knowledge.

Please retrieve the Hibernate DataSource Project for downloading.

Leave a Reply 0

Your email address will not be published. Required fields are marked *