COMMON SERVICES FOR DISTRIBUTED ENTERPRISE COMMUNICATIONS
1. COMMON SERVICES FOR DISTRIBUTED
ENTERPRISE COMMUNICATIONS
Naming Services
Directory and Trading Services
Activation Services
Messaging Services
Transaction Services
2. Naming Services
• Naming Services in a Nutshell
• JNDI Naming Services
• Naming Files
• CORBA Naming
• RMI Naming
• DNS
• DCOM Naming
A naming service is the principal mechanism used in distributed and
nondistributed systems for referring to objects from within your
applications via a name identifying that object.
The term name used here typically means a name that is human
readable or at least easily converted into a human-readable String
format.
A file system uses filenames when doing out references associated
with file media to programs requesting access to those files.
3. Similarly, CORBA clients can use object names to obtain
handles to CORBA objects, which reference objects that
may be sitting in some remote system process. These
name-to-object associations are referred to as name
bindings.
A name binding is always defined relative to a naming
context. Here, a naming context encapsulates a domain of
names in which each name binding in that naming context
is unique.
use a naming service to either explicitly or implicitly bind
object references to names and resolve names to objects.
The Java Naming and Directory Interface (JNDI)
component of the J2EE is described as the primary means
for hooking into naming systems from enterprise Java
applications.
4. To learn:
Naming service–related concepts such as compound and
composite names, name bindings, naming contexts, and the
common roles of a name service.
The architecture, API components, and use of Java's framework
for commonly accessing various naming services via the Java
Naming and Directory Interface.
Why a file system is a naming service and how to use JNDI to
access your file system.
The architecture of a CORBA Naming Service (CosNaming) and
the access of aCosNaming Service via JNDI.
How to access the RMI Registry via JNDI.
How to use JNDI with RMI/IIOP.
The architecture of the Internet's domain name system (DNS)
and how to look up an IP address given a DNS name.
The DCOM equivalent for implementing the role of a naming
service.
5. Naming Services in a Nutshell
Naming services provide a way for you to write code
that refers to objects in a system using human-
readable names. Names very often have a string form
enabling you to write code that is more readable, as
well as providing you with a simple way to obtain an
initial handle to an object.
Handles, names, and the context in which names are
scoped are all fundamental concepts relevant to an
understanding of naming systems.
6. Handles
An object in a system corresponds to an instance in memory or
some range of addresses relating to some discrete collection of
functions or data. "Handles" to such objects are often referred to
as references or pointers
Such handles can be associated with objects residing in a
process local to your current execution environment or with
distributed machine.
Handles are often not human readable, frequently are
numeric by nature, perhaps have some embedded
communications protocol-specific information, sometimes are
platform-dependent, and usually are dependent on the current
execution environment.
7. Names
A name is simply a logical and generally human-readable value
for referring to an object in both distributed and nondistributed
systems. Here are some examples of what a name can be:
A filename string referring to a file object reference.
An Internet hostname string referring to a machine on the Internet.
An object service name referring to a CORBA server object on a remote
machine.
Each name is expressed in a syntax understandable by the naming
system for which it is relevant (for example, the file system, the
Internet, a CORBA Naming Service). Each naming system has its
own naming convention syntax for which valid names are
expressed.
Thus, for example, a Windows file-naming system requires absolute
filenames to be expressed in terms of a root drive and semicolon
with directory names separated by backslashes () and ending with
a filename and extension (for example, C:MyDirmyFile.txt)
Each name- to-object association is typically referred to as a name
binding.
For example, given the object instance name hallwayPrinter from
NetworkPrinter hallwayPrinter = new NetworkPrinter();
8. Naming Contexts and Systems
Names always have some meaning in a specific
context. For example, the name "Leesburg"designates
a U.S. city in the states of Virginia, New Jersey,
Florida, Georgia, Alabama, Indiana, and Ohio. The
fully qualified name of "Leesburg, Virginia, USA"
pinpoints the name "Leesburg" to the context of
"Virginia, USA."
The same need for referring to names within some
context also applies to computer systems.
10. In Figure 1, whereas the name index.html on your computer hosting
a Web server refers to a specific file you have created in the directory
C:public_html, this same filename in your Web server's directory
C:public_htmlsales refers to an entirely different file object. The
name index.html has to be put in context to determine what specific
file object is being referenced.
Each context thus holds a set of name-to-object bindings in which
the object may be an actual system resource (for example, file
object) or perhaps another context (that is, a subcontext). Each
context will have its own standard for naming the objects and
subcontexts to which it binds names.
A naming system serves to provide a standard for managing a set of
contexts with the same naming convention and with similar means
for binding names to objects and resolving objects to names.
Many systems such as the Lightweight Directory Access
Protocol (LDAP), the Network Information System (NIS), and
the Novell Directory Service (NDS) provide the name binding
and resolving functionality of naming services
11. JNDI Naming Services
The Java Naming and Directory Interface (JNDI)
provides a standard Java interface-to- naming system
that can be used with various types of underlying
naming systems. JNDI can also be used to name and
reference objects that lie outside of a particular
naming system.
Furthermore, JNDI also provides interfaces for
encapsulating and handling events that can be
generated from a naming service.
13. As depicted in Figure 2, JNDI is a Java extension and a
fundamental component of the
J2EE, providing a standard way to interface with many naming
services and directory services.
JNDI provides a Java API for commonly interfacing with any
naming or directory service for which there exists an adapter to
map JNDI API calls to the specific calls provided by the
particular naming or directory service provider.
All calls to the JNDI API are properly delegates to the particular
service via the adapter. This adapter is referred to as a Service
Provider Interface (SPI). SPIs are provided by Sun
Microsystems
The JNDI class libraries are included as a core component of the
J2EE and the J2SE v1.3.
14. The JNDI class libraries are partitioned into the following
packages:
• javax.naming: Contains all the core JNDI API classes and
interfaces used by Java applications needing access to various
naming services.
• javax.naming.directory: Contains the JNDI API classes
for performing more sophisticated directory-service
functionality extending the basic naming-service functionality.
• javax.naming.event: Contains the JNDI API classes and
interfaces for providing event notification services for naming
and directory systems.
• javax.naming.ldap: Contains the JNDI API classes and
interfaces for specific support of the more advanced
management features of the LDAPv3 standard when using the
LDAP SPI.
• javax.naming.spi: Contains the JNDI SPI classes and
interfaces for implementers of SPIs to map standard JNDI API
calls to a particular naming or directory service.
15. Naming Objects
Before a naming service can be utilized, JNDI clients need to obtain
handles to an initial JNDI context. Names can then be bound to
objects, and objects can be looked up relative to such a context
using standard JNDI interfaces.
Names have a syntax that can be described using regular Java
String objects or using some of the interfaces provided by JNDI to
encapsulate names.
JNDI Contexts
The JNDI client API user will first be required to create a reference to
an initial context of the naming service of interest.
This initial context creation process establishes a connection with the
service when constructed with a set of properties describing the
specific naming or directory service provider library to use, the URL of
the naming or directory service process, and perhaps a username and
user credentials.
Other properties may also be set whose names are defined as static
public attributes in the javax.naming.Context interface. A
javax.naming.InitialContext class implementing the Context
interface can be used to create an actual handle to a particular naming
service. The valid static public properties are defined in Table 1.
16. Out of all properties defined in Table 1, the first two
properties (INITIAL_CONTEXT_FACTORY and
PROVIDER_URL) will probably be the most commonly
used properties in your programs. The creation of an
InitialContext is therefore typically straightforward:
Properties properties = new Properties();
properties.setProperty(Context.INITIAL_CONTEXT_F
ACTORY,
"com.sun.jndi.fscontext.RefFSContextFactory");
properties.setProperty("PROVIDER_URL",
"file:C:public_html"); Context context = new
InitialContext(properties);
17. Surround the context closing within a finally block to ensure that it is
called:
try{
…
}
catch(…){
…
}
finally{
try{
context.close();
}
catch(NamingException ex){
…
}}
Subcontexts can be created and removed using the InitialContext
createSubcontext() and destroySubcontext() methods,
respectively. Subcontexts can be looked up by using the lookup()
method, with the subcontext name defined according to whatever
naming convention is employed to separate components of the
name,such as this:
Context salesBrochureContext = context.lookup("salesbrochures");
18. JNDI Binding and Lookup
After a context reference is obtained, an object from the server
side can be bound to the context in a standard fashion using the
bind() and rebind() methods.
The difference between bind() and rebind() is simply that
rebind() overwrites any existing bindings, whereas bind()
throws an exception. As an example of a rebind call, we have
this:
String eProducts = "eProducts.html";
Brochure eProductBrochure = new Brochure();
…
salesBrochureContext.rebind(eProducts, eProductBrochure);
From the client side, a lookup of a particular object yields a
reference to that object which is simply cast to the object of the
appropriate type:
String eProductsName = "salesbrochureseProducts.html";
Brochure brochure = (Brochure)
context.lookup(eProductsName);
19. JNDI Names
Binding objects to names and looking up objects given a name
can be accomplished using a String form of a name, as well as
using a class implementing the javax.naming.Name interface.
A Name is composed of a sequence of name components. Name
objects provide a more type-safe means to manipulate names
according to the syntax convention of the particular naming
system with which the name is associated.
One can add and remove name components as well as
accomplish other helper operations on names given a Name
interface implementation.
The CompoundName class implements the Name interface for
names that are confined within a single hierarchical naming
system.
A set of properties can be passed into the CompoundName
constructor. These are the valid properties that can be passed
into the CompoundName constructor:
20. jndi.syntax.direction: Parsing direction such as left_to_right, right_to_left, or
flat.
jndi.syntax.separator: Separator to use between name components (for
example, / or .).
jndi.syntax.ignorecase: Name components are case-insensitive if true.
jndi.syntax.escape: Escape string for overriding separators (for example, /).
jndi.syntax.beginquote: Beginning of quote delimiter.
jndi.syntax.endquote: Ending of quote delimiter.
jndi.syntax.beginquote2: Alternative begin quote.
jndi.syntax.endquote2: Alternative end quote.
jndi.syntax.separator.typeval: Name-value separators (for example, = as in
mfg=Dodge).
jndi.syntax.separator.ava: Name-value pair separator (for example, , as in
mfg=Dodge,make=Raider,color=red).
jndi.syntax.trimblanks: Leading and trailing whitespace of a name is trimmed if
true.
For example, the following String may be parsed into a compound name using
the
CompoundName class:
String name = "PrinterPublicGroup.Printer19";
CompoundName cName = new CompoundName(name,
rmiNamingProperties);
21. JNDI Context Listings
The contents of a JNDI naming service may also be listed using the list()
and listBinding() methods defined by the Context interface and
implemented by InitialContext.
The list() method requires a name parameter identifying the particular
context level at which to search for name service bindings. The list()
method returns a javax.naming.NamingEnumeration of
javax.naming.NameClassPair objects in which each NameClassPair
represents an object name and its classname of an object bound at the
desired context level. For example (exception handling excluded)
NamingEnumeration namesList = context.list(someContextName);
…
while(namesList.hasMore()){
NameClassPair pair = (NameClassPair) namesList.next(); String
objectName = pair.getName();
String className = pair.getClassName();
…
}
22. In addition to returning the object name and its associated classname,
the listBindings() method call on a context returns the actual bound
object as well. Given the particular context level to list, the
listBindings() method returns a NamingEnumeration of javax.naming.
Binding objects that extend NameClassPair objects with the capability
to store and retrieve the object bound at the listed context level.
For example, to retrieve each name, classname, and bound object from
a NamingEnumeration returned from a listBindings() call, we would
use this:
NamingEnumeration namesList =
context.listBindings(someContextName);
…
while(namesList.hasMore()){
Binding binding = (Binding) namesList.next();
String objectName = binding.getName(); String className =
binding.getClassName();
MyObject obj = (MyObject) binding.getObject();
…
}
23. Referenceable Objects
Aside from binding and looking up object references in a
naming system using names via JNDI, JNDI also provides
support for binding and looking up references to objects that sit
somewhere outside of the naming system (that is, referenceable
objects).
A referenceable object, in JNDI lingo, is an object with a
reference that can be stored in a JNDI service with information
telling JNDI how to associate lookups for that object to the
object itself.
Referenceable objects can be useful when an object not
belonging to any particular naming system needs to be bound
to a naming service for ease of lookup. Referenceable objects are
also useful when an object from one naming system needs to be
bound to an entirely different naming system.
A referenceable object is first created by implementing the
javax.naming.Referenceable interface. The Referenceable
interface has one method called getReference(), which returns
a handle to a javax.naming.Reference object.
24. For example, some com.beeshirts.customer.Customer class that
you've defined may implement the getReference() method as
shown here:
public javax.naming.Reference getReference()
throws NamingException
{
String className = "com.beeshirts.customer.Customer";
String factoryName =
"com.beeshirts.customer.CustomerFactory"; String contents =
this.getAsString(); // Get state as a String
javax.naming.StringRefAddr refAddr
= new javax.naming.StringRefAddr("Customer", contents);
return new javax.naming.Reference(className, refAddr,
factoryName, null);
}
25. After binding the Customer referenceable object, the naming service
can reconstruct the object during a lookup by consulting the
com.beeshirts.customer.CustomerFactory object factory
implementing the getObjectInstance() method like this (excluding
error handling):
public Object getObjectInstance(Object obj, Name objName,
Context objContext, Hashtable objEnv)
throws Exception
{
javax.naming.Reference reference = (javax.naming.Reference) obj;
javax.naming.StringRefAddr refAddr
= (javax.naming.StringRefAddr) reference.get("Customer");
String contents = (String) refAddr.getContent(); Customer customer=
new Customer();
customer.setAsString(contents); // Reconstructs state from a String
return customer;
}
26. Naming Events
JNDI also now provides (as of JNDI v1.2) an infrastructure for
encapsulating and handling naming and directory service events.
Naming and directory services can generate naming- related events
such as the renaming of an object, the removal or addition of an
object from or to the naming service, and the state change of an
object registered with the naming service.
The javax.naming.event.NamingEvent class represents an event
that can be generated from a naming service when one of its registered
objects changes. NamingEvent objects extend the standard
java.util.EventObject; they have a type and contain an event source,
SPI-specific change information, and a reference to binding
information both before and after the event.
The source of an event is a context implementing the
javax.naming.event.EventContext interface. An EventContext is
simply a type of Context that allows for the addition and removal of
listeners interested in naming events. A special javax.naming.event.
NamingExceptionEvent event object can also be generated in the
event of a failure during the generation of a normal naming event for
notifying naming listeners
27. EventContext eventContext = // Construct an event context
NamespaceChangeListener customerManager = // Construct a listener
eventContext.addNamingListener("AllisonPerrone",EventContext.OBJ
ECT_SCOPE, customerManager);
Either the javax.naming.event.ObjectChangeListener or the
javax.naming.event. NamespaceChangeListener sub-interfaces of
NamingListener typically is implemented to handle generated naming
events.
The ObjectChangeListener interface is implemented to handle events
associated with an object's state change
(NamingEvent.OBJECT_CHANGED), such as attribute addition,
deletion, or modification, as well as the replacement of an object in
the naming system.
The NamespaceChangeListener interface is implemented by those
objects wanting to handle the addition
(NamingEvent.OBJECT_ADDED), removal (NamingEvent.
OBJECT_REMOVED), or renaming
(NamingEvent.OBJECT_RENAMED) of objects registered with the
naming service.
28. As an example of a naming event listener, the following skeleton structure implements
methods for handling both object change and namespace change naming events:
import javax.naming.event.NamespaceChangeListener;
import javax.naming.event.ObjectChangeListener;
import javax.naming.event.NamingEvent;
import javax.naming.event.NamingExceptionEvent;
public class SampleNamingListener
implements NamespaceChangeListener, ObjectChangeListener
{public void objectAdded(NamingEvent namingEvent)
{
// Handle object addition
}public void objectRemoved(NamingEvent namingEvent)
{
// Handle object removal
}public void objectRenamed(NamingEvent namingEvent)
{
// Handle object renaming
}public void objectChanged(NamingEvent namingEvent)
{
// Handle object attribute changing
}public void namingExceptionThrown(NamingExceptionEvent
namingExceptionEvent)
{// Handle naming exception
}}
29. Naming Files
The file-naming system is the most basic and common naming
system that computer users encounter. In a file-naming system,
filenames correspond to the names of the naming service, file-
system directories correspond to the contexts that make up
names, and the file objects and descriptors correspond to the
handles of the system resource of interest.
Different file systems will have different naming syntax
conventions. Thus, whereas Windows-based file systems use
the backslash () to separate context-space (that is, directories)
and components of a name, UNIX-based systems use the
forward slash (/). Similarly, Windows- based systems ignore
differences between upper- and lowercase, whereas UNIX-based
systems are case-sensitive.
30. File-System Interfaces
Figure 19.6. Traditional Java file-system interfaces.
Before JNDI, the most common and obvious way to
interact with a file system was to use the classes available
in the java.io package, as shown in Figure 6. The Java 2.0
platform has provided many enhancements to the java.io
package, including a host of new methods added to the
java.io.File class.
The File class encapsulates an interface to a file system's
files and directory paths. Operations such as file renaming
and deleting, as well as directory listing, can be achieved
via the File class. The FileInputStream and
FileOutputStream classes can be used to create new files,
as well as populate such files with data or reading files. The
FileReader and FileWriter classes can also be used to read
and write character files.
31. JNDI File SPI
A file-system SPI exists for use with the JNDI API and is freely
downloadable from the Sun Web site. Many developers may still
elect to use the core Java support for file manipulation via use of
the file streaming and reader/writer APIs provided in the java.io
package.
In fact, the JNDI file SPI provided by Sun actually heavily
depends on the java.io.File class. However, use of a JNDI file-
system SPI has its advantages by providing classes and
interfaces for making file management more flexibly
independent across different file-system types (depending on
your underlying SPI implementation), as well as providing a
standard interface to the file system that can be used even in a
composite naming scheme.
32. CORBA Naming
The OMG's CORBA Naming Service (also called Object
Naming Service and CosNaming) presents the primary and
standard way for mapping between names and objects on a
CORBA ORB.
The Object Naming Service was proposed by the OMG as a
means to provide a standard interface to various underlying
naming services.
It serves as the language-independent and standard way to wrap
existing name servers for connectivity from various clients.
Although the JNDI API has some similarities to the Java
mapping of the CORBA Naming Service API, it is not identical.
your Java client will use JNDI with a CORBA SPI that maps calls
to a CORBA name server. The server in turn actually maps
CORBA Naming calls to a naming service that could have been
directly communicated with from your Java application
33. CosNaming IDL
Names in CORBA are sequences of name components.
A name with a single component is referred to as a simple name,
whereas a name with more components is called a compound name.
Name components are defined by an ID and a kind. The "kind"
attribute of a name simply serves to classify names for use by
application software. Each ID is unique within a particular naming
context.
Naming contexts in CORBA contain a list of names that are all
unique to that context in which each binding has a binding type
indicating whether the name is bound to either a CORBA object or
another naming context, do not need to be associated with logical
names.
Operations on naming contexts include binding and rebinding names
to objects, resolving objects given a name, unbinding objects, creating
subcontexts, and listing names associated with the context.
The CosNaming module shown in Listing 4 defines the CORBA
Naming Service IDL interfaces.
34. The CORBA Naming Service specification also
provides for the efficient representation of names with
a names library pseudo-IDL (PIDL) specification as
shown in Listing 5.
The names library is implemented in the CORBA
client's native language. These client-side libraries
provide the client with a lightweight means for
manipulating names in which the names actually refer
to CORBA pseudo-objects
35. CosNaming Service Implementations
The CORBA name service used "CORBA Communications," and "RMI
Communications," was the transient name service that comes equipped with
Java IDL and RMI/IIOP.
The command tnameserv is used to start the CosNaming-compliant name
service on a particular machine on the default port 900.
The command-line flag -ORBInitialPort <PortNum> may also be used to run
the name service on a different port number.
From within your CORBA client and server applications, a handle to the name
service can be retrieved using the
org.omg.CORBA.ORB.resolve_initial_references() method.
If the name service is run on a new port number other than the default, naming-
service clients must set the org.omg.CORBA.InitialPort property associated
with the ORB object.
The term transient is used in referring to the tnameserv naming service to
highlight the fact that all name/object binding information is lost whenever the
naming service terminates. Other naming-service options do exist, however.
36. Most commercial CORBA vendors provide Java-
based, CosNaming-compliant naming services such as
these:
IONA Technologies'OrbixWeb Orbix Names
(http://www.iona.com/products/orbix/names.html)
Inprise's VisiBroker Naming Service
(http://www.borland.com/visibroker/cosservices/)
Prism Technologies'OpenFusion Naming Service
(http://www.prismtechnologies.com/products/openf
usion/products/naming -service.html)
37. CORBA Naming Interfaces
Figure 7 presents the key programmatic interfaces to a
CosNaming service. Only key components are shown; the helpers
and holders associated with the various interfaces are not shown
to simplify the diagram.
By narrowing an initial reference to the NameService returned
from the ORB, we can obtain a handle to a NamingContext
interface like this:
ORB orb = ORB.init(args,null);
org.omg.CORBA.Object namingRef =
orb.resolve_initial_references("NameService");
NamingContext namingContext =
NamingContextHelper.narrow(namingRef);
38. A CORBA server can then be registered from the server side by first creating a
NameComponent array (that is, a CORBA name) and calling bind() or rebind()
on the NamingContext reference as such:
MyMessageImpl server = new MyMessageImpl();
NameComponent nameComponent = new NameComponent("SampleServer",
"");
NameComponent nameComponent1 = new
NameComponent("SampleServer2", ""); NameComponent path[] = {
nameComponent , nameComponent1 }; namingContext.rebind(path, server);
A CORBA client obtains an initial reference to a naming service in the same
fashion as a CORBA server. The CORBA client can then use the naming
context to look up the object reference given the CORBA name as shown here:
NameComponent nameComponent = new NameComponent("SampleServer",
""); NameComponent nameComponent1 = new
NameComponent("SampleServer2", ""); NameComponent path[] = {
nameComponent , nameComponent1 };
MyMessage obj = MyMessageHelper.narrow(namingContext.resolve(path));
39. JNDI CosNaming SPI
A CosNaming JNDI SPI exists as part of the J2EE v1.2 and can also be
downloaded separately for use with the J2SE v1.2. When you interface
with the CosNaming service directly, you need to understand a host of
CosNaming-specific APIs.
By using JNDI with a CosNaming SPI, you are provided with a
standard way (as a Java developer) to interact with a host of naming-
service interfaces, and thus it is not necessary to learn all the
semantics specific to CosNaming.
The Sample.idl file in Listing 6 exports a simple "Hello-World"
sample method embedded inside of a Message interface. The
SampleCosNamingServer of Listing 7 implements this interface and
also registers the server with a CosNaming server via JNDI.
After a Message server is bound to two different names from within
the SampleCosNamingServer.bindWithDifferentNames() method, the
SampleLookupExample, SampleListAndSearchExample, and
SampleBindingExample programs are all run to illustrate usage of the
generic JNDI API with a CosNaming system.
40. RMI Naming
RMI also has a means to bind objects to names and look up object
references via a name. As we saw "RMI Registration" and "RMI
Lookup," both RMI/JRMP and RMI/IIOP had distinct ways to
communicate with a naming service. Of course, RMI/IIOP used the
CosNaming service interfaces. RMI/JRMP used the built-in RMI Registry
interfaces.
RMI Naming System Interfaces
The RMI Registry provides a simple mechanism for interfacing with a
naming service, but it is dependent on RMI/JRMP, which is a Java-
centric means for distributing objects.
RMI/IIOP uses a CosNaming server, and thus you can both create
RMI/IIOP clients to communicate with CORBA servers implemented in
another language and implement RMI/IIOP servers that can offer their
services to a language-independent community of CORBA clients.
The CosNaming service that implements the CORBA Naming Service
interface and supports the special ORB extensions required of RMI/IIOP.
41. JNDI RMI SPI
An RMI Registry JNDI SPI that works with RMI/JRMP is shipped
with J2EE products and is separately downloadable for use with
the J2SE v1.2.
RMI/IIOP-based applications can use a CosNaming JNDI SPI.
Because our sample RMI/IIOP applications are dependent on
the tnameserv CosNaming service provided with RMI/IIOP,
our RMI/IIOP applications also depend on use of the
CosNaming SPI provided by Sun to work with the tnameserv
CosNaming service.
The Sample.java RMI interface in Listing 8 exports a simple
"Hello-World" example RMI method implemented by both the
RMI/JRMP server (SampleJRMPServerUsingNamingContext) of
Listing 9 and the RMI/IIOP server (SampleRMIIIOPServer) of
Listing 10.
42. DNS
No JNDI SPI for the domain name service existed. This section thus focuses on a
description of the DNS and describes existing intermediate means for Java
applications to perform some minimal DNS name management functionality.
The level of support via Java is currently limited to half-baked, simple lookups.
The Domain Name System
The DNS provides a translation of the hierarchically defined machine
hostnames that we are all familiar with (for example, www.yahoo.com) to and
from IP addresses (for example, 204.71.200.68).
DNS names have a syntax convention and map to IP addresses that are logical
addresses of network devices or hosts. These IP addresses are used by network
routing elements to determine how to deliver IP-based messages to a host
machine.
By using human-readable and structured names, the task of the developer is
simplified and less dependent on a priori knowledge of the internals of routing
tables and machine configurations.
The names in DNS adhere to the syntax convention of case-insensitive name
components separated by dots (.). Parsing of the names occurs from right to left
with the rightmost name component corresponding to a top-level domain
context. Many organizations use the set of top-level domain names presented in
Table 2.
43. Additionally, a country code can also serve as a top-level domain name, such
as the code US for United States–based organizations. Names are then created
according to this standard format:
<Entity Name>.<Locality>.<State Code>.US
For example AssuredTech.Leesburg.VA.US
A subdomain is prepended to a top-level domain name with a dot as a
separator to formulate a "registered" domain name. Thus, yahoo.com is a
registered domain with yahoo as the subdomain and com as the top-level
domain.
Regionally designated authority to grant "registered" domain names is
provided by Internet Resource Registries such as with Network Solutions,
Inc.'s management of all .com, .net, and .org top-level domains.
An organization that has registered a domain name with an Internet Resource
Registry can then create various subdomains for the registered domain name.
These subdomains can be organized in any way according to the
organization's liking such as sales.myCorp.com and products.myCorp.com.
Hostnames for machines within these subdomains can then be assigned. Thus,
joeSalesman.sales.myCorp.com and elPresidente.myCorp.com
<Hostname>.< Optional One or More Dot-Separated SubDomains>.<Registered
Domain Name>
44. A DNS server can run DNS software offered by various COTS
packages on various platforms.
A popular implementation for UNIX systems is the Berkley
Internet Name Domain (BIND) package, which has also been
ported to Windows platforms (http://www.isc.org/bind.html).
Each host in the domain must be configured to know the IP
addresses of the local DNS servers or be configured to refer to a
Dynamic Host Configuration Protocol (DHCP) to help
locate the local DNS servers.
When a TCP/IP request is made with a hostname, the TCP/IP
protocol consults the DNS server with which it has been
configured to look up the IP address with the associated
hostname. If a DNS server cannot resolve a hostname to an IP
address, it forwards the request to another DNS server.
45. Java-Based DNS Interfacing
The primary way to interact with the DNS via Java right now is
by use of the java.net.InetAddress class to look up an IP
address given a hostname. Three static methods defined on
InetAddress can be used to return InetAddress object instances:
InetAddress getByName(String hostName) returns a handle to
an InetAddress object given an IP Address in the form X.X.X.X
(for example, 209.207.135.133) or a machine name String (for
example, http://www.assuredtech.com).
InetAddress[] getAllByName(String hostName) returns a handle
to an array of all known InetAddress objects for a particular
hostName defined as in the getByName() call.
InetAddress getLocalHost() returns a handle to an InetAddress
object for your local host machine.
46. After an InetAddress object is returned, the following calls can
be used to obtain host naming and IP address information for
use by your applications:
String getHostName() returns a String defining the hostname
associated with this IP address by performing a DNS lookup.
String getHostAddress() returns a String containing the IP
address in the form X.X.X.X.
byte[] getAddress() returns a byte array of the IP address in
network order with byte[0] as the most significant byte.
Thus, the InetAddress.getHostName() call is where the DNS
lookup really transpires. All three static InetAddress methods
and the getHostName() method map to native calls from your
Java platform implementation to your specific machine's DNS
TCP/IP client libraries.
47. DCOM Naming
Although DCOM provides APIs that do support naming of DCOM
classes and some support for stateful DCOM object naming, the
mapping of these APIs to Java-based programs has produced a
somewhat cumbersome, DCOM-equivalent naming service interface.
DCOM Class Naming with CLSIDs and ProgIDs
DCOM Class Identifiers (CLSIDs) are used to uniquely identify a particular
DCOM class. The DCOM class identified by a CLSID refers to a collection of
DCOM interfaces implemented by that class.
The DCOM com.ms.win32.Ole32.CoCreateInstance() API call uses this
CLSID when looking up and registering DCOM objects with the Microsoft
Windows Registry.
Java-based DCOM server objects can be registered for distributed access using
the javareg utility with the /surrogate parameter.
The Java-based DCOM server also needs to be defined with a static final CLSID
String . General DCOM clients can obtain a pointer to the DCOM object using
the CLSID passed as a parameter to the CoCreateInstance() DCOM API call.
Java-based DCOM clients using the Microsoft JVM can simply instantiate an
instance of the DCOM object (for example, QueryManager ) with the new
operator and then cast the object to a DCOM interface (for example,
IQueryManager ):
IQueryManager query = (IQueryManager) new
com.beeshirts.QueryManager();
48. The casting to a particular interface by the client also cues the
Microsoft JVM to call QueryInterface() to determine whether
such an interface is supported by this DCOM class and to obtain
the interface reference.
The Windows Registry stores the hostname of the remote
implementation, as well as the remote implementation
classname used during a call to CoCreateInstance(). Direct calls
to the CoCreateInstanceEx() call permit passing of a particular
hostname.
The COM libraries make calls to the Service Control Manager
(SCM) to activate the remote object. The SCM on the client
machine makes a call to the SCM on the server machine. The
server SCM then uses COM libraries to activate the remote
object and return the remote reference.
Program identifiers (ProgIDs) can be used to define a
human-readable name for a DCOM class. ProgIDs follow the
format <Program>.<Component>.<Version>.
49. The DCOM com.ms.win32.Ole32. CLSIDFromProgID() API
call takes ProgIDs that map to CLSIDs. Such a CLSID can
then be used with the CoCreateInstance() API call to
obtain a handle to the object as shown here:
String name = "QueryManager.Application";
myGuid = // set appropriate Guid type
type = // set type of COM Server
com.ms.com._Guid objCLSID =
com.ms.win32.Ole32.CLSIDFromProgID(name);
Object comObject =
com.ms.win32.Ole32.CoCreateInstance(objCLSID, null,
type, myGUID);
50. DCOM Object Naming with Monikers
CLSIDs and ProgIDs are useful only for registering and looking
up DCOM classes and interfaces. Because DCOM objects are
stateless by default, a different mechanism is needed in order to
register actual stateful object instances to be retrieved later by a
distributed DCOM client. To a certain extent, DCOM monikers
provide this capability.
Monikers in DCOM can be used to obtain a handle to an object
previously created.The interface used to define a moniker is the
com.ms.com.IMoniker interface, as shown in Listing 11.
If a client has a handle to an IMoniker interface, the client can
refer to an existing server. The IMoniker object consults the COM
libraries'running object table (ROT) to find an underlying
reference to the actual running server. If IMoniker can not find a
server in the ROT, it will create a handle to a new one from a
persistent store. IMoniker objects derive from a
com.ms.com.IPersistStream object and can be persisted
51. The BindToObject() call on an IMoniker object executes the
bind to a stateful DCOM object. Some predefined IMoniker
objects are equipped with the COM libraries. Of course, the
semantics of the BindToObject() call are specific to the object
implementing the IMoniker interface.
IMonikers can also be associated with a binding context similar
to the fashion in which names can belong to a naming context.
IMoniker objects have human-readable display names
retrievable from the GetDisplayName() call. Displayed moniker
names are of this general form:
<TypeName>:<InstanceName>.
The ParseDisplayName() API call can be used to parse a
moniker's display name into a DCOM object instance IMoniker
interface. The ProgID used in the display name is converted to a
CLSID, and then an IMoniker reference associated with this
CLSID type is returned.
52. Conclusions
Naming services fulfill a basic distributed enterprise
Communications need for mapping between names in a
context and object references. Given an object reference, a
server can bind this object to a name in a naming service, and
given that name, a client can look up the object reference in the
naming service.
JNDI is a core component of the J2EE that provides a standard
interface for enterprise Java applications to access naming
services. JNDI naming- service providers exist for file
systems, RMI applications, and CORBA programs.
Mapping Internet DNS names to IP addresses is also possible
from within Java. Finally, DCOM also provides a means for
mapping between names and object references using its
communications paradigm. Beyond mere mapping between
names and objects, characteristics about such objects can
also be associated with an extended form of naming
system known as a directory or trading system.