Servlet JNDI DataSource in Tomcat

14 May 2012 By Nithya Vasudevan 22,567 views 13 Comments
4 Flares Twitter 1 Facebook 2 Google+ 1 4 Flares ×

Environment Used

  • JDK 6 (Java SE 6) (To install JDK – Windows , Ubuntu)
  • Eclipse Indigo IDE for Java EE Developers (3.7.1) (To install Eclipse, refer this page)
  • Apache Tomcat 6.x (To install Tomcat refer this page)
  • MySQL 5.5 (To install MySQL refer this page)
  • MySQL Connector/J 5.1 JAR file
  • Java EE 5 API (Servlet 2.5)
  • Java Database Connectivity (JDBC) API (java.sql.*, javax.sql.*)
  • [Optional] For monitoring and analyzing HTTP headers between the browser and web servers, you can use one of these add-ons of Firefox
    • Live HTTP Headers
    • HttpFox

Setting up development environment

If you are new to developing Servlet with Tomcat and Eclipse, you can read this page before proceeding with this example.

Project Description

  • This example explains how to configure datasource in Apache Tomcat and look it up in Servlet.
  • This application uses one table ‘Employee‘ and displays employee details to the user.
  • We use Eclipse IDE for Java EE Developers and Apache Tomcat to run the Servlet.

What is javax.sql.DataSource?

  • Datasource is a Java object which represents a factory of connections to the physical data source. DataSource is preferred over DriverManager facility.
  • The DataSource interface is implemented by a driver vendor and will typically be registered with a naming service based on the Java Naming and Directory (JNDI) API.
  • DataSource is usually configured and managed by the application server instead of your application. DataSource object is retrieved through a lookup operation using JNDI API and then used to create a Connection object.
  • Advantage of DataSource:
    • A DataSource object has properties that can be modified when necessary. If the data source is moved to a different server, the property for the server can be changed and any code accessing that data source does not need to be changed.

Create Database and table in MySQL

This example uses one table ‘Employee‘ and the description of the table is shown below.

FieldTypeKeyExtra
emp_idintPrimary Keyauto_increment
emp_namevarchar(255)
salarydouble
dept_namevarchar(255)
  • Open command prompt (Windows) or Terminal(Linux) and type
    mysql –u [your-username] –p
    and press enter and type the password.
  • If you are using Windows, you can also use MySQL command line client which will be available in All programs menu.
  • For creating a new database, refer this page. In this example, the database name is ‘exampledb‘.
  • After creating the database type the command “use <database_name>;”
  • For creating a new table, refer this page. In this example, the table name is ‘employee
  • Insert some records in the table. Refer this page for inserting rows using MySQL.

Create Dynamic Web Project

  • Open Eclipse IDE
  • For writing Servlet and JSP, we need to create a new Dynamic Web project. Create this project and name it as “ServletDatasource“.

Download MySQL connector

  • The connector can be downloaded from: http://dev.mysql.com/downloads/connector/j/.
  • This tutorial uses 5.1 version. Unzip the connector to a safe location on your computer which contains MySQL Connector J JAR.
  • Copy the MySQL Connector J JAR and paste it inside project’s ‘lib’ folder.

Configure Context

  • Configure the JNDI DataSource in Tomcat by adding a declaration for your resource to your Context in context.xml.
  • This xml file contains context information and can be placed in one of the location as explained below,
    • In the /conf/context.xml file
    • In the /conf/[enginename]/[hostname]/context.xml.
    • META-INF/context.xml inside the application.

We will place the context.xml file in appliction’s META-INF folder.
Create a new XML file in META-INF folder and copy the following content.

<?xml version="1.0" encoding="UTF-8"?>
 <!-- The contents of this file will be loaded for each web application -->
  <Context crossContext="true">

	<!-- Default set of monitored resources -->
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
	
   <Resource name="jdbc/testDB" auth="Container" 
		type="javax.sql.DataSource"
		maxActive="100" maxIdle="30" maxWait="10000"
		username="<YOUR_DATABASE_USERNAME>" 
		password="<YOUR_DATABASE_PASSWORD>" 
		driverClassName="com.mysql.jdbc.Driver"
		url="jdbc:mysql://localhost/exampledb"/>
</Context>

Fill the username and password for your database and enter your database name in the url string.

Create Servlet

Here, we lookup the JDBC resource and store it in DataSource object. Using this object we create Connection object. We are creating SQL Statement and executing the query and printing the result.

package com.theopentutorials.servlets;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

public class EmployeeServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	public EmployeeServlet() {}

	public void doGet(HttpServletRequest request, 
		HttpServletResponse response) 
		throws ServletException, IOException {
		
		Context envContext = null;
		try {
			envContext = new InitialContext();
			Context initContext  = (Context)envContext.lookup("java:/comp/env");
			DataSource ds = (DataSource)initContext.lookup("jdbc/testDB");
			//DataSource ds = (DataSource)envContext.lookup("java:/comp/env/jdbc/testDB");
			Connection con = ds.getConnection();
						
			Statement stmt = con.createStatement();
			String query = "select * from employee";
			ResultSet rs = stmt.executeQuery(query);
			
			PrintWriter out = response.getWriter();
			response.setContentType("text/html");
			out.print("<center><h1>Employee Details</h1></center>");
			out.print("<html><body><table border=\"1\" cellspacing=10 cellpadding=5>");
			out.print("<th>Employee ID</th>");
			out.print("<th>Employee Name</th>");
			out.print("<th>Salary</th>");
			out.print("<th>Department</th>");
			
			while(rs.next())
			{
				out.print("<tr>");
				out.print("<td>" + rs.getInt("emp_id") + "</td>");
				out.print("<td>" + rs.getString("emp_name") + "</td>");
				out.print("<td>" + rs.getDouble("salary") + "</td>");
				out.print("<td>" + rs.getString("dept_name") + "</td>");
				out.print("</tr>");				
			}
			out.print("</table></body></html>");		
		}  catch (SQLException e) {
			e.printStackTrace();
		} catch (NamingException e) {
			e.printStackTrace();
		}
	}
}
  • There is a global JNDI namespace, and it uses names that are vendor dependent, possibly not portable. Every EJB, JDBC pool, JMS Topic or Queue, you create in the server, has its name in the global JNDI.
  • “java:comp/env” is a utility context and every resource (for example, JDBC, EJB, etc) has its own java:comp/env context populated with resources such as datasources, ejbs, etc.
  • To lookup JDBC resources in that global namespace, we use “jdbc/” as defined in name attribute of element in context.xml. In our case, it is “jdbc/testDB“.

Instead of doing the lookup twice (one for global JNDI namespace and another for JDBC resource) as shown above, we can do a single lookup to the JDBC resource in the namespace as shown below.

Context envContext = new InitialContext(); DataSource ds = (DataSource)envContext.lookup("java:/comp/env/jdbc/testDB");

Configure web.xml

A resource reference is an element in a deployment descriptor that identifies the component’s coded name for the resource. More specifically, the coded name references a connection factory for the resource. In the example in the following section, the resource reference name is “jdbc/testDB“.
Now create a WEB-INF/web.xml for this application.

<?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/javae		
	/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
    <resource-ref>
    <description>DB Connection</description>
    <res-ref-name>jdbc/testDB</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    </resource-ref>
  <servlet>
    <servlet-name>EmployeeServlet</servlet-name>
    <servlet-class>com.theopentutorials.servlets.EmployeeServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>EmployeeServlet</servlet-name>
    <url-pattern>/employee.do</url-pattern>
  </servlet-mapping>
</web-app>

Folder Structure

The complete folder structure of this example is shown below.

Output

Use Ctrl + F11 in Eclipse to run the Servlet. The URL for requesting the Servlet is
http://localhost:8080/ServletDatasource/employee.do

Program control flow

  • Web client (browser) sends requests to Servlet through request URL. Since the request is sent directly to Servlet it is a HTTP GET Request
  • Servlet in doGet() method, looks up (using JNDI) JDBC resource (jdbc/testDB) in global JNDI namespace (java:/comp/env) and stores it in DataSource object. Using this object it creates Connection and executes SQL statement and responds with actual HTML content

The content of HTTP request and response headers can be monitored using browser add-ons such as Live HTTP Headers, HttpFox, etc

Tags: , , , , , , , ,

  • Lalit Jha

    Thanks.

    It helped me a lot. I was looking for configuring JNDI in my application itself rather than in tomcat, to remove server specific configuration.

    Can you suggest how configuring context in META-INF in application will behave on JBoss.

    • http://theopentutorials.com Praveen Macherla

      I don’t think you can do the same way in JBoss. In JBoss you have to define a *-ds.xml to define datasources. Check the JBoss Datasource configuration xml files which may be available in the jboss folder itself.

  • Ruthreshwar

    Hi,
    Thank you. This clearly explained me the JNDI concept. It was very useful. I have a doubt whether driver class will be loaded if we use this JNDI concept?

    • http://theopentutorials.com Nithya Vasudevan

      Yes. The driver class is loaded by the Application Server during start up.

  • Rajesh

    Hi Nithya,
    Thank you very much.. I was struggled lot to make connection with db. Now i got clear idea. Please keep on posting such articles ,this will help a lot for beginners like me.

  • sandeep

    Just wanted to add that if required, we can also configure connection pool in tomcat by using java code:
    connection pool

  • Shaik Abdul Shukoor

    Hai Nithya,
    This is Shukoor.I struggled a lot for this jndi connection as i am a newbie.This explaination is too good and thank you so much for your help.Plz keep on posting these articles as these are very useful for the newbies like me.Thank you once again

  • Pingback: Javaaround.com

  • kadhiresh

    Hi NIVAS (nithiya vasudevan),

    you make me feel free about this concept thanks a lot

  • Kishore Kumar

    am getting name not found exception , when i try to add that context.xml file in confcontext.xml

  • vardhan

    Superb…Thanks dude..Helped me a lot as am new to Web Applications and JNDI.. :)

  • Suresh Kumar

    hi very good tutorial…but i want to know if i want to place context.xml at any other location except above three location….is it can be done….?

  • Divyang Agrawal

    I have put my context file in the /conf/[enginename]/[hostname]/context.xml. But when I am trying to access the JNDI, it says jdbc/dbName is not bound in the context