caucho
Resin
FAQ
Reference Guide
Demo
Tutorial

Getting Started
Configuration
IDE
Topics
JSP
XML/XSLT

Basic Config
Directory
Servlets
Filters
Resources
Databases
Messaging
Security Config
Log Config
Taglib Config
Misc resin.conf
Host resin.conf
Port resin.conf
App resin.conf
Summary
Glossary
Index
 JNDI: Resource Configuration

Filters
Configuration
Databases

  1. web-apps and JNDI Contexts
  2. JNDI Names
  3. JNDI API
  4. JNDI configuration
    1. resource-ref
    2. env-entry
  5. Known JNDI Object Factories
    1. javax.sql.DataSource
    2. javax.sql.XADataSource
    3. javax.mail.Session
  6. Custom Factories

Applications can store factory objects and configuration variables in a global naming tree using the JNDI API. JNDI, the Java Naming and Directory Interface, provides a global memory tree to store and lookup configuration objects. JNDI will typically contain configured Factory objects.

JNDI lets applications cleanly separate configuration from the implementation. The application will grab the configured factory object using JNDI and use the factory to find and create the resource objects. In a typical example, the application will grab a database DataSource to create JDBC Connections. Because the configuration is left to the configuration files, it's easy for the application to change databases for different customers.

Some typical factory objects include:

web-apps and JNDI Contexts

Resin organizes its resources into a tree, rooted in the system classloader. Each Resin context is associated with a classloader, a JNDI context, and a set of resources (databases, JMS, EJB beans, etc.)

Child contexts inherit classes and resources from the parent contexts. For example, a database with a JNDI name "java:comp/env/jdbc/foo" belonging to the foo.com virtual host would be shared for all web-applications in that host.

When Resin detects class or configuration changes in a context, it will reload that context and all child contexts. This is how Resin reloads an application when a servlet changes.

Each web-app gets its own JNDI copy. So a web-app named /quercus and a web-app named /cmp could each use java:comp/env/jdbc/test for a database pool, but would use unique pools (probably using different databases.)

This separation keeps web-apps from stepping on each other's toes and also lets each virtual host use different databases.

The web-apps can share JNDI configuration from its host, and the hosts can share JNDI configuration from the global server. Each web-app copies the host JNDI tree, and each host copies the server JNDI tree. So the web-app can't affect the host's JNDI, but it can share the host's pools.

In Resin's configuration, the context determines where the JNDI will be shared. If the JNDI configuration is in the <host>, it will be shared across the entire host. If it's in the <web-app>, it will only be used in the web-app.

contextscope
http-servershared across all applications
hostshared across the virtual host
web-appspecific to the servlet application (.war)
host and web-app specific configuration
...
<host id='foo.com'>
  <resource-ref res-ref-name='jdbc/foo'
                res-type='javax.sql.DataSource'>
    <init-param driver-name="org.gjt.mm.mysql.Driver"/>
    <init-param url="jdbc:mysql://localhost:3306/foo"/>
  </resource-ref>

  <web-app id='/quercus'>
    <resource-ref res-ref-name='jdbc/quercus'
                  res-type='javax.sql.DataSource'>
      <init-param driver-name="org.gjt.mm.mysql.Driver"/>
      <init-param url="jdbc:mysql://localhost:3306/quercus"/>
    </resource-ref>
  </web-app>
</host>
...

In the previous example, the java:comp/env/jdbc/foo pool is shared across all web-apps in foo.com, but the java:comp/env/jdbc/quercus pool is only available in the /quercus web-app.

JNDI Names

JNDI names look like URLs. A typical name for a database pool is java:comp/env/jdbc/test. The java: scheme is a memory-based tree. comp/env is the standard location for Java configuration objects and jdbc is the standard location for database pools.

Other URL schemes are allowed as well, including RMI (rmi://localhost:1099) and LDAP. Many applications, though will stick to the java:comp/env tree.

namemeaning
java:comp/envConfiguration environment
java:comp/env/jdbcJDBC DataSource pools
java:comp/env/ejbEJB remote home interfaces
java:comp/env/cmpEJB local home interfaces (non-standard)
java:comp/env/jmsJMS connection factories
java:comp/env/mailJavaMail connection factories
java:comp/env/urlURL connection factories
java:comp/UserTransactionUserTransaction interface

JNDI API

The vast majority of applications will only need the following simple pattern to lookup objects using JNDI. Since the JNDI objects are typically configured in the web.xml or resin.conf, servlets will typically look up their DataSources or EJB objects once in the init() method. By looking up the object once, the application can avoid any JNDI overhead for normal requests.

Looking up a DataSource
import javax.naming.InitialContext;
import javax.naming.Context;

...

Context env = (Context) new InitialContext().lookup("java:comp/env");
DataSource pool = (DataSource) env.lookup("jdbc/test");

new InitialContext() returns the initial context for the current web-app. As explained above, each application has its own independent JNDI namespace. So applications and virtual hosts will not conflict with each other's JNDI names.

The lookup(subpath) call finds the object at the specified subpath, like a filesystem lookup. Intermediate paths, like env in the example above, are Context objects. There's a strong analogy between filesystem directories and JNDI Context objects.

callmeaning
new InitialContext()A new pointer to the root context
context.lookup("subpath")Finds the object or context at the named path beneath the current context

Applications will generally cache the results of the JNDI lookup. Once configured, factory objects don't change so they can be saved to avoid the JNDI lookup. For example, EJB Home and DataSource factories don't change once they've been configured. A well-designed application will lookup the DataSource once and cache it for the next call. Servlets, for example, will often lookup the DataSource or EJB Home in the init() method and save them in servlet instance variables.

Caching a DataSource in a Servlet init()
package qa;

import javax.servlet.*;
import javax.naming.*;

public class MyServlet extends GenericServlet {
  DataSource dataSource;

  public void init()
    throws ServletException
  {
    try {
      Context env = new InitialContext().lookup("java:comp/env");
      dataSource = (DataSource) env.lookup("jdbc/test");
    } catch (Exception e) {
      throw new ServletException(e);
    }
  }

  ...
}

JNDI configuration

resource-ref

Factory configuration, including configuration for database pooling. resource-ref puts the DataSource in a JNDI context and also in the ServletContext. Each web-app can configure its own database pool. Resin can also share a common pool by putting the resource-ref in the <host> or in the <http-server>.

More details are in the database config page.

The driver can be in WEB-INF/lib or WEB-INF/classes, although it's a better idea to put it in the global classpath or resin-2.0.x/lib.

AttributeMeaning
res-ref-nameJNDI path attribute to store the pool. The path is relative to java:comp/env.
res-typejavax.sql.DataSource or javax.sql.XADataSource for database pools
init-paraminitialization parameters (Resin 1.2)
init-classClass containing init params (Map or Hashtable) (Resin 1.2.4)
bean-nameoptional bean class to be used as a resource (Resin 1.2)

init-param sets bean properties of the data source. You can look at the com.caucho.sql.DBPool JavaDoc for its interface. Unknown parameters are used to set the driver properties. So you can set any driver-specific property in the init-param.

env-entry

JNDI parameter configuration. The env-entry configuration is similar to the init-param for servlets, but is accessible to any Java class in the application without needing to pass along a context.

AttributeMeaning
env-entry-nameJNDI path attribute to store the variable. The path is relative to java:comp/env.
env-entry-typeJava type of the variable
env-entry-valueThe variable value.

The example configuration stores a string in java:comp/env/greeting. Following the J2EE spec, the env-entry-name is relative to java:comp/env. If the env-entry is in the <host> context, it will be visible to all web-apps in the host.

Example resin.conf fragment
<env-entry>
  <env-entry-name>greeting</env-entry-name>
  <env-entry-type>java.lang.String</env-entry-type>
  <env-entry-value>Hello, World</env-entry-value>
</env-entry>

The following servlet fragment is a typical use in a servlet. The servlet only looks up the variable once and stores it for later use.

GreetingServlet.java
import java.io.*;
import javax.naming.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class TestServlet extends HttpServlet {
  private String greeting;

  public void init()
    throws ServletException
  {
    try {
      Context env = (Context) new InitialContext().lookup("java:comp/env");
      greeting = (String) env.lookup("greeting");
    } catch (NamingException e) {
      throw new ServletException(e);
    }
  }

  ...
}

jndi-link

Links a foreign JNDI context to the Resin JNDI context. For example, you can use jndi-link to link in client EJBs from a foreign EJB container.

AttributeDescription.
jndi-nameJNDI path attribute to bind the link
property-filejndi.property to use to obtain the Context.
jndi-factoryClass name of an InitialContextFactory used to create the bean.
init-paramProperties to be used to get the initial context.
jndi-lookupJNDI path for the foreign context.
Linking a WebLogic EJB client bean
<jndi-link>
  <jndi-name>java:comp/env/ejb/traderHome</jndi-name>
  <jndi-factory>weblogic.jndi.WLInitialContextFactory</jndi-factory>
  <init-param java.naming.provider.url="t3://localhost:7001"/>
  <jndi-lookup>statelessSession.TraderHome</jndi-lookup>
</jndi-link>

Known JNDI Object Factories

javax.sql.DataSource

Configures a non-transactional JDBC data sources. More details are available on the database configuration page.

init-param values
AttributeMeaning
driver-nameThe Java classname of the driver.
urlThe driver specific database url.
data-sourceA reference to an XADataSource or PooledDataSource.

Here's a sample minimal resin.conf fragment to bind a DBPool-based database to the JNDI path "java:comp/env/jdbc/test". The examples below show how that JNDI path will be used.

Sample resin.conf fragment
<resource-ref>
  <res-ref-name>jdbc/test</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <init-param driver-name="com.caucho.jdbc.mysql.Driver"/>
  <init-param url="jdbc:mysql-caucho://localhost:3306/test"/>
</resource-ref>

javax.sql.XADataSource

Configures a transactional JDBC data sources. More details are available on the database configuration page.

init-param values
AttributeMeaning
driver-nameThe Java classname of the driver.
urlThe driver specific database url.

Here's a sample minimal resin.conf fragment to bind a transactional DBPool-based database to the JNDI path "java:comp/env/jdbc/test". The examples below show how that JNDI path will be used.

Sample resin.conf fragment
<resource-ref>
  <res-ref-name>jdbc/test</res-ref-name>
  <res-type>javax.sql.XADataSource</res-type>
  <init-param driver-name="com.caucho.jdbc.mysql.Driver"/>
  <init-param url="jdbc:mysql-caucho://localhost:3306/test"/>
</resource-ref>

javax.mail.Session

JavaMail sessions are configured with resource-ref. The session is created with Session.getInstance using the properties defined in the init-param.

<resource-ref res-ref-name='mail/MySession'
              res-type='javax.mail.Session'>
  <init-param mail.transport.protocol='smtp'>
  <init-param mail.host='localhost'>
  <init-param mail.user='harry'>
</resource-ref>

Custom Factories

The resource-ref element can configure any bean-based factory. A new instance of the bean will be created from the specified class-name. To make this work, the factory class must have a public zero-arg constructor.

The init-param elements configure the factory's properties using introspection. A 'foo' property expects a setFoo method, and a 'foo-bar' property expects a setFooBar property:

custom.MyBean
package custom;

public class MyBean {
  private String foo;
  private int bar;

  public void setFoo(String foo)
  {
    this.foo = foo;
  }

  public void setBar(int bar)
  {
    this.bar = bar;
  }

  ...
}
Configuration for custom.MyBean
<resource-ref res-ref-name='custom/MyBean'
              class-name='test.MyBean'>
  <init-param foo='a string'>
  <init-param bar='613'>
</resource-ref>

Once configured, the application will lookup the factory in java:comp/env/custom/MyBean and use it to create any needed application objects. As long as the class follows the bean patterns, it can be configured in resource-ref.


Filters
Configuration
Databases
Copyright © 1998-2002 Caucho Technology, Inc. All rights reserved.
Resin® is a registered trademark, and HardCoretm and Quercustm are trademarks of Caucho Technology, Inc.