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
 

While it is easier to write CORBA applications in Java than in any other language, there are still a few conceptual stumbling stones that Java/CORBA programmers need to be aware of.

The combination of Java and CORBA, the OMG's middleware standard, has been receiving a lot of interest in both the Java and CORBA communities because of their apparent similarities in syntax and concepts. An OMG-defined language mapping and a number of existing commercial and public domain CORBA platforms open up the CORBA world for Java applications and components. In this article, I look at how far the integration of Java and CORBA can really go and point out a few pitfalls that arise because of subtle and not-so-subtle mismatches between the two worlds.

Introduction
In the Java/CORBA context, the term "integration" occurs frequently as a synonym for the combination of Java and CORBA technology. What this term conveys nicely is that the combination of these technologies promises more than just the sum of its parts as, e.g., in "language A plus thread library Y". With the conceptual distance between Java and CORBA so small, you can actually expect CORBA and Java to integrate smoothly, with only a few additional aspects that need to be understood by Java developers.

Java/CORBA integration can be achieved at two different levels: Level one is where CORBA concepts as expressed in IDL - the CORBA Interface Definition Language - are mapped to Java so that Java developers can now use them. This is what we have today: a standardized IDL-to-Java language mapping and IDL compilers from different vendors which realize it. However, this views the world from the CORBA perspective only: You design your applications in IDL using concepts not present in Java and implement them by modelling these features with Java language constructs.

At the second level, however, you can design distributed applications using a homogeneous Java programming paradigm rather than IDL. An easy-to-use distribution platform, something like a CORBA-enhanced RMI, makes your Java objects or components accessible from a CORBA-environment - without IDL specifications. To achieve this degree of integration, it must be possible to easily map both ways between Java and CORBA, so there is a need for a reverse mapping from Java to IDL in addition to the already standardized IDL-to-Java mapping. Existing approaches like Visigenic's Caffeine point in that direction, and the OMG is actively working on a Java-to-IDL mapping.

A few weak spots remain at both levels of integration. In the following sections, I'd like to go into more detail and explain why 100 percent integration is not possible.

Mapping the CORBA Object Model
Let's look at how the CORBA object model is mapped to Java. Most of this mapping is fairly straightforward, but some IDL concepts map less easily than others and need extra consideration.

The CORBA object model is defined by the concepts of IDL. Since CORBA addresses implementation only in the individual language mappings, IDL does not have a notion of classes - only interfaces (object types) can be defined. Interfaces can inherit from other interfaces and define operations and attributes. Operations can throw exceptions as in Java, but unlike in Java, operation names may not be overloaded. Also, the parameter passing modes are more varied than in Java. Apart from the fact that object-type arguments are always passed by reference and base-type arguments are passed by value, the direction in which arguments are passed has to be selected to be one of in, out or inout. While in parameters are passed to the called context, out parameters are passed back to the calling context when an invocation returns. The inout mode is a combination of the other two modes. Listing 1 is an example of an IDL specification.

Mapping the specification from Listing 1 to Java requires mapping some concepts not present in Java; in this case typedefs, sequences, bounded arrays and out parameters. The output the IDL compiler produces for the two IDL interfaces is shown in Listing 2.

As you can see, the IDL interfaces map directly to Java interfaces which also preserve the inheritance relationship between writer and server. Also note that the typedef'd names stringArray and longs do not appear in the mapped Java code. Typedef'd names can generally be replaced by the name of the original type they denote, as the mapping did for longs. In the case of stringArray, however, it would not be sufficient simply to replace it with String[]. First, Java does not permit declaring array types with fixed bounds as in the IDL file above, so these kinds of array declarations result in extra generated Java classes which know about their array bounds. The IDL compiler therefore generates a class StringArray5. However, we're not done yet; the IDL compiler has to generate another class to model the out parameter of the arryfy operation: StringArray5OutHolder. This class finally is the one used for the parameter type in the Java interface.

While mapping IDL as sketched above can be standardized and taken care of by tools, a few object model mismatches between Java and CORBA remain and deserve mention.

Object Model Mismatches
First, Java has no unsigned integers as CORBA does. This is not a big problem, but it is annoying that programmers have to take care that large positive integer values, e.g., results from operations on other CORBA objects, do not exceed the range of positive values of Java integers.

Another, more serious, point is that strings and arrays are object types in Java whereas they are base types in CORBA. This has practical implications: First, you cannot pass a null reference to either a string or an array as an argument to a CORBA operation. As these types are no reference types in CORBA, only empty strings and arrays will be accepted:

Server s = Somewhere.getServer();
s.write(""); // ok
String str = null;
s.write( str ); // illegal

Second, and this is even more problematic, operations with array parameters might exhibit different behaviors depending on the kind of object reference used to call them and thus on the parameter passing semantics employed. In the case of strings, this is not problematic: Strings are immutable, so operations on a string from within an operation's context are not visible in the calling context. With arrays, however, there is a real problem.

Consider the implementation of the operation sum in Listing 3: Sum calculates the sum of two integer arrays of equal length by adding the items at each index position and returns an array containing the results. If invoked as a CORBA operation, both a and b are passed by value and so is the result. For efficiency reasons, the method does not create another array for the results but rather reuses a. Everything works fine as long as we are in the world of CORBA semantics and all arguments are passed by value. If, however, sum is called using a Java object reference, its arguments are passed by reference and the actual argument supplied for a will have its contents overridden by the result.

Ultimately, what this example shows is that there can be no access-transparent integration of Java and CORBA in any platform: It must be clear at all times which invocation semantics apply in order to avoid unpleasant surprises. If the designer of sum intended it to be used with CORBA semantics only, users must take care that they never access objects of this class using local Java references!

Actually, this is not an inherent problem of CORBA. Rather, it is due to the fact that the Java language design defines parameter passing modes which cannot be applied consistently in both local or remote calls. The Java approach of passing arrays by reference is not appropriate for remote invocations, so any distribution platform worth its salt will pass arrays by value in remote invocations. Consequently, this problem will surface in any Java platform for distributed programming; e.g., in RMI [2].

Method Overloading, Classes, Object Serialization
In the previous sections the focus was on CORBA concepts without exact equivalents in Java. Let's now examine three Java concepts not present in CORBA - method overloading, object serialization and classes.

While overloading method names is common in Java, it is not allowed in IDL. Fortunately, this need not pose problems even when making existing Java applications CORBA-aware - if you have a tool providing a reverse mapping from Java to IDL. In the process of reverse mapping, this tool will simply rename overloaded names apart; i.e., mangle them. If you only design in IDL, there will simply be no overloaded names in your Java implementations.

Another concept frequently considered missing in CORBA is the option to pass objects by value, also known as object serialization from RMI. In many situations, such as when an object is actually not a full-blown ADT which encapsulates state but a simple container of data, it is much more appropriate to copy this object to the operation than to pass a reference to it: i.e., pass it by value. The OMG has acknowledged the need for passing objects by value and has issued a corresponding request for proposals, so the process to enhance IDL with this concept is under way.

If we now look at the class concept of Java, we find that it has three different aspects. Classes define object types, they represent object implementations and also serve as a template for object creation. The aspect of object implementation is obviously beyond the scope of CORBA, but what about types and object creation?

As already mentioned, object types can only be defined with interfaces in IDL. It is, however, not a problem to use classes as object types in Java, even if you plan to distribute your Java application with CORBA later. A decent reverse mapping is quite capable of implicitly or explicitly deriving IDL interfaces and generating stubs and skeletons from Java classes.

What about instantiating objects now? In a normal Java program you simply call a class's constructor and the runtime system will provide you with a reference to a newly created object, so you need only assign the resulting object reference to a variable.

X my_x = new XImpl();

Implicit in this way of creating and binding objects are two things that cannot be handled implicitly in a distributed environment. First, you have not only created an object of a particular type X, but also had to know about a specific implementation, XImpl. Second, there is no way to influence the actual location at which the object was created. Both these restrictions are not generally acceptable for creating objects in open distributed systems, so creating objects has to be done in a different fashion.

As you cannot rely on classes for creating object instances in CORBA, you have to use special objects which explicitly list a creation function for other objects in their interface. These "creator" objects are called factory objects or factories. Using factories to create objects, you need not care about which implementation of the desired object type is actually used - that's determined by the factory's implementation. If you really need to know, you can always provide a specific factory implementation yourself. To control object locations, CORBA defines a dedicated service, the Life Cycle Service, which provides means to create objects at specific locations or, if applicable, move them around. However, this is not a language construct of IDL and thus not an integral part of the CORBA object model - which in itself is location transparent. Also, not all CORBA platforms actually come with this service.

Summary
In this article I have outlined a few mismatches between Java and CORBA and pointed out their practical implications. Most of them are not critical as such and can be worked around with either tool support or by following certain programming conventions.

But wouldn't it be nice if Java eventually came with proper parameter passing modes and perhaps a few other modifications so that it could really be called a CORBA implementation language? A language with just the right concepts and constructs to make implementing CORBA objects as easy as Java programming is today?

References

  1. The OMG documents on the IDL-to-Java and the Java-to-IDL mappings are at http://www.omg.org/library/schedule/IDL_to_Java_RFP.html and http://www.omg.org/library/schedule/Java_to_IDL_RFP.html respectively.
  2. Gerald Brose, Klaus-Peter Löhr, Andre Spiegel, "Java Does not Distribute", Procs. TOOLS Pacific 97, Melbourne, Australia.

    About the Author
    Gerald Brose is a research assistant and PhD candidate at Freie Universität Berlin, Germany, and the author of JacORB, a free Java implementation of CORBA. He can be reached through e-mail at [email protected]

    	
    
    Listing 1: Example IDL specification.
      
    module example   
    {  
       typedef string stringArray[5];  
       typedef sequence<long> longs;  
       exception UnequalLength {};  
    
       interface writer {  
         void write(in string s);  
       };  
    
       interface server: writer   
       {  
         void arryfy(in string s,   
                     out stringArray);  
         longs sum(in longs a,   
                   in longs b)   
               raises (UnequalLength);  
       };  
    };  
    
    Listing 2: Output produced by IDL compiler.
      
    package example;  
    public interface writer   
    {  
       void write(String s);  
    }  
    
    package example;  
    public interface server  
       extends example.writer  
    {  
       void arryfy( String s,   
           StringArray5OutHolder sa );  
    
       int[] sum(int[] a, int[] b)  
           throws UnequalLength;  
    }  
    
    Listing 3: Implementation of the operation sum.
      
    int[] sum(int[] a, int[] b)  
       throws UnequalLength  
    {  
       if( a.length != b.length )  
          throw new UnequalLength();  
       for(int i=0; i<a.length; i++)  
          a[i] = a[i] + b[i];  
       return a;  
    }  
    
    
    
 

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.