<title>JNDI</title>

JNDI, the Java Naming and Directory Interface, provides a global
memory tree to store and lookup configuration objects.  JNDI will
typically contain objects like database pools, EJB home objects, and
global configuration variables.

<subsection title='JNDI Names'>

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

<p/>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.

<deftable>
<tr><th>name<th>meaning
<tr><td>java:comp/env<td>Configuration environment
<tr><td>java:comp/env/jdbc<td>JDBC DataSource pools
<tr><td>java:comp/env/ejb<td>EJB remote home interfaces
<tr><td>java:comp/env/cmp<td>EJB local home interfaces (non-standard)
<tr><td>java:comp/env/jms<td>JMS connection factories
<tr><td>java:comp/env/mail<td>JavaMail connection factories
<tr><td>java:comp/env/url<td>URL connection factories
<tr><td>java:comp/UserTransaction<td>UserTransaction interface
</deftable>

</subsection>

<subsection title='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.

<example>
import javax.naming.*;

...

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

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

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

</subsection>

<subsection title="Separate JNDI for hosts and web-apps">

<p/>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 (possibly using
different databases.)

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

<p/>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.

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

<example>
...
&lt;host id='foo.com'>
  &lt;resource-ref res-ref-name='jdbc/foo'
                res-ref-type='javax.sql.DataSource'>
    <init-param driver-name="org.gjt.mm.mysql.Driver"/>
    <init-param url="jdbc:mysql://localhost:3306/foo"/>
  &lt;/resource-ref>

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

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.

</subsection>

<section title="JNDI configuration">

<subsection title="resource-ref">
<sum>Resource configuration, including configuration for
database pooling.</sum>  <var/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 &lt;host> or in
the &lt;http-server>.

<p/>More details are in the <a href='db-config.xtp'>database config</a>
page.

<p/>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.

<deftable>
<tr><th>Attribute<th>Meaning
<tr><td>res-ref-name<td>JNDI path attribute to store the pool.  The
path is relative to java:comp/env.
<tr><td>res-type<td>javax.sql.DataSource or javax.sql.XADataSource for database pools
<tr><td>init-param<td>initialization parameters (Resin 1.2)
<tr><td>init-class<td>Class containing init params (Map or Hashtable) (Resin 1.2.4)
<tr><td>bean-name<td>optional bean class to be used as a resource (Resin 1.2)
</deftable>

<p/><var/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.

</subsection>

<subsection title="env-entry">
<sum>JNDI parameter configuration.</sum>  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.

<deftable>
<tr><th>Attribute<th>Meaning
<tr><td>env-entry-name<td>JNDI path attribute to store the variable.  The path is relative to java:comp/env.
<tr><td>env-entry-type<td>Java type of the variable
<tr><td>env-entry-value<td>The variable value.
</deftable>

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 &lt;host> context, it will
be visible to all web-apps in the host.

<example title="Example resin.conf fragment">
&lt;env-entry>
  &lt;env-entry-name>greeting&lt;/env-entry-name>
  &lt;env-entry-type>java.lang.String&lt;/env-entry-type>
  &lt;env-entry-value>Hello, World&lt;/env-entry-type>
&lt;/env-entry>
</example>

<p/>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.

<example title="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);
    }
  }

  ...
}
</example>

</subsection>

</section>

<section title="Known JNDI Object Factories">

<subsection title='javax.mail.Session'>

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

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

</subsection>

</section>

