HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

Two months ago (JDJ, Vol.2, Iss. 2), Ellen Siegel gave a very nice introduction to CORBA from a Java point of view. This article is focused on a more specific topic which often occurs to newcomers to the CORBA world: How do I discover the objects I want to use?

Identification of an Object
To answer this question, we must first establish how we identify an object. Similarly to Java, CORBA identifies objects by an object reference. An object reference is an opaque datatype which contains all the information needed to successfully invoke an operation on the object (even when the object has been relocated). The CORBA 2.0 Specification defines Interoperable Object References (IORs) which enable object identification across ORB boundaries.

In the Java language mapping, an IDL-defined interface is mapped to a Java interface. A client declares a variable of the Java interface, obtains an actual object reference and can immediately invoke operations on the object. Table 1 shows a sample IDL interface and some corresponding client Java code.

Table 1

Various Methods
How do clients obtain a reference to an actual object. There are various ways that provide different levels of sophistication to solve the problem and to fill in the code that is missing right after the bold printed comment in Table 1.

Stringified Object Reference
Object references can be persistified. That means the opaque data type is converted into a string representation. This string is often called a stringified object reference. A stringified object reference can be stored in a file or database, or can be sent via e-mail, posted to a newsgroup or published on a Web page. A stringified object reference can be re-converted into a "life" object reference.

The ORB provides a pair of operations for stringifying and de-stringifying object references. Their Java notation is shown in Listing 1.

If an object publishes its stringified object reference and the client gets the reference (e.g., by passing it as command-line parameter or reading it from a file), the client can re-convert it to a real object reference by calling object_to_string()on the ORB object. As shown in Listing 1, the method returns an object of type org.omg.CORBA.Object. To use the object, it needs to be narrowed to the right type. The IDL/Java language mapping defines a Helper class called InterfaceNameHelper which contains, among other helper methods, the narrow method. Listing 2 shows the client code using a stringified object reference to identify the object the client wants to invoke.

Passing Object References
Object references can be passed as arguments to operations. Once an object has received an object reference it can invoke any operation on this object. A special case of this mechanism is the callback. A callback means that a client creates an object and passes its object reference as argument of an operation. The invoked object then has knowledge of the client-object and can invoke an operation on it. This is known as a call back to the client.

Passing object references as operation arguments does not solve the problem of establishing an initial connection. However, it is a widely used technique to propagate knowledge of objects within an application.

CORBA Naming Service
A more sophisticated way of obtaining object references is to use the CORBA Naming Service. The OMG has adopted a number of specifications for fundamental service. Those services are branded as CORBAservices and the Naming Service is one of them. Other CORBA services include the Object Trading Service (see Figure 1), the Event Service and the Object Transaction Service.

Figure 1
Figure 1:

The Naming Service is similar to the telephone white pages. An object registers its object references under a certain name and potential clients can look up the object reference by the name. The Naming Service's name space is, unlike the white pages' one, not flat. Names can be grouped in contexts which play a similar role as directories in file systems. Figure 1 illustrates a configuration of various naming contexts.

Contexts are CORBA objects and a Naming Service is a process which hosts one or more context objects. Linking contexts across the boundaries of their respective Naming Services means the federating of those Naming Services. Figure 1 also illustrates the federation of two Naming Services, Foo and Bar. The Context objects hosted by the service provide the interface to bind, unbind and look up application objects and other context objects.

It makes sense to organize the naming graph which is created by binding contexts together as a tree or rooted graph. Users then have a root context as a starting point. Different classes of users can have different starting contexts which are only the root of a sub-tree or sub-graph.

Names which refer to an object are relative to a starting context and involve the names of sub contexts and finally, the name of the application object. Technically, a name is a sequence of name components which are a pair of an identifier and a kind field (both of type string).

The Java class called EasyNaming simplifies the use of names. It allows you to register and look up names using a notation similar to the one known from file systems. EasyNaming would allow you to register and look up our object under the name "/X/Y/YA/FooBar". The implementation of EasyNaming can be found at http://www.wiley.com/compbooks/vogel/examples.

In our example, assume the GoodDay object is registered under a certain name. The construction of the name in the code example has been omitted because it is a bit lengthy. Also, assume that the client has a reference to a root context. In Listing 3, we discuss how to deal with this boot strapping problem. The client can now look up the object using its name.

Listing 3 shows the relevant code at the client. The context returns an object of type CORBA Object which needs to be narrowed to the right type. To use the CORBA Naming Service, clients and objects must share knowledge about the naming conventions and names of the objects.

CORBA Object Trading Service
The CORBA Object Trading Service, Trader for short, plays the role of the Yellow Pages in the CORBA world. Objects can be looked up by their type, which is called Service Type. The Service Type contains the Interface Type; that is, the IDL definition of the object's interface, and a set of non-functional properties called Service Properties.

For example, a print object might provide an interface offering the following operations: printing a document, looking up the printer queue, cancelling a printer job. Service properties could be the paper sizes available, the resolutions the printer can handle, the location of the printer, postscript capabilities and the price per page (if applicable).

Figure 2 illustrates the basic interactions between client, object and Trader. An object registers itself or is registered by a third party with the Trader. Potential clients can look up objects by specifying a Service Type and further constraints over the properties defined in the service type.

Figure 2
Figure 2:

Traders can be federated; that means, a Trader is linked to another Trader and can forward client queries to those linked Traders. Federated Traders form a trading graph and a federation protocol controls the traversal of that graph to avoid cycles and deadlocks. The federations of Traders provide for sophisticated configuration of trading domains, allowing them to reflect organizational structures, access policies, etc. Figure 3 illustrates two federated Traders where one external Trader holds the references to publicly accessible services and the other, internal, Trader holds references to the objects with restricted access. Of course, internal clients using the internal Trader want to see all objects, but external clients should see only the publicly available objects. The federation scenario shown in Figure 3 satisfies those requirements. Based on the asymmetric character of the link, the internal client's queries are forwarded to the external trader.

Figure 3
Figure 3:

In the Hello World example, assume that the client has a reference to a Trader and that the object is registered with this Trader. Listing 4 shows the client using the query operation on the Trader's Lookup interface to obtain a reference to a suitable object.

Proprietary Mechanisms
Various Java ORB implementations also provide proprietary mechanisms to locate objects. Those mechanisms are similar to the Naming Service, solve the boot-strapping problem and, in some cases, add features.

Visibroker's Smart Agent
Visibroker's Smart Agent is an example of such a proprietary mechanism. For clients, it provides a bind method which comes in various flavors. Objects can be selected by their interface type or selections can be constrained by names and host identifiers, as shown in Listing 5. Visibroker's Smart Agent provides additional features such as load balancing and failure recovery through automatic re-bind to replicas.

The IDL/Java Language Mapping foresees a class called InterfaceNameHelper to hold such proprietary extensions as the Smart Agent's bind methods. Using Visibroker's Smart Agent and the bind method, we can implement the client of our example, as shown in Listing 6.

The Smart Agent works automatically within a local area network (IP subnet). To work across multiple local networks, you must install some very simple configuration files. This, however, creates some interesting issues for clients which are somewhere on the Internet and will be discussed later in a general context.

Although proprietary extensions such as Visibroker's bind mechanisms seem to be quite convenient to use, they have two drawbacks. Clients which use the mechanisms become unportable and non-interoperable. However, this only becomes a problem when one wants to use multiple ORB products in the same project.

URL Name Service
Another example of a proprietary location mechanism is the URL Name Service which is offered by Visigenic and Netscape. However, clients and objects implemented with any ORB can use the URL Naming Service.

An object registers itself under a certain URL with the URL Name Server using a CORBA pseudo object Resolver. The resolver contacts the identified HTTP server using the HTTP put operation. A client uses the bind method of the appropriate Helper class. This is the same method that was explained in the previous section. However, the implementation of the method in this instance checks if the string argument has a URL format and if so, uses the URL Name Service to locate the object. The URL identified resource is a stringified object reference which is reconverted into a life object reference and narrowed to the right type as discussed earlier. Figure 4 illustrates this mechanism.

Figure 4
Figure 4:

In this example, the client calls the bind method similarly to the one shown in Listing 6. However, this time argument is an URL, as shown in Listing 7.

Boot Strapping
To use the Naming or the Object Trading Service, a client has to obtain a reference to a naming context or a Trader's query interface. CORBA defines two operations on the ORB interface which can solve the boot-strap problem. The definition of those operations in Java is shown in Listing 8.

The CORBA services specification defines names for the services; for example, "NameServer" for the Naming Service.

The implementation of those methods is ORB-specific. Configuration is the major issue. There can be more than one instance of a naming and/or trading service, the reference of which object should be returned. There is a joint proposal by IBM, Sun Microsystems and Visigenic Software which introduces an "initialization agent". This agent is defined as a CORBA Pseudo object called InitialReferences. The agent listens by default on port 900 on either the Web server where an applet has been downloaded from or, in the non-applet client scenario, on the local host. An administration interface allows the configuration of the agent with respect to hosts, port numbers and content (i.e., initial services).

Another possibility for boot-strapping is to use stringified object references for basic services. Most ORB implementations allow for persistent object references; i.e., each time the object is re-started it will have the same object reference. If a persistent object reference is used, it seems less problematic to hard-code stringified object references for basic services.

Finally, the proprietary mechanisms can be used for obtaining the initial object references needed to boot-strap an application.

Note: All code examples use th eofficial IDL/Java mapping.

About the Author
Andreas Vogel is a Senior Consultant with Visigenic Software. He holds a MSc and Phd from Humboldt university, Berlin. After holding research positions at the Universityof Montreal and the Distributed Technology Centre (DSTC) in Brisbane, australia, he joined Visigenic. Andreas has worked on distributed systems for more than six years and published over 30 papers in international conferences and journals. He wrote the recent book, "Java Programming with CORBA," with Keith Duddy. Andreas can be reached at [email protected]

	

Listing 1.

public abstract Object string_to_object(String ior)throws SystemException    
public abstract String object_to_string(Object object)throws SystemException

Listing 2

try 
{// initiliaze the ORB 
org.omg.CORBA.ORB orb =org.omg.CORBA.ORB.init();
// get stringified object reference from command line 
Org.omg.CORBA.Object obj = orb.string_to_object( args[1] );
// narrow orb to the right type HelloWorld.
GoodDay good_day = HelloWorld.GoodDayHelper.narrow(obj);
// invoke the operation and print result 
System.out.println(good_day.hello());}

Listing 3

CosNaming.NamingContext root_context;CosNaming.NameComponent[] name;
try 
{// initiliaze the ORB 
org.omg.CORBA.ORB orb =org.omg.CORBA.ORB.init();
I CosNaming.NameComponent[] name;        
//initialise root_context and name (omitted)
// look up the reference by the name 
omg.org.Org.omg.CORBA.Object obj = root_context.resolve( name );
// narrow orb to the right type 
HelloWorld.GoodDay good_day = HelloWorld.GoodDayHelper.narrow(obj);    
// invoke the operation and print result    
System.out.println(good_day.hello());}

Listing 4

CosTrading.Lookup.Ref lookup;
try 
{// initiliaze the ORB  
org.omg.CORBA.ORB orb =org.omg.CORBA.ORB.init();    
// declare variables needed for the query     
// in parameters of the query operation    
String service_type, constr, prefs;
CosTrading.PolicySeq query_pols;    
CosTrading.PolicyValue policy_value;
CosTrading.PropertyNameSeq desired_prop_names;    
CosTrading.Lookup.SpecifiedProps desired_props;int num_offers;    
// out parameters of the query operation 
CosTrading.OfferSeq return_offers;
CosTrading.OfferIterator.Holder iter;
CosTrading.PolicyNameSeq limits;    
// initialise lookup and initialise parameters (omitted)     
// query the Trader lookup.query
( service_type, constr, prefs, query_pols,desired_props, num_offers, return_offers, iter, limits);    
// invoke the operation and print result 
if( return_offers.length > 0 ) {good_day = return_offers[0]; 
System.out.println(good_day.hello());}}

Listing 5.

public static <class_name> bind();public static <class_name> bind(String name);
public static <class_name> bind( String name, String host );
public static <class_name> bind( String name, String host,org.omg.CORBA.BindOptions options );

Listing 6.

try 
{// initiliaze the ORB  
org.omg.CORBA.ORB orb =org.omg.CORBA.ORB.init();    
// bind to GoodDay object    
HelloWorld.GoodDay good_day = HelloWorld.GoodDayHelper.bind();
// invoke the operation and print result    
System.out.println(good_day.hello());}

Listing 7.

try 
{// initiliaze the ORB  
org.omg.CORBA.ORB orb =org.omg.CORBA.ORB.init();    
// get object from URL Naming Service    
HelloWorld.GoodDay good_day = HelloWorld.GoodDayHelper.bind
("http://www.visigenic.com/Examples/HelloWorld/GoodDay.ior" );    
// invoke the operation and print result    
System.out.println(good_day.hello());}

Listing 8.

String[] list_initial_references()
org.omg.Org.omg.CORBA.Object resolve_initial_reference
( String identifier ) throws org.omg.CORBA._ORB.InvalidName


 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.