Developing the Cabin EJB and the TravelAgent EJB may have raised your confidence, but it also may have raised a lot of questions. We have glossed over most of the details involved in developing, deploying, and accessing the enterprise beans. In this chapter and the ones that follow, we will peel away the layers of the Enterprise JavaBeans onion to expose the details of EJB application development.
This chapter focuses specifically on the client’s remote and local view of entity and session beans. The endpoint view, which is used by Web service clients to access stateless session beans, is significantly different and is addressed separately in the Web services chapter, Chapter 14. Message-driven beans are not covered in this chapter either—they are covered in detail in Chapter 12.
In
Chapter 4, the client application started by
creating an InitialContext
, which it then used to
get a remote reference to the homes of the Cabin and TravelAgent
EJBs. The InitialContext
is part of a larger API
called the Java Naming and Directory Interface ( JNDI). We use JNDI
to look up an EJB home in an EJB server just like we might use a
phone book to find the home number of a friend or business associate.
JNDI is a standard Java package that provides a uniform API for accessing a wide range of services. It is somewhat similar to JDBC, which provides uniform access to different relational databases. Just as JDBC lets us write code that doesn’t care whether it’s talking to an Oracle database or a DB2 database, JNDI lets us write code that can access different directory and naming services, including the naming services provided by EJB servers. EJB servers are required to support JNDI by organizing beans into a directory structure and providing a JNDI driver, called a service provider, for accessing that directory structure. Using JNDI, an enterprise can organize its beans, services, data, and other resources in a unified directory.
Two of JNDI’s greatest features are that it is virtual and dynamic. JNDI is virtual because it allows one directory service to be linked to another through simple URLs. The URLs in JNDI are analogous to HTML links. Just as an HTML link allows you to download a new page without worrying about the server on which that page is located, JNDI lets us drill down through directories to files, printers, and EJB home objects without knowing where the resources—or even the directory servers holding information about the resources—are located. The directories and subdirectories can be located in the same host or physically hosted at different locations. As developers or administrators, we can create virtual directories that span a variety of services over many different physical locations.
JNDI is dynamic because it allows the JNDI drivers (a.k.a. service providers) for specific types of directory services to be loaded at runtime. A driver maps a specific kind of directory service into the standard JNDI class interfaces. When a link to a different directory service is chosen, the driver for that type of directory service is automatically loaded from the directory’s host, if it is not already resident on the user’s machine. Automatically downloading JNDI drivers makes it possible for a client to navigate across arbitrary directory services without knowing in advance what kinds of services it is likely to find.
After the client application locates and obtains a remote reference
to the EJB home using JNDI, the client can use the EJB home to obtain
an EJB object reference to an enterprise bean. In Chapter 4 the client applications used the method
getInitialContext( )
to get a JNDI
InitialContext
object, which looked like this:
public static Context getInitialContext( ) throws javax.naming.NamingException { Properties p = new Properties( ); // ... Specify the JNDI properties specific to the vendor. return new javax.naming.InitialContext(p); }
An initial context
is the starting point for any
JNDI
lookup—it’s similar in concept to the root of
a filesystem. The way an initial context is created is peculiar, but
not fundamentally difficult. We start with a properties table of type
Properties
. This is essentially a hash table to
which we add various values that determine the kind of initial
context you get. Of course, as mentioned in Chapter 4, this code depends on how our EJB vendor
has implemented JNDI. For example, with the
Pramati Application Server,
getInitialContext( )
might look something like
this:
public static Context getInitialContext( ) throws Exception { Hashtable p = new Hashtable( ); p.put(Context.INITIAL_CONTEXT_FACTORY, "com.pramati.naming.client.PramatiClientContextFactory"); p.put(Context.PROVIDER_URL, "rmi://127.0.0.1:9191"); return new InitialContext(p); }
For a more detailed explanation of JNDI, see O’Reilly’s Java Enterprise in a Nutshell by David Flanagan, Jim Farley, William Crawford, and Kris Magnusson.