Sun GlassFish Enterprise Server v3 Application Development Guide

Chapter 16 Using the Java Naming and Directory Interface

A naming service maintains a set of bindings, which relate names to objects. The Java EE naming service is based on the Java Naming and Directory InterfaceTM (JNDI) API. The JNDI API allows application components and clients to look up distributed resources, services, and EJB components. For general information about the JNDI API, see http://java.sun.com/products/jndi/.

You can also see the JNDI tutorial at http://java.sun.com/products/jndi/tutorial/.

This chapter contains the following sections:


Note –

The Web Profile of the Enterprise Server supports the EJB 3.1 Lite specification, which allows enterprise beans within web applications, among other features. The full Enterprise Server supports the entire EJB 3.1 specification. For details, see JSR 318.


Accessing the Naming Context

The Sun GlassFishTM Enterprise Server provides a naming environment, or context, which is compliant with standard Java EE requirements. A Context object provides the methods for binding names to objects, unbinding names from objects, renaming objects, and listing the bindings. The InitialContext is the handle to the Java EE naming service that application components and clients use for lookups.

The JNDI API also provides subcontext functionality. Much like a directory in a file system, a subcontext is a context within a context. This hierarchical structure permits better organization of information. For naming services that support subcontexts, the Context class also provides methods for creating and destroying subcontexts.

The rest of this section covers these topics:


Note –

Each resource within the server must have a unique name.


Global JNDI Names

Global JNDI names are assigned according to the following precedence rules:

  1. A global JNDI name assigned in the sun-ejb-jar.xml, sun-web.xml, or sun-application-client.xml deployment descriptor file has the highest precedence. See Mapping References.

  2. A global JNDI name assigned in a mapped-name element in the ejb-jar.xml, web.xml, or application-client.xml deployment descriptor file has the second highest precedence. The following elements have mapped-name subelements: resource-ref, resource-env-ref, ejb-ref, message-destination, message-destination-ref, session, message-driven, and entity.

  3. A global JNDI name assigned in a mappedName attribute of an annotation has the third highest precedence. The following annotations have mappedName attributes: @javax.annotation.Resource, @javax.ejb.EJB, @javax.ejb.Stateless, @javax.ejb.Stateful, and @javax.ejb.MessageDriven.

  4. A default global JNDI name is assigned in some cases if no name is assigned in deployment descriptors or annotations.

    • For an EJB 2.x dependency or a session or entity bean with a remote interface, the default is the fully qualified name of the home interface.

    • For an EJB 3.0 dependency or a session bean with a remote interface, the default is the fully qualified name of the remote business interface.

    • If both EJB 2.x and EJB 3.0 remote interfaces are specified, or if more than one 3.0 remote interface is specified, there is no default, and the global JNDI name must be specified.

    • For all other component dependencies that must be mapped to global JNDI names, the default is the name of the dependency relative to java:comp/env. For example, in the @Resource(name="jdbc/Foo") DataSource ds; annotation, the global JNDI name is jdbc/Foo.

Accessing EJB Components Using the CosNaming Naming Context

The preferred way of accessing the naming service, even in code that runs outside of a Java EE container, is to use the no-argument InitialContext constructor. However, if EJB client code explicitly instantiates an InitialContext that points to the CosNaming naming service, it is necessary to set the java.naming.factory.initial property to com.sun.jndi.cosnaming.CNCtxFactory in the client JVM software when accessing EJB components. You can set this property as a command-line argument, as follows:


-Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory

Or you can set this property in the code, as follows:

Properties properties = null;
      try {
            properties = new Properties();
            properties.put("java.naming.factory.initial",
                  "com.sun.jndi.cosnaming.CNCtxFactory");
      ...

Accessing EJB Components in a Remote Enterprise Server

The recommended approach for looking up an EJB component in a remote Enterprise Server from a client that is a servlet or EJB component is to use the Interoperable Naming Service syntax. Host and port information is prepended to any global JNDI names and is automatically resolved during the lookup. The syntax for an interoperable global name is as follows:

corbaname:iiop:host:port#a/b/name

This makes the programming model for accessing EJB components in another Enterprise Server exactly the same as accessing them in the same server. The deployer can change the way the EJB components are physically distributed without having to change the code.

For Java EE components, the code still performs a java:comp/env lookup on an EJB reference. The only difference is that the deployer maps the ejb-reference element to an interoperable name in an Enterprise Server deployment descriptor file instead of to a simple global JNDI name.

For example, suppose a servlet looks up an EJB reference using java:comp/env/ejb/Foo, and the target EJB component has a global JNDI name of a/b/Foo.

The ejb-ref element in sun-web.xml looks like this:

<ejb-ref>
   <ejb-ref-name>ejb/Foo</ejb-ref-name>
   <jndi-name>corbaname:iiop:host:port#a/b/Foo</jndi-name>
<ejb-ref>

The code looks like this:

Context ic = new InitialContext();
Object o = ic.lookup("java:comp/env/ejb/Foo");

For a client that doesn’t run within a Java EE container, the code just uses the interoperable global name instead of the simple global JNDI name. For example:

Context ic = new InitialContext();
Object o = ic.lookup("corbaname:iiop:host:port#a/b/Foo");

Objects stored in the interoperable naming context and component-specific (java:comp/env) naming contexts are transient. On each server startup or application reloading, all relevant objects are re-bound to the namespace.

Naming Environment for Lifecycle Modules

Lifecycle listener modules provide a means of running short or long duration tasks based on Java technology within the application server environment, such as instantiation of singletons or RMI servers. These modules are automatically initiated at server startup and are notified at various phases of the server life cycle. For details about lifecycle modules, see Chapter 13, Developing Lifecycle Listeners.

The configured properties for a lifecycle module are passed as properties during server initialization (the INIT_EVENT). The initial JNDI naming context is not available until server initialization is complete. A lifecycle module can get the InitialContext for lookups using the method LifecycleEventContext.getInitialContext() during, and only during, the STARTUP_EVENT, READY_EVENT, or SHUTDOWN_EVENT server life cycle events.

Configuring Resources

The Enterprise Server exposes the following special resources in the naming environment. Full administration details are provided in the following sections:

External JNDI Resources

An external JNDI resource defines custom JNDI contexts and implements the javax.naming.spi.InitialContextFactory interface. There is no specific JNDI parent context for external JNDI resources, except for the standard java:comp/env/.

Create an external JNDI resource in one of these ways:

Custom Resources

A custom resource specifies a custom server-wide resource object factory that implements the javax.naming.spi.ObjectFactory interface. There is no specific JNDI parent context for external JNDI resources, except for the standard java:comp/env/.

Create a custom resource in one of these ways:

Built- in Factories for Custom Resources

The Enterprise Server provides built-in factories for the following types of custom resources:

Template sun-resources.xml files for these built-in factories and a README file are available at as-install/lib/install/templates/resources/custom/. For more information about the sun-resources.xml file, see the Sun GlassFish Enterprise Server v3 Application Deployment Guide.

JavaBeanFactory

To create a custom resource that provides instances of a JavaBean class, follow these steps:

  1. Set the custom resource's factory class to org.glassfish.resources.custom.factory.JavaBeanFactory.

  2. Create a property in the custom resource for each setter method in the JavaBean class.

    For example, if the JavaBean class has a method named setAccount, specify a property named account and give it a value.

  3. Make sure the JavaBean class is accessible to the Enterprise Server.

    For example, you can place the JavaBean class in the as-install/lib directory.

PropertiesFactory

To create a custom resource that provides properties to applications, set the custom resource's factory class to org.glassfish.resources.custom.factory.PropertiesFactory, then specify one or both of the following:

PrimitiviesAndStringFactory

To create a custom resource that provides Java primitives to applications, follow these steps:

  1. Set the custom resource's factory class to org.glassfish.resources.custom.factory.PrimitivesAndStringFactory.

  2. Set the custom resource's resource type to one of the following or its fully qualified wrapper class name equivalent:

    • int

    • integer

    • long

    • double

    • float

    • char

    • character

    • short

    • byte

    • boolean

    • String

  3. Create a property in the custom resource named value and give it the value needed by the application.

    For example, If the application requires a double of value 22.1, create a property with the name value and the value 22.1.

URLFactory

To create a custom resource that provides URL instances to applications, follow these steps:

  1. Set the custom resource's factory class to org.glassfish.resources.custom.factory.URLFactory.

  2. Choose which of the following constructors to use:

    • URL(protocol, host, port, file)

    • URL(protocol, host, file)

    • URL(spec)

  3. Define properties according to the chosen constructor.

    For example, for the first constructor, define properties named protocol, host, port, and file. Example values might be http, localhost, 8085, and index.html, respectively.

    For the third constructor, define a property named spec and assign it the value of the entire URL.

Using a Custom jndi.properties File

To use a custom jndi.properties file, place the file in the domain-dir/lib/classes directory or JAR it and place it in the domain-dir/lib directory. This adds the custom jndi.properties file to the Common class loader. For more information about class loading, see Chapter 2, Class Loaders.

For each property found in more than one jndi.properties file, the Java EE naming service either uses the first value found or concatenates all of the values, whichever makes sense.

Mapping References

The following XML elements in the Enterprise Server deployment descriptors map resource references in application client, EJB, and web application components to JNDI names configured in the Enterprise Server:

These elements are part of the sun-web.xml, sun-application-client.xml, and sun-ejb-ref.xml deployment descriptor files. For more information about how these elements behave in each of the deployment descriptor files, see Appendix C, Elements of the Enterprise Server Deployment Descriptors, in Sun GlassFish Enterprise Server v3 Application Deployment Guide.

The rest of this section uses an example of a JDBC resource lookup to describe how to reference resource factories. The same principle is applicable to all resources (such as JMS destinations, JavaMail sessions, and so on).

The @Resource annotation in the application code looks like this:

@Resource(name="jdbc/helloDbDs") javax.sql.DataSource ds;

This references a resource with the JNDI name of java:comp/env/jdbc/helloDbDs. If this is the JNDI name of the JDBC resource configured in the Enterprise Server, the annotation alone is enough to reference the resource.

However, you can use an Enterprise Server specific deployment descriptor to override the annotation. For example, the resource-ref element in the sun-web.xml file maps the res-ref-name (the name specified in the annotation) to the JNDI name of another JDBC resource configured in the Enterprise Server.

<resource-ref>
   <res-ref-name>jdbc/helloDbDs</res-ref-name>
   <jndi-name>jdbc/helloDbDataSource</jndi-name>
</resource-ref>