Skip to main content

Apache Geronimo JNDI naming and Java resource connection pools, Part 1: Data source connections

Use JNDI to access connection pools for data sources, Java Messaging Services, mail sessions, and URL connections

Dale de los Reyes (dreyes4@hotmail.com), Freelance Writer, Freelance
Dale de los Reyes graduated with a degree in computer science from California Polytechnic State University, San Luis Obispo in 1996. His experience includes application development in J2EE, C++ for Microsoft® Windows®, and COBOL for Mainframes. In his spare time he takes photographs, practices martial arts, and pursues independent projects.

Summary:  Java™ Naming and Directory Interface (JNDI) is an interface to connection pools in the Apache Geronimo application server. Through this interface, developers have access to all Java objects, including Enterprise Java Beans (EJBs). This article series provides concept-rich documentation on how to use JNDI to access connection pools for data sources, Java Messaging Services (JMS), mail sessions, and URL connections.

View more content in this series

Date:  21 Nov 2006
Level:  Intermediate
Activity:  2454 views
Comments:  

Get to know JNDI

JNDI is an application programming interface (API) or library that provides applications with methods to associate names with objects and look up those objects in a directory based on their names. This article, the first in a series, gives you insight into how Geronimo, JNDI, and data source connection pools interrelate, how to build a data source connection, and how to then access it in a simple Geronimo application -- called the Customer Service utility -- using JNDI.

A data source refers to the object or factory that generates connections to the actual source of data (usually a database) within an application. In Java Platform, Enterprise Edition (Java EE), this data source refers to a database connection pool, a group of readily available connections to the database. The reason for creating a data source or database pool is that it increases application performance, because opening even a single connection is a CPU-intensive operation.

The Customer Service utility (available in the Download section of this article) is a simple Web application that lets you save basic customer information into a database. You'll build it using Apache Ant 1.6.5 and Java 1.4.2_10, deploy it on Geronimo 1.1 with Tomcat, and use the Apache Derby database bundled with Geronimo (see the Resources section at the end of this article for a link to download Geronimo). The next section covers how to create this database and data source using the Geronimo console.


Set up Geronimo

The Geronimo console provides a user-friendly way to manage Java EE components. After Geronimo has started, you can access it at http://localhost:8080/console. The default user name and password are system and manager, respectively.

To get started:

  1. Click the DB Manager link at the bottom left side of the Console Navigation panel. This presents the Derby database manager.
  2. Create the customer service database by typing CustomerServiceDatabase in the Create DB field, then click the Create button.
  3. Create the database table by selecting CustomerServiceDatabase in the Use DB pull-down menu.
  4. Then paste the contents of the SQL script shown in Listing 1 into the table, and click the Run SQL button. Note that the SQL script in Listing 1 is included with the source code.

Listing 1. SQL script
CustomerService-Part1.sql
create table customers (
   customerid varchar(10) primary key,
   fullname varchar(30),
   emailaddress varchar(30),
   interests varchar(100)
);
insert into customers values ('A100','John Doe10','Doe10@work.com','Java,Open Source, 
Computer Graphics');
insert into customers values ('b100','Jane Doe20','Doe20@home.net','Budget Travel, New 
Zealand, Martial Arts');

The customer service database should now be created in Derby. It has only one table, Customers, with only two entries in it. Figure 1 shows what the properly initialized table looks like after clicking the Application link, followed by the View Contents link.


Figure 1. Customer service database after initialization
customer service database after initialization

Next you create a connection pool for the recently created database:

  1. Click the Database Pools link in the Console Navigation panel on the left.
  2. Then click the Using the Geronimo database pool wizard link, and complete the following steps:
    • On the page titled Step 1: Select Name and Database, enter CustomerServicePool for the Name of Database Pool field. Select Derby embedded from the Database Type pull-down menu, and click Next.
    • On the page titled Step 2: Select Driver, JAR, Parameters, select org.apache.derby/derby/10.1.1.0/jar from the Driver JAR pull-down menu. In the DB User Name field, type app. Leave the DB Password blank. Enter CustomerServiceDatabase in the Database field, and click Next.
    • On the page titled Step 3: Final Pool Configuration, make sure the Driver Status field says Loaded Successfully. The Connection Pool Parameters can be left blank. Click the Test Connection button to proceed to the next page.
    • On the page titled Step 4: Test Connection, the Test Result field should say Connected to Apache Derby 10.1.1.0. Click Deploy. Figure 2 shows the new connection pool after it has been created.

Figure 2. Newly created CustomerServicePool data source
Newly created CustomerServicePool data source

By now the database (CustomerServiceDatabase) and the data source (CustomerServicePool) should be configured and deployed on Geronimo and ready to use. Next, take a look at how to declare these objects in JNDI.


Creating Geronimo deployment descriptors

Any component deployed to Geronimo needs deployment descriptors. Even the CustomerServicePool previously created uses a descriptor file as evidenced by the Show Plan button on the page titled Step 4: Test Connection. The most common components that application developers will create are EJBs (JAR files), Web archives (WAR files), and application archives (EAR files). The Customer Service utility makes use of each of these component types.

Configuring the descriptor files is important, because it's the mechanism that allows these components to be used in Geronimo. It's also how JNDI names get associated with a given Java object. Components deployed in Geronimo typically have two deployment files: the standard Java deployment descriptor and the Geronimo-specific deployment plan. The primary resource is the CustomerServiceDatabase. The data source, CustomerServicePool, provides a number of connections to access this database. To store customer information, the user first accesses the Web interface and types information in the fields. Those fields are passed to a Java bean that references a session bean. This session bean acts on the customer data by referencing an entity bean to perform the basic database operations. The entity bean is the Java object representation of one row in the customer's table, and it's the component that references the CustomerServicePool to access the database. Listing 2 contains the standard Java deployment descriptor for this entity bean.


Listing 2. Partial listing of CustomerEJB-ejb.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" 
"http://java.sun.com/dtd/ejb-jar_2_0.dtd">

<ejb-jar>
   <enterprise-beans>
      <entity>
         <ejb-name>CustomerEntityBean</ejb-name>
         <home>com.service.customer.ejb.CustomerHome</home>
         <remote>com.service.customer.ejb.Customer</remote>
         <ejb-class>com.service.customer.ejb.CustomerEntityBean</ejb-class>
         <persistence-type>Container</persistence-type>
         <resource-ref>
            <res-ref-name>jdbc/CustomerServiceDataSource</res-ref-name>
            <res-type>javax.sql.DataSource</res-type>
            <res-auth>Container</res-auth>
         </resource-ref>
      </entity>
   </enterprise-beans>
</ejb-jar>

There are four tags of interest here. The <ejb-name> tag specifies the name of this entity bean. The <persistence-type> tag indicates this entity bean uses container-managed persistence (CMP). This means all database operations are handled automatically by Geronimo. The <res-ref-name> tag specifies the JNDI name that will be used when performing a lookup. The implementation of an entity bean using CMP is pretty minimal, and no JNDI lookup is explicitly coded. The declaration in the <res-ref-name> tag is still required. Finally, the <res-type> tag indicates what object type is associated with the JNDI name. Listing 3 covers the Geronimo-specific companion file for this entity bean.


Listing 3. Partial listing of CustomerEJB-openejb.xml
<?xml version="1.0" encoding="UTF-8"?>

<openejb-jar xmlns="http://www.openejb.org/xml/ns/openejb-jar-2.1"
          xmlns:naming="http://geronimo.apache.org/xml/ns/naming-1.1">
   <dep:environment xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.1">
      <dep:moduleId>
         <dep:groupId>default</dep:groupId>
         <dep:artifactId>CustomerEJB</dep:artifactId>
         <dep:version>1.0</dep:version>
         <dep:type>jar</dep:type>
      </dep:moduleId>

      <dep:dependencies>
         <dep:dependency>
            <dep:groupId>console.dbpool</dep:groupId>
            <dep:artifactId>CustomerServicePool</dep:artifactId>
            <dep:version>1.0</dep:version>
            <dep:type>rar</dep:type>
         </dep:dependency>
      </dep:dependencies>

      <dep:hidden-classes/>
      <dep:non-overridable-classes/>
   </dep:environment>

   <cmp-connection-factory>
      <resource-link>CustomerServicePool</resource-link>
   </cmp-connection-factory>

   <enterprise-beans>
      <entity>
         <ejb-name>CustomerEntityBean</ejb-name>
         <jndi-name>CustomerRemoteEntity</jndi-name>

         <resource-ref>
            <ref-name>jdbc/CustomerServiceDataSource</ref-name>
            <resource-link>CustomerServicePool</resource-link>
         </resource-ref>
      </entity>
   </enterprise-beans>
</openejb-jar>

The value of <ejb-name> must correspond to the value of <ejb-name> in the companion descriptor file. The <jndi-name> tag specifies the JNDI name that only application clients will use. These clients aren't bundled with the application archive (.ear) file. The <ref-name> tag corresponds to the JNDI name in the <res-ref-name> tag of Listing 2. The <resource-link> tag associates the CustomerServicePool created in the Geronimo console to the name in <ref-name>.

It's worth mentioning that the format of Geronimo-specific deployment descriptors has changed with version 1.1. The previous version used configID and parentID attributes in the header to specify an object's ID and dependency. This format has now been replaced with a moduleId structure based on the Apache Maven-style naming convention. It consists of four elements in the following pattern: groupID/artifactID/version/type. This naming pattern corresponds to the directory structure in the geronimo-1.1/repository.

The <dep:XXX> tags in the descriptor file above correspond to this convention. For example, the dependency, CustomerServicePool, is located in the Geronimo repository at console/dbpool/CustomerServicePool/1.0. This new convention means that applications deployed on Geronimo 1.0 will have to be updated. The 1.1 user manual has a section on how to do this. However, future releases of Geronimo will support this convention, so applications deployed on 1.1 should deploy on those newer releases without any update to the descriptors.

Now let's continue with the configuration of the session bean in Listing 4.


Listing 4. Partial listing of ProcessCustomerEJB-ejb.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 
2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd">

<ejb-jar>
   <enterprise-beans>
      <session>
         <ejb-name>ProcessCustomerSessionBean</ejb-name>
         <home>com.service.customer.ejb.ProcessCustomerHome</home>
         <remote>com.service.customer.ejb.ProcessCustomer</remote>
         
<ejb-class>com.service.customer.ejb.ProcessCustomerSessionBean</ejb-class>
         <session-type>Stateless</session-type>
         <transaction-type>Container</transaction-type>

         <ejb-ref>
            <ejb-ref-name>ejb/CustomerEntityBean</ejb-ref-name>
            <ejb-ref-type>Entity</ejb-ref-type>
            <home>com.service.customer.ejb.CustomerHome</home>
            <remote>com.service.customer.ejb.Customer</remote>
         </ejb-ref>
      </session>
   </enterprise-beans>
</ejb-jar>

The <ejb-name> tag specifies the name of the session bean, ProcessCustomerSessionBean. The <ejb-ref-name> tag specifies the JNDI name that components within the application will use. In this case, the session bean will perform a lookup on the entity bean. The corresponding Geronimo-specific plan is in Listing 5.


Listing 5. Listing of ProcessCustomerEJB-openejb.xml
<?xml version="1.0" encoding="UTF-8"?>

<openejb-jar xmlns="http://www.openejb.org/xml/ns/openejb-jar-2.1"
        xmlns:naming="http://geronimo.apache.org/xml/ns/naming-1.1"
        xmlns:security="http://geronimo.apache.org/xml/ns/security-1.1"
        xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.1">
   <dep:environment>
      <dep:moduleId>
         <dep:groupId>default</dep:groupId>
         <dep:artifactId>ProcessCustomerSessionBean</dep:artifactId>
         <dep:version>1.0</dep:version>
         <dep:type>jar</dep:type>
      </dep:moduleId>

      <dep:dependencies/>
      <dep:hidden-classes/>
      <dep:non-overridable-classes/>
   </dep:environment>

   <enterprise-beans>
      <session>
         <ejb-name>ProcessCustomerSessionBean</ejb-name>
         <jndi-name>ProcessCustomerRemoteSessionBean</jndi-name>

         <ejb-ref>
            <ref-name>ejb/CustomerEntityBean</ref-name>
            <ejb-link>CustomerEntityBean</ejb-link>
         </ejb-ref>
      </session>
   </enterprise-beans>
</openejb-jar>

The <dep:moduleId> specifies the full name of this component. Like the entity bean, the <ejb-name> tag must correspond to the <ejb-name> in the standard descriptor of the previous listing. And the <jndi-name> tag contains the JNDI name used only by application clients. Finally, the <ejb-ref> tag associates the JNDI name to the EJB's name. The Web archive is next, and it references the session bean from a Java bean. Its standard deployment descriptor is shown in Listing 6.


Listing 6. Partial listing of web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
         version="2.4">

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <ejb-ref>
    <ejb-ref-name>ejb/ProcessCustomerSessionBean</ejb-ref-name>
    <ejb-ref-type>Session</ejb-ref-type>
    <home>com.service.customer.ejb.ProcessCustomerHome</home>
    <remote>com.service.customer.ejb.ProcessCustomer</remote>
  </ejb-ref>
</web-app>

The main item of interest to note is the <ejb-ref> tag. It shows how to declare the JNDI name that will be used to look up the session bean.

The Geronimo-specific plan for the Web archive is fairly straightforward. It defines the Web archive's full name and specifies the context root where the application can be found when accessed from a Web browser (see Listing 7).


Listing 7. Listing of geronimo-web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://geronimo.apache.org/xml/ns/j2ee/web-1.1"
         xmlns:naming="http://geronimo.apache.org/xml/ns/naming-1.1">
   <dep:environment xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.1">
      <dep:moduleId>
         <dep:groupId>default</dep:groupId>
         <dep:artifactId>CustomerService-web</dep:artifactId>
         <dep:version>1.0</dep:version>
         <dep:type>war</dep:type>
      </dep:moduleId>

      <dep:dependencies/>
      <dep:hidden-classes/>
      <dep:non-overridable-classes/>
   </dep:environment>

   <context-root>/service</context-root>
</web-app>

The Customer Service utility is deployed as an .ear file. Consequently, it has two descriptor files, application.xml and geronimo-application.xml. However, neither of these files contains any JNDI declarations, so they are not covered here. That's it for declaring JNDI names and associating them to EJB components! The next section covers how to look up these objects in code.


The Customer Service utility

The Customer Service utility is almost ready. The next step is to call these EJBs using JNDI to access the database. The complete JNDI strings follow the naming convention, as shown in Listing 8.


Listing 8. Listing of JNDI names in customer.properties
# Specify JNDI names here
jndi.customer.ejb=java:/comp/env/ejb/CustomerEntityBean
jndi.process.ejb=java:/comp/env/ejb/ProcessCustomerSessionBean

The names declared earlier in the <ejb-ref-name> tag of the EJB descriptors are now listed in their full JNDI name context. The recommended naming convention says that objects should be prefaced with their corresponding domain. Hence, the entity bean and session bean are both prefaced with ejb/. The CustomerServiceDataSource declared in the entity bean's descriptor file uses jdbc/, because it's database related. The code in Listing 9 shows how to perform a JNDI lookup of CustomerEntityBean from within a session bean using the full name.


Listing 9. Partial listing of ProcessCustomerSessionBean.java
package com.service.customer.ejb;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

public class ProcessCustomerSessionBean implements SessionBean
{
   private ResourceBundle    bundle = null;
   private SessionContext    context = null;
   private CustomerHome      customerHome = null;
   private String            JNDI_CUSTOMER_EJB = null;

   // Create method(s)
   public void ejbCreate()
      throws CreateException
   {
      try
      {
         doJNDILookups();
      } // end try

      catch (Exception e)
      {
         throw new CreateException("ejbCreate: " + e.getMessage());
      } // end catch
   } // end ejbCreate

   // Support methods
   private void doJNDILookups()
      throws NamingException, ClassCastException
   {
      Object objref = null;
      InitialContext initial = null;

      bundle = ResourceBundle.getBundle("customer", Locale.getDefault(), 
ProcessCustomerSessionBean.class.getClassLoader());
      JNDI_CUSTOMER_EJB = bundle.getString("jndi.customer.ejb");

      initial = new InitialContext();
      objref = initial.lookup(JNDI_CUSTOMER_EJB);
      customerHome = (CustomerHome)PortableRemoteObject.narrow(objref, 
CustomerHome.class);
      System.out.println("looking up: " + JNDI_CUSTOMER_EJB);
   } // end doJNDILookups
} // end ProcessCustomerSessionBean

The main item of interest in Listing 9 is the doJNDILookups method. First, the complete JNDI name is retrieved from the customer.properties file. Next, an InitialContext is created, and a lookup is performed on the JNDI name. Finally, the narrow method checks to make sure the retrieved object from JNDI can be cast into the intended object type, CustomerHome. Listing 10 shows how the lookup is performed from a Java bean.


Listing 10. Partial listing of CustomerServiceJavaBean.java
public class CustomerServiceJavaBean
{
   private ProcessCustomerHome processHome = null;
   private ResourceBundle      bundle = null;
   private String              JNDI_PROCESS_EJB = null;

   public CustomerServiceJavaBean()
   {
      InitialContext initial = null;
      Object objref = null;

      bundle = ResourceBundle.getBundle("customer", Locale.getDefault(), 
CustomerServiceJavaBean.class.getClassLoader());
      JNDI_PROCESS_EJB = bundle.getString("jndi.process.ejb");

      try
      {
         initial = new InitialContext();
         objref = initial.lookup(JNDI_PROCESS_EJB);
         processHome = (ProcessCustomerHome)PortableRemoteObject.narrow(objref, 
ProcessCustomerHome.class);
         System.out.println("looking up: " + JNDI_PROCESS_EJB);
      } // end try

      catch (Exception e)
      {
         e.printStackTrace();
      } // end catch
   } // end CustomerServiceJavaBean
} // end CustomerServiceJavaBean

The steps for retrieving ProcessCustomerSessionBean are similar to the entity bean lookup. Only this time, the JNDI name is different, and the ProcessCustomerHome class is used to confirm the retrieved object from JNDI.

The Customer Service utility is now ready to deploy on Geronimo:

  1. Modify the CustomerService/resources/build.properties file, and make sure the directory locations are properly defined.
  2. Next, open a console and change directories to the location of CustomerService/build.xml. Then type ant. This will build and deploy the application, which can be accessed at http://localhost:8080/service.

Figure 3 shows what the data entry page looks like.


Figure 3. Data entry page for Customer Service utility
Data entry page for Customer Service utility

At this point, only the most basic customer information is stored in the database.

There is one final issue to note. Developers may encounter an SQL Exception error when trying to access the Customer Service utility after having accessed the Derby database from Geronimo's console, or vice versa. Rebooting Geronimo will correct the error for one, but then generate the exception again when the database is accessed by the other. The issue seems related to a documented condition in the Geronimo 1.1 User Manual in the 1.0 migration section at the end (see Resources for a link).

The condition is caused when a database connection pool has a dependency on the Derby (org.apache.derby/derby/10.1.1.0/jar) or Derbynet (org.apache.derby/derbynet/10.1.1.0/jar) drivers. Keeping the dependency as such will load a second copy of Derby in a second class loader causing the SQL Exception. The Geronimo database pool wizard will create a plan that has such a dependency when Derby embedded is used. The alternative is to cut and paste the generated plan and deploy it as part of the application archive. In this manner, the database pool becomes specific only to the Customer Service utility. The existing descriptor plans will need modification, and the subsequent listings will highlight those changes starting with Listing 11.


Listing 11. Modified CustomerServicePool-alt.xml

<dep:moduleId>
    <dep:groupId>default</dep:groupId>
    <dep:artifactId>CustomerServicePool</dep:artifactId>
    <dep:version>1.0</dep:version>
    <dep:type>rar</dep:type>
</dep:moduleId>

The generated plan is obtained from the database pool wizard. On the page titled Step 4: Test Connection, click the Show Plan button instead of Deploy. After the generated plan is cut and pasted and saved into another file, such as CustomerServicePool-alt.xml, the <groupId> tag must be modified to match the contents of Listing 11, because the CustomerServicePool will now be deployed as part of the application. Hence, this <groupId> tag will correspond to the <groupId> tag in geronimo-application.xml, which is partially displayed in Listing 12.


Listing 12. Alternative geronimo-application.xml

<module>
    <connector>tranql-connector-1.2.rar</connector>
    <alt-dd>CustomerServicePool-alt.xml</alt-dd>
</module>

The geronimo-application.xml descriptor will need the additional tag from Listing 12. This is also true for the standard application.xml shown in Listing 13.


Listing 13. Alternative application.xml

<module>
    <connector>tranql-connector-1.2.rar</connector>
</module>

This additional tag is also needed in application.xml for the alternative deployment. Listing 14 shows the code change needed in the descriptor, CustomerEJB-openejb.xml.


Listing 14. Modified CustomerEJB-openejb.xml
<dep:dependencies/>

The existing <dependencies> tag on CustomerServicePool can be replaced with the code shown in Listing 14.

Finally, the tranql driver and the modified database pool plan need to be bundled at the same level as the JAR and WAR files within the application archive (.ear file). The tranql driver comes bundled with Geronimo and is located in the repository folder C.


Summary

Hopefully this first installment in the series has helped you understand one of the most common JNDI connections, accessing a database pool from an EJB. You learned how the Geronimo console is used to initialize the database and configure a database connection pool. Finally, the Customer Service utility showed you how this connection pool can be accessed within the code. Stay tuned for the next article in the series, which discusses JNDI connections to a JMS resource and shows you how to use them to enhance the example application.



Download

DescriptionNameSizeDownload method
Part 1 source codeCustomerService-part1.zip57KB HTTP

Information about download methods


Resources

Learn

Get products and technologies

Discuss

About the author

Dale de los Reyes graduated with a degree in computer science from California Polytechnic State University, San Luis Obispo in 1996. His experience includes application development in J2EE, C++ for Microsoft® Windows®, and COBOL for Mainframes. In his spare time he takes photographs, practices martial arts, and pursues independent projects.

Comments



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Open source, Java technology, WebSphere
ArticleID=175237
ArticleTitle=Apache Geronimo JNDI naming and Java resource connection pools, Part 1: Data source connections
publish-date=11212006
author1-email=dreyes4@hotmail.com
author1-email-cc=troy@backstopmedia.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers