<document>
  <header>
    <product>resin</product>
    <resin-2.0>$resin/ref/jndi.xtp</resin-2.0>
    <title>JNDI Resource Configuration</title>
  </header>

  <body>
    <summary/>

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

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

<p>Some typical factory objects include:

</p><ul>
<li><a href="config|db">JDBC DataSource</a>
</li><li>EJB Home interfaces
</li><li><a href="jms|index">Java Messaging Service (JMS)</a> connection factories
</li><li>JavaMail connection factories
</li><li>Global configuration constants
</li></ul>

<s1 title="web-apps and JNDI Contexts">

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

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

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

<figure src="jndi_tree.gif"/>

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

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

<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>

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

<deftable>
<tr><th>context</th><th>scope
</th></tr><tr><td>http-server</td><td>shared across all applications
</td></tr><tr><td>host</td><td>shared across the virtual host
</td></tr><tr><td>web-app</td><td>specific to the servlet application (.war)
</td></tr></deftable>

<example title="host and web-app specific configuration">
...
&lt;host id='foo.com'&gt;
  &lt;database name='jdbc/foo'&gt;
    &lt;driver-class&gt;org.gjt.mm.mysql.Driver&lt;/driver-class&gt;
    &lt;driver-url&gt;jdbc:mysql://localhost:3306/foo&lt;/driver-url&gt;
  &lt;/database&gt;

  &lt;web-app id='/quercus'&gt;
    &lt;database name='jdbc/quercus'&gt;
      &lt;driver-class&gt;org.gjt.mm.mysql.Driver&lt;/driver-class&gt;
      &lt;driver-url&gt;jdbc:mysql://localhost:3306/quercus&lt;/driver-url&gt;
    &lt;/database&gt;
  &lt;/web-app&gt;
&lt;/host&gt;
...
</example>

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

<p>The previous example was meant to illustrate the concept of how
JNDI objects belong to a certain context, for more realistic
examples of configuring and using databases see the <a href="doc|db|">Databases</a> topic.

</p></s1>

<s1 title="JNDI Names">

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

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

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

</s1>

<s1 title="JNDI API">

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

<example title="Looking up a DataSource">
import javax.naming.InitialContext;
import javax.naming.Context;

...

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

<p><var>new InitialContext()</var> 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.
</p>

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

<deftable>
<tr><th>call</th><th>meaning
</th></tr><tr><td>new InitialContext()</td><td>A new pointer to the root context
</td></tr><tr><td>context.lookup("subpath")</td><td>Finds the object or context at the named path beneath the current context
</td></tr></deftable>

<p>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
<var>init()</var> method and save them in servlet instance variables.
</p>

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

  ...
}
</example>

</s1>

<s1 title="JNDI configuration">

<s2 title="resource">
<p>Factory configuration, including configuration for
database pooling.  <a config-tag="resource"/> 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 in the &lt;host&gt; or in
the &lt;server&gt;.</p>

<p>More details are in the configuration documentation for the <a config-tag="resource"/> tag.
page.</p>

</s2>

<s2 title="env-entry">
<p>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.</p>

<p>More details are in the configuration documentation for the <a config-tag="env-entry"/> tag.

</p></s2>

<s2 title="jndi-link" version="Resin 1.2" type="defun">
<p>Links a foreign JNDI context to the Resin JNDI context.
For example, you can use <var>jndi-link</var> to link in client EJBs from
a foreign EJB container.</p>

<p>More details are in the configuration documentation for the <a config-tag="jndi-link"/> tag.

</p></s2>
</s1>

<s1 title="Known JNDI Object Factories"> 

<s2 title="javax.sql.DataSource">

<p>Configures a non-transactional JDBC data sources.  More details are
available on the <a href="config|db">database configuration</a> page.
</p>

</s2>

<s2 title="javax.sql.XADataSource">

<p>Configures a transactional JDBC data sources.  More details are
available on the <a href="config|db">database configuration</a> page.</p>

</s2>

<s2 title="javax.mail.Session">

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

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

</s2>

</s1>

<s1 title="Custom Resource Objects">

<p>The resource element can configure any bean-based object.
A new instance of the bean is created from the name
of the class specified with <var>type</var>.  To make this work, the class
must have a public zero-arg constructor.</p>

<p>You code your java class to accept bean-style setters.  You can
then  use <a href="|config|init">Bean-style initialization</a> or
<var>init-param</var> elements to configure the factory's
properties using introspection.  A 'foo' property expects a
setFoo method, and a 'foo-bar' property expects a setFooBar property.
</p>

<p>An example of a custom JNDI object that uses bean-style
initialization is the <a href="|resource|tutorial|jndi-appconfig">jndi-appconfig</a>
tutorial.</p><p>

The following is a short example using <var>init-param</var>:

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

  ...
}
</example>

<example title="Configuration for custom.MyBean">
&lt;resource jndi-name='custom/MyBean'&gt;
  &lt;type&gt;test.MyBean&lt;/type&gt;
  &lt;init-param foo='a string'&gt;
  &lt;init-param bar='613'&gt;
&lt;/resource&gt;
</example>

</p><p>The application uses the standard jndi API to find the resource with the
jndi name <var>java:comp/env/custom/MyBean</var>. 
needed application objects.  As long as a class follows the bean patterns (at
minimum a public, zero-arg constructor, and setXXX mthods for properties), it
can be configured in <code>resource</code>.
</p>

</s1>
  </body>
</document>