Realize a distributed object environment through Java, RMI, and HORB Until recently, when software programs were created using object-oriented design, the designs operated mainly in the memory of single machines. Design methods other than object-oriented were necessary for adapting the software for network use and saving the software in secondary storage. Distributed object technology for networks was developed to solve this problem, and object-oriented database (ODBMS) technology, which saves the objects directly in secondary storage, was born.These technologies are definitely not new — development tools supporting ODBMS appeared on the market in the early 90s. However, the products either were high-priced, used an obscure language, or never gained general popularity among engineers. With the appearance of Java, distributed objects and ODBMS technology have been refined further, and prices have dropped, so they have gained acceptance by engineers. Based on recent software trends, the attention given to these technologies promises to increase even more.It is clear that future software environments must include three important technologies: “object-orientation”“networks”“databases”These environments can be realized through distributed object technology and ODBMS. Of these, this article focuses on Java-based distributed object technology.What are distributed objects?In simple terms, distributed object technology allows objects on different machines to communicate messages (Java method calls) to each other. To help you understand what distributed objects are, see Figure 1, the design of a network karaoke model. As you can see, when song selection is executed for the karaoke box in the server by remote operation, a music object is sent to the client. The client starts the music by sending the message “play.”To define some terms, an object equivalent to the karaoke box is called a “remote object,” the music object that is sent to the client is called a “copy object,” and the message sent from the client to the karaoke box object in the server is called a “remote message.” We will use this model to try to implement a distributed object system. An overview of RMI and HORBThis article focuses on two distributed object technologies: RMI (Remote Method Invocation), which is bundled as a standard feature of JDK 1.1; and HORB (Hirano Object Request Broker), which was developed by Satoshi Hirano of the National Institute of Electronics (Ministry of International Trade and Industry). (For more on HORB, see the Resources section.) CORBA, which is aiming to become an industry-standard distributed object system, will be introduced later in this article. The latest information on HORB is available from the following URL: https://ring.etl.go.jp/openlab/horb/.Application of distributed objects (HORB versus RMI)We now will try to use the two technologies, HORB and RMI, to construct a distributed object system. The fastest way to understand these technologies is by getting actual hands-on experience.First, we will design classes based on the network karaoke model. Figure 2 shows a class diagram that illustrates the structure of the relationships among instances created based on the internal class structure and classes. An introduction to HORBThis section provides an example of how to implement with HORB. Compared with RMI, HORB allows coding in a format that is similar to normal object-oriented programming. Listing 1 shows the class source of the HORB karaoke box (KaraokeBox.java). We will now proceed with building the system by expanding the source.Listing 1: Karaoke box class [HORB]class KaraokeBox{ void hello(String s){ System.out.println("Client Name " + s); } } Listing 2 is the client source that uses the karaoke box (Client.java). First, the hello() method of the KaraokeBox class is called. Up to this point, the program is not a distributed object. Calling the hello() method of the KaraokeBox is a local call. Listing 2: Client source that uses karaoke box [HORB]class Client{ public static void main(String argv[]){ String name = (argv.length == 1) ? argv[0] : "-"; KaraokeBox box = new KaraokeBox(); box.hello(name); } } Now we will apply a little magic to transform KaraokeBox into a remote object. First, the client source is modified, as shown in Listing 3; this shows you how to use KaraokeBox in remote operations (Client.java). The sections that were changed from Listing 2 are identified with comments. In Listing 3, instance of KaraokeBox_Proxy, not KaraokeBox, is created. When is the all-important instance of KaraokeBox created? The answer is when the instance of KaraokeBox_Proxy is created. Listing 3: Using KaraokeBox in remote operation (Client.java) [HORB]import horb.orb.*; // Add class Client{ public static void main(String argv[]){ String name = (argv.length == 1) ? argv[0] : "-"; KaraokeBox_Proxy box = new KaraokeBox_Proxy("horb://kinta"); // Change (change host name) box.hello(name); } } In the next code example, you see how to use KaraokeBox in an RMI operation (Client.java):Listing 4: Using KaraokeBox in an RMI operation (Client.java) [RMI]class Client{ public static void main(String argv[]){ String name = (argv.length == 1) ? argv[0] : "-"; try{ // Change KaraokeBox box = (KaraokeBox)java.rmi.Naming.lookup("rmi://kinta/karaokebox1"); // Change box.hello(name); } // Change catch(Exception e){e.printStackTrace();} // Change } } Figure 3 shows the mechanism for the karaoke box. KaraokeBox_Proxy is called the “proxy object” of KaraokeBox. The actual instance for KaraokeBox is located in the server (host name “kinta” in this example). The client creates the instance for KaraokeBox_Proxy as the proxy object. Messages to KaraokeBox are sent to the KaraokeBox_Proxy instance. The message is relayed to the KaraokeBox instance through the KaraokeBox_Proxy and the mechanism called KaraokeBox_Skeleton, which is located in the server. The result is then returned to the client. So you can see that remote object operations are possible.Here are the necessary source changes. One of the nice features of HORB is that the KaraokeBox source, which becomes the remote object, does not have to be changed at all.Creating the execution environment KaraokeBox_Proxy and KaraokeBox_Skeleton are created automatically by the HORB compiler. Client.java is compiled by the Java compiler, as usual.>horbc KaraokeBox.java KaraokeBox.classKaraokeBox_Proxy.classKaraokeBox_Skeleton.class are created>javac Client.java Client.class is created.Copy Client.class and KaraokeBox_Proxy.class to the client, and KaraokeBox.class and KaraokeBox_Skeleton.class to the server. (HORB must be installed in both the client and the server.)Execution procedureStart the HORB daemon on the server.From the client, start Client with the character string “Junzo” as an argument.The results “Client Name Junzo” is displayed at the server.The execution result is shown in Figure 4. An introduction to RMIThis section introduces implementing with RMI. First, you change the client source as shown in Listing 4 above. The locations to be changed are almost the same as those changed for HORB. Comments identify the changes from Listing 2 above.In Listing 4, the RMI method called lookup() is used instead of creating a KaraokeBox instance by calling new. So does lookup() then create the KaraokeBox instance? Actually, no. The reason for this is explained later.When RMI is used, the KaraokeBox source also must be changed. First, you must create the Java interface. Listing 5 shows the source for the KaraokeBox interface (KaraokeBox.java). The object type that the client receives from lookup() is this interface. Listing 5: Karaoke box interface (KaraokeBox.java) [RMI]interface KaraokeBox extends java.rmi.Remote{ public void hello(String s) throws java.rmi.RemoteException; } Listing 6 shows the class source of the implementation of the interface (KaraokeBoxImpl.java). Compared with the initial source (Listing 1 above), in which the objects are not distributed, these sources have more code. Listing 6: Karaoke box implementation (KaraokeBoxImpl.java) [RMI]import java.rmi.*; import java.rmi.server.UnicastRemoteObject; public class KaraokeBoxImpl extends UnicastRemoteObject implements KaraokeBox{ public KaraokeBoxImpl() throws RemoteException{ super(); } public void hello(String s) throws RemoteException{ System.out.println("Client Name " + s); } public static void main(String argv[]){ System.setSecurityManager(new RMISecurityManager()); try{ KaraokeBox box = new KaraokeBoxImpl(); java.rmi.Naming.rebind("karaokebox1", box); } catch(Exception e){e.printStackTrace();} } } Here are the necessary source changes. In RMI, the remote objects are registered with assigned names (rebind.bind). Although, these names do not need to be specified in the source, RMI, like HORB, uses objects to enable remote object operation. These objects are called Stub (equivalent to “proxy” in HORB) and Skeleton.Creating the execution environment RMI has functions that are equivalent to those of the HORB compiler, and these functions automatically create Stub and Skeleton. >javac Client.java KaraokeBox.java KaraokeBoxImpl.java Client.classKaraokeBox.classKaraokeBoxImpl.class are created>rmic KaraokeBoxImpl KaraokeBoxImpl_Stub.class KaraokeBoxImpl_Skel.class are createdCopy Client.class, KaraokeBox.class, and KaraokeBoxImpl_Stub.class to the client and KaraokeBox.class, KaraokeBoxImpl.class, KaraokeBoxImpl_Stub.class, and KaraokeBoxImpl_Skel.class to the server. (RMI must be installed in both the client and the server.)Execution procedureStart the RMI Registry on the server.Start the KaraokeBoxImpl remote object on the server.From the client, start Client with the character string “Junzo” as an argument.The results “Client Name Junzo” is displayed at the server.The execution result is shown in Figure 5.An introduction to the basic object modelThis section explains the basic object models for HORB and RMI based on the source presented earlier. The basic object model refers to the “view shown to the remote object user” when a remote object is generated and used. HORB and RMI differ significantly in their basic object models. Generation model [HORB, DCOM] The generational model provides the same method as instance creation as object-oriented programming. Refer to the section added to Listing 3 above (HORB client source).The following listing contains the source that generates KaraokeBox_Proxy: Code 1: Proxy object creationKaraokeBox_Proxy box = new KaraokeBox_Proxy("horb://YourHostName"); Recall that the KaraokeBox instance also is created as a consequence of this execution. In other words, if you use KaraokeBox_Proxy thinking that it is KaraokeBox, a remote object can be created via a method that does not vary from the normal instance generation process in object-oriented programming (see Figure 6).Connection model [CORBA (Java IDL), RMII, HORB, PDO (NEXTSTEP)] The connection model is used to connect to remote objects that were generated earlier by the server. As in the generation model, with the connection model the client does not simply create the KaraokeBox instance. Instead, the object that was created earlier by the server is used.When the RMI execution procedure is compared with the HORB execution procedure, it is evident that the server starts KaraokeBoxImpl so that the client can start Client (see Figure 7).The following listing contains the source code that allows the client to connect to the remote object:Code 2: Connection to remote objectKaraokeBox box = (KaraokeBox)Naming.lookup("rmi://YourHostName/karaokebox1"); The reason for the additional code in the server source (see Listings 5 and 6 above) with RMI is that a main() method must be created so that the code for generating the remote object can be incorporated.The connection model is a type that is provided by nearly all distributed object technologies. HORB supports both the generation and connection models.One problem with the connection model is that the client can only connect to objects generated by the server. To resolve this problem, use a technique in which the server creates the remote object requested by the client before returning it to the client. Here is an example of this technique:Code 3: Remote object creation by a client request public KaraokeBox getObject() throws RemoteException{ KaraokeBox box = null; try{ box = new KaraokeBoxImpl("karaokebox" + instanceNo ); } catch(Exception e){e.printStackTrace();} return box; } Remote messagesThe method for sending a remote message after a remote object becomes usable is almost the same for both RMI and HORB. Figure 8 shows hello() method calling and the copying of a String instance (as a parameter in the hello() method) to the server.In this process, the distributed object system turns the String interface into simple stream data and uses the low-level Socket class to send the data to the server. The server returns the String class to its original form. These mechanisms are called “marshalling” and “unmarshalling.”Now the question is, can a newly created, independent class instance be set as a remote message parameter or a return value? The answer is provided in the explanation for object passing below.Object passingPassing an object instance as a remote method parameter, or receiving an object instance from the server as the return value for a remote method, is called “object passing.” As an example of this, we will try to call the getMusic() method of KaraokeBox (see Figure 9). The client passes the song selection number as a parameter and receives the corresponding music object as the return value.1: Object passing by HORB First, we’ll provide an example of calling using HORB. A constructor for registering the getMusic() method and the Music objects for ten songs at initialization is added to KaraokeBox:Listing 7: Music object passing (KaraokeBox.java) [HORB]import java.util.*; class KaraokeBox{ Hashtable musicbox = new Hashtable(); public KaraokeBox(){ for(int i=0;i < 10;i++){ musicbox.put( new Integer(i), new Music(i,"Music" + i) ); // Register music } } public void hello(String s){ System.out.println("Client Name " + s); } public Music getMusic(int select_no){ Music music = (Music)musicbox.get(new Integer(select_no)); return music; // Return music for specified song selection number } } Next, the Music class is created, as shown in Listing 8. Note that in the current HORB version, only public or “friendly” attributes (a friendly attribute is one that is not specified as public or private) can be passed in an object. This restriction probably will be resolved in the next HORB version, which supports JDK 1.1.Listing 8: Music data management class (Music.java) [HORB]public class Music{ int no = 0; String title = ""; String musicdata = ""; final static String[] SOUNDS = {"Tan", "Bom", "Tata", "Ra-ra"}; public Music(){} public Music(int no,String title){ this.no = no; this.title = title; for(int i=0;i < 8;i++){ musicdata += SOUNDS[(int)(Math.random() * 4)] ; // Create song (laugh) } System.out.println("new .." + title + ": " + musicdata ); } public int getNo(){ return no; } public String getTitle(){ return title; } public void play(){ System.out.println("start --> " + musicdata + " --> stop"); } } Note that the current HORB version can pass an object instance only if it contains no protected or private members. This restriction will probably be resolved in the next HORB version, which supports JDK 1.1.Code for receiving music objects is added to the client source in the same way as it was for the hello() method:Listing 9: Version for accepting music objects (Client.java) [HORB]import horb.orb.*; class Client{ public static void main(String argv[]){ String name = (argv.length == 1) ? argv[0] : "-"; KaraokeBox_Proxy box = new KaraokeBox_Proxy("horb://kinta"); box.hello(name); for(int i=0;i < 10;i++){ Music m = box.getMusic(i); // Object is copied from server System.out.print("No." + m.getNo() + " [" + m.getTitle() + "] "); m.play(); } } } Creating the execution environment The procedure for compiling Music.java and KaraokeBox.java by HORB command and compiling Client.java by javac is described below. Note that Music.java must be compiled by HORB. If HORB is to be used for object passing, a proxy is necessary. To make things easier for yourself later on, make sure you specify HORB compiler options as shown below so that unnecessary sources and classes are not generated.>horbc -delete -proxyonly Music.java Music.classMusic_Proxy.class are created.>horbc -delete KaraokeBox.java KaraokeBox.classKaraokeBox_Proxy.classKaraokeBox_Skeleton.class are created.>javac Client.java Client.class is created.* horbc options:-proxyonly generates a proxy class bus does not generate a skeleton class.-delete deletes the skeleton source and the proxy source.Execution procedureStart the HORB daemon in the server.From the client, start Client with the character string “Junzo” as an argument.Ten music data items are displayed at the server and the client.The execution results are shown in Figure 10.2: Object passing by RMI The first step is KaraokeBox loading, and, as with HORB, code for the getMusic() method and music object registration is added. In addition, the sources for both KaraokeBox and KaraokeBoxImpl must be changed (see Listings 10 and 11).Listing 10: KaraokeBox interface (KaraokeBox.java) [RMI]interface KaraokeBox extends java.rmi.Remote{ public void hello(String s) throws java.rmi.RemoteException; public Music getMusic(int select_no) throws java.rmi.RemoteException; } Listing 11: Music object passing (KaraokeBoxImpl.java) [RMI]import java.rmi.*; import java.rmi.server.UnicastRemoteObject; import java.util.Hashtable; public class KaraokeBoxImpl extends UnicastRemoteObject implements KaraokeBox{ private Hashtable musicbox = new Hashtable(); public KaraokeBoxImpl() throws RemoteException{ super(); for(int i=0;i < 10;i++){ musicbox.put( new Integer(i), new Music(i,"Music" + i) ); // Register music } } public void hello(String s) throws RemoteException{ System.out.println("Client Name " + s); } public Music getMusic(int select_no) throws RemoteException{ Music music = (Music)musicbox.get(new Integer(select_no)); return music; // Return music for specified song selection number } public static void main(String argv[]){ try{ KaraokeBox box = new KaraokeBoxImpl(); System.setSecurityManager(new RMISecurityManager()); java.rmi.Naming.rebind("karaokebox1", box); } catch(Exception e){e.printStackTrace();} } } The JDK 1.1 Serialize functionality is used in RMI object passing. The Java interface java.io.Serializable must be implemented by the Music class (see Listing 12). Unlike HORB, RMI allows object passing even when the object members are private.Listing 12: Music data management class (Music.java) [RMI]public class Music implements java.io.Serializable{ private int no = 0; private String title = ""; private String musicdata = ""; private final static String[] SOUNDS = {"Tan", "Bom", "Tata", "Ra-ra"}; public Music(int no,String title){ this.no = no; this.title = title; for(int i=0;i < 8;i++){ musicdata += SOUNDS[(int)(Math.random() * 4)] ; // Compose song (laugh) } System.out.println("new .." + title + ": " + musicdata ); } public int getNo(){ return no; } public String getTitle(){ return title; } public void play(){ System.out.println("start --> " + musicdata + " --> stop"); } } As with HORB, code for receiving the music object is added to the client source, as shown in Listing 13.Listing 13: Music object reception version (Client.java) [RMI]class Client{ public static void main(String argv[]){ String name = (argv.length == 1) ? argv[0] : "-"; try{ KaraokeBox box = (KaraokeBox)java.rmi.Naming.lookup("rmi://kinta/karaokebox1"); box.hello(name); for(int i=0;i < 10;i++){ Music m = box.getMusic(i); System.out.print("No." + m.getNo() + " [" + m.getTitle() + "] "); m.play(); } } catch(Exception e){e.printStackTrace();} } } Creating the execution environment Unlike with HORB, compile Music.java with javac as usual.>javac Music.java Client.java KaraokeBox.java KaraokeBoxImpl.java>rmic KaraokeBoxImplExecution procedureStart the RMI Registry on the server.Start the KaraokeBoxImpl remote object on the server.Ten music data items are displayed at the server.From the client, start Client with the character string “Junzo” as an argument.Ten music data items are displayed at the client.The execution results are shown in Figure 11. (In this sample code, “lookup” (step 4 above) must be executed after “rebind” (step 3 above) is completed.)Designing distributed applicationsThere are a few points to consider when designing your distributed application.Understand the characteristics of a product An important point in developing a distributed application is to grasp the general characteristics of the distributed objects to be used. The best way to do so is to compare the product you’re developing with other, preexisting products. In addition, you should understand the concepts of the product. For example, HORB strives for a seamless, distributed object-oriented environment, so the KaraokeBox class introduced in Listing 1 above does not have to be modified for the remote server design. Also, clients that use the KaraokeBox class can generate remote objects in the same fashion as local objects — by calling new. Even in remote method calling, the programmer does not need to use exception handling when coding the program.In contrast, RMI forces the programmer to design the distributed objects according to precise rules so that the overall reliability of the software can be enhanced. For example, to design remote objects, the program must use the Java interface and clearly classify the objects as local methods. Also, in remote method calling, the programmer must handle exceptions. Another difference from HORB is that super class is determined in remote objects.If asked which is currently the best solution, we would have to answer, the network seamless concept of HORB. But we can answer based only on personal preference; we are not able to make an objective evaluation. HORB also provides high reliability, and RMI, like HORB, is easy to use once you become used to the coding.Instead of deciding which is good and which is bad at this time, we recommend that readers compare HORB and RMI from a more objective viewpoint. By doing so, you will be able to understand the intentions of the creator of the distributed object technology that is to be used. You also will be able to understand the software while compensating for any defects. And, you may be able to gain insight into the form that distributed objects should take in the future. In sum, the best solution is something that is determined by the trends of the time and timing.Clearly indicate the distributed processing targets Deciding which items to set as remote objects is an important point. Distributed objects are single-memory objects that have been expanded to the network. When designing remote objects, programmers should consider the overhead involved. Specifically, programmers must consider points such as minimizing the network transfer volume in remote processing and making the client and remote object interface as small as possible. In choosing to build a system, in order to create a balanced design, requirements for including distributed objects in the network must be considered.Use object passing and remote objects properly Another important point is to use object passing and remote objects properly. Remote objects represent a method of referring to server objects through proxies. For example, in the music object example that was introduced earlier, the processing can be implemented by mounting the music objects as remote objects instead of by using object passing. Only CORBA supports this method.Object passing allows the programmer to reduce the network communication overhead because the object is copied to the client. Remote objects are better suited for cases in which objects need to access server CPU resources or server data resources directly. From the viewpoint of data consistency, remote objects are preferred when the client only requires some object attributes and all server objects do not have to be copied. Remote objects also are preferred for models in which the server object attributes constantly are changed by server processes.Modeling as a link of object-orientation methodologyDesigns in which the distribution targets are clearly indicated should be implemented seamlessly from the object-orientation analysis. In the future, the network distributed object model probably will have to be incorporated as a development process link of the object-orientation methodology. In the “Drop,” the object-orientation methodology developed by the author (https://www.njk.co.jp/otg/), this type of environment is implemented by using an object classification method called the “reuse base model” in object analysis. The reuse base model is a category classification method that classifies objects from the request analysis stage into roles such as View (views), Process (processes), and Data (data management), and clarifies the reuse scope, such as Generic (general use), AppParts (system common), and App (application specific). This mode can be used to classify objects from the request analysis stage and switch over to seamless distributed object design.Design using CORBAThis section introduces an example of a Music class design that uses CORBA. CORBA uses remote objects to mount Music. In this case, when the client calls the play() method for the Music object reference (proxy object in CORBA), the play() method is executed by the server. This is inconvenient. Actually, the play() method for the Music class must be changed to the method named getMusicData(), and the Music data structure (not an object) must be passed to the client. The client must create a new Player class and must use the Player object to change the design that uses the Music data. In other words, the play() method must not be input to a target that is distributed to the server (see Figure 12).In the example described here, the Music class becomes a data management data object, and the Player class becomes a play process. In other words, “Drop” does not advocate a design that assigns the play process called play() to the Music data management object. (In this article, we assigned play() to Music to simplify the explanation.)By classifying the data management data and the data manipulation process at the start of the analysis and focusing on the data management object, we can solve the problem of having to change the design method because of differences in the distribution object product. We also can exclude the calling method from the essential problem analysis phase.Last year, the team to which the author belongs developed an airplane reservation system as a mode that uses the “Drop” development process. This system executes middle software verification and network framework examination simultaneously by using the notion called “concept” during system activation to switch the calling method for distributed objects or databases.Currently, the team is using this airplane system to introduce methods of designing distributed object-based network systems through seminars and a Web site. This year, we plan to hold free seminars to educate students who will be supporting the software business in the future.The goal of distributed object programmingThe goal of distributed object programming is to expand object-oriented mechanisms found in single-memory units to the network. The technological concepts for implementing this goal can be arranged into the following three concepts:Network-permeable object-oriented operation — Allow objects to be operated with the same methods used in normal object-oriented programming.Permeability of object locations — Provide a mechanism that hides the location (server) of objects in the network.Language-independent, ORB product-independent environment — Provide an environment that does not depend on a particular language or product.The first concept, network-permeable object-oriented operation is a concept that is strongly promoted by HORB. However, HORB does not support concepts 2 or 3 above — permeability of object locations and language-independent, ORB product-independent environments. The HORB concept treats distributed objects as extensions of object orientation. RMI also does not support concepts 2 or 3. However, the RMI concept is close to the CORBA object model and also seems to stress the first concept listed above, as does HORB. On the other hand, CORBA uses concepts that strongly promote 2 and 3. Since 1990, the Object Management Group (OMG) has been promoting CORBA as the global standard for distributed object programming. The current CORBA version is 2.0. A CORBA-compliant ORB called Java IDL (Interface Definition Language) is bundled in JDK 1.1. The CORBA concepts, such as remote procedure call (RPC) and distributed computing environment (DCE) of the Open Software Foundation (OSF) appear to treat distributed objects as extensions of network computing. CORBA therefore has focused on technical concepts 2 and 3, which assumes a large-scale, distributed network system. We still cannot say that CORBA has achieved the goal of enabling the concept of a “network-permeable object operation.”For example, let’s look at CORBA’s common language — the IDL. Remote message declarations must be specified in this language. IDL is important as a framework for enabling cooperative object operations in an environment in which different ORBs and languages are dispersed. However, the use of IDL is similar to the concept behind the development of the language known as Esperanto, which would allow everyone in the world to converse in a common language.” Using a common language probably will lead to the decline of a country’s sophisticated culture (for example, the sophisticated object-orientated functions of a programming language). Furthermore, ORB vendors would be faced with enormous work demands if they were to completely implement the voluminous specifications of CORBA.Although each distributed object tool has different architectures, next-generation distributed object applications probably will feature a good balance of the three technical concepts described above. The enhancements for reaching that stage have already begun. For example, some of the CORBA products hide IDL from the users. There also are non-CORBA products that support CORBA’s Internet Inter-ORB Protocol (IIOP) so that they can connect to CORBA. Although these enhancements can be considered quick fixes, they are probably indispensable as part of the development process leading to the next-generation of distributed object products.ConclusionThis article described the basic functions of the Java-based distributed object technologies, RMI and HORB. There are many other functions that we would like to introduce, such as bidirectional message communication supported by RMI and HORB and asynchronous communication supported by HORB. And there are many new CORBA-compliant, Java-based distributed object products. However, due to space limitations, we will stop here.Distributed object programming certainly is not difficult. Rather, it represents leading technology that will make complex network applications easier to understand.Junzo Hagimoto is manager of Object Technology Group, New Technology Division at NJK Corporation in Japan. In 1991 Mr. Hagimoto set up the object-oriented development team at NJK, and in 1995 he launched the company’s object-oriented laboratory division. The division’s work and his original object-oriented theory, called “Drop,” can be seen at http://www.njk.co.jp/otg/. Mr. Hagimoto regularly writes about distributed object technology for JavaWorld magazine published by IDG Communications Japan. His book Easy Java Programming is available in Japanese from AI Publishing Inc. Mr. Hagimoto’s most recent book on object-oriented programming will be published in December. Todd Sundsted, JavaWorld columnist and president of Etcee, a Java-centric training, mentoring, and consulting firm, served as technical editor for this translated article. Web DevelopmentJava