This section discusses the Java Naming and Directory Interface (JNDI), which is an API for accessing different kinds of naming and directory services. J2SE components locate objects by invoking the JNDI lookup method.
This section covers the following topics:
A JNDI name is a user-friendly name for an object. These names are bound to their objects by the naming and directory service that is provided by a J2SE server. Because J2SE components access this service through the JNDI API, an object’s user-friendly name is its JNDI name. For instance, the JNDI name of the Oracle database can be jdbc/Oracle. When it starts up, Sun Java System Web Server reads information from configuration file and automatically adds JNDI database names to the name space.
The application component’s naming environment is a mechanism that allows customization of the application component’s business logic during deployment or assembly. Use of the application component’s environment allows the application component to be customized without the need to access or change the application component’s source code.
A J2SE container implements the Web application component’s environment, and provides it to the application component instance as a JNDI naming context. The application component’s environment is used as follows:
The Web application component’s business methods access the environment using the JNDI interfaces. The application component provider declares in the deployment descriptor all the environment entries that the application component expects to be provided in its environment at runtime.
The container provides an implementation of the JNDI naming context that stores the application component environment. The container also provides the tools that allow the deployer to create and manage the environment of each application component.
A deployer uses the tools provided by the container to initialize the environment entries that are declared in the application component’s deployment descriptor. The deployer can set and modify the values of the environment entries.
The container makes the environment naming context available to the application component instances at runtime. The application component’s instances use the JNDI interfaces to obtain the values of the environment entries.
Each application component defines its own set of environment entries. All instances of an application component within the same container share the same environment entries. Application component instances are not allowed to modify the environment at runtime.
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 given in the following section, the resource reference name is jdbc/SavingsAccountDB.
The JNDI name of a resource and the name of the resource reference are not the same. This approach to naming requires that you map the two names before deployment, but it also decouples components from resources. Because of this de-coupling, if at a later time the component needs to access a different resource, you do not have to change the name in the code. This flexibility also makes it easier for you to assemble J2SE applications from preexisting components.
The following table lists recommended JNDI lookups and their associated references for the J2SE resources used by Sun Java System Web Server.Table 12–1 JNDI Lookups and Their Associated References
JNDI Lookup Name
Application environment entries
JDBC DataSource resource
JavaMail Session Connection Factories
URL Connection Factories
A naming reference is a string used by the application to look up an object in the given naming context. For each Web application, there is a naming context and the references are configured in the standard component deployment descriptors.This section describes the standard deployment descriptor features used in Sun Java System Web Server. This section covers the following topics:
Environment entries, defined using <env-entry>, provide a way of specifying deployment time parameters to J2SE Web applications. Note that the servlet context initialization parameters could be defined using <context-param>, but <env-entry> is the preferred way because application deployers to configure such applications parameters by explicitly specifying the name, type and values for them.
The following sample describes the syntax of <env-entry> as specified in the J2SE standard deployment descriptors:
<env-entry> <description> Send pincode by mail </description> <env-entry-name> mailPincode </env-entry-name> <env-entry-value> false </env-entry-value> <env-entry-type> java.lang.Boolean </env-entry-type> </env-entry>
The <env-entry-type> tag specifies a fully qualified class name for the entry. Here is a code snippet to lookup the <env-entry> using JNDI from a servlet or JSP:
Context initContext = new InitialContext(); Boolean mailPincode = (Boolean) initContext.lookup("java:comp/env/mailPincode"); // one could use relative names into the sub-context Context envContext = initContext.lookup("java:comp/env"); Boolean mailPincode = (Boolean) envContext.lookup("mailPincode");
A factory is an object that creates other objects on demand. A resource factory creates resource objects, such as database connections or message service connections. They are configured using <resource-ref> element in the standard deployment descriptors.
The following example describes the use of factories:
Declaration of a reference to a JDBC connection factory that returns objects of type javax.sql.DataSource:
<resource-ref> <description> Primary database </description> <res-ref-name> jdbc/primaryDB </res-ref-name> <res-type> javax.sql.DataSource </res-type> <res-auth> Container </res-auth> </resource-ref>
<res-type> is a fully-qualified class name of the resource factory. The <res-auth> variable can be assigned either Container or Application as a value.
If Container is specified, the web container handles the authentication before binding the resource factory to JNDI lookup registry. If Application is specified, the servlet must handle authentication programmatically. Different resource factories are looked up under a separate sub-context that describes the resource type, follows:
jdbc/ for a JDBC javax.sql.DataSource factory
mail/ for a JavaMail javax.mail.Session factory
url/ for a java.net.URL factory
Here is a code snippet to get JDBC connection from an application component with the container handling the authentication:
InitialContext initContext = new InitialContext(); DataSource source = (DataSource) initContext.lookup("java:comp/env/jdbc/primaryDB"); Connection conn = source.getConnection();
Please note that in order to ensure that for these resource references work, the res-ref-name must map to valid resource factory at runtime.
Resource environment references provide a way of accessing, by using JNDI lookups, administered objects associated with a resource. The <resource-env-ref> element, defined in the standard deployment descriptors lets applications declare the resource requirements.
The main difference between <resource-env-ref> and <resource-ref> element is the absence of specific resource authentication requirement, both these elements have to be backed up by a resource factory descriptor.
<resource-env-ref> <description> My Topic </description> <res-env-ref-name> jdbc/MyTopic </res-ref-name> <res-env-ref-type> javax.jdbc.Topic </res-type> </resource-env-ref>
Here is a code snippet to access a JMS Topic object:
InitialContext initContext = new InitialContext(); javax.jms.Topic myTopic = (javax.jdbc.Topic) initContext.lookup("java:comp/env/jdbc/MyTopic");
The naming support in Sun Java System Web Server is based primarily on J2SE 1.3, with a few added enhancements.When an application component creates the initial context by using InitialContext(), Sun Java System Web Server returns an object that serves as a handle to the Web application’s naming environment. This object in turn provides sub-contexts for the java:comp/env namespace. Each Web application gets its own namespace java:comp/env name space is allotted to each Web application and objects bound in one Web application’s namespace do not collide with objects bound in other Web applications.
For J2SE web applications, the deployment descriptor in the web.xml file is the placeholder for defining references to application environment entries or resource manager (such as SQL Data Source) connection factories. Applications look up such references using the JNDI InitialNamingContext provided by the J2SE containers. This feature makes applications portable to different Web Server environments by just making changes to the deployment descriptor, that is, without accessing or modifying the application’s source code.
A connection factory is an object that produces connection objects that enable a J2SE component to access a resource. The connection factory for a database is a javax.sql.DataSource object, which creates a java.sql.Connection object.
In Sun Java System Web Server, you can configure the means of accessing the following resources and resource factories:
JDBC connection factories
JavaMail Session connection factories
Generic, custom user-written resource object factories.
Support for external resource repositories such as LDAP
All Sun Java System Web Server resource factories are specified within the <resources> </resources> tags in server.xml and have a JNDI name specified using the jndiname attribute (with the exception of jdbconnectionpool which does not have a jndiname). This attribute is used to register the factory in the server-wide namespace. Deployers can map user-specified, application-specific resource reference names (declared within resource-ref or resource-env-ref elements) to these server-wide resource factories using the resource-ref element in sun-web.xml. This enables deployment time decisions to be made with regards to which JDBC resources (and other resource factories) to use for a given application.
A custom resource accesses a local JNDI repository and an external resource accesses an external JNDI repository. Both types of resources need user-specified factory class elements, JNDI name attributes, and so on.
In this section, we will discuss how to create various J2SE resources, and how to access these resources.