mc0078

50
August 2012 Master of Computer Application (MCA) – Semester 4 MC0078 – Java Programming – 4 Credits (Book ID: B0831 & B0832) Assignment Set – 1 Book ID: B0831 1. What are the difference between an interface and an abstract class? Answer: Main difference is methods of a Java interface are implicitly abstract and cannot have implementations. A Java abstract class can have instance methods that implements a default behavior. 1.Variables declared in a Java interface is by default final. An abstract class may contain non-final variables. 2.Members of a Java interface are public by default. A Java abstract class can have the usual flavors of class members like private, protected, etc.. 3.Java interface should be implemented using keyword “implements”; A Java abstract class should be extended using keyword “extends”. 4.An interface can extend another Java interface only, an abstract class can extend another Java class and implement multiple Java interfaces. 5.A Java class can implement multiple interfaces but it can extend only one abstract class. 6.Interface is absolutely abstract and cannot be instantiated; A Java abstract class also cannot be instantiated, but can be invoked if a main() exists. 7.In comparison with java abstract classes, java interfaces are slow as it requires extra indirection. 2. Explain the following with respect to Inheritance in Java: a. Various Access Specifiers and their usage

Upload: -

Post on 29-Oct-2014

897 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: mc0078

August 2012Master of Computer Application (MCA) – Semester 4

MC0078 – Java Programming – 4 Credits (Book ID: B0831 & B0832)Assignment Set – 1

Book ID: B0831 1. What are the difference between an interface and an abstract class?

Answer: Main difference is methods of a Java interface are implicitly abstract and cannot have implementations. A Java abstract class can have instance methods that implements a default behavior.

1. Variables declared in a Java interface is by default final. An abstract class may contain non-final variables.

2. Members of a Java interface are public by default. A Java abstract class can have the usual flavors of class members like private, protected, etc..

3. Java interface should be implemented using keyword “implements”; A Java abstract class should be extended using keyword “extends”.

4. An interface can extend another Java interface only, an abstract class can extend another Java class and implement multiple Java interfaces.

5. A Java class can implement multiple interfaces but it can extend only one abstract class.

6. Interface is absolutely abstract and cannot be instantiated; A Java abstract class also cannot be instantiated, but can be invoked if a main() exists.

7. In comparison with java abstract classes, java interfaces are slow as it requires extra indirection.

2. Explain the following with respect to Inheritance in Java:a. Various Access Specifiers and their usageb. Abstract classes and their applications

Answer : Just googling "java access specifiers" brings up relevant hits. It shouldn't, because there is no such thing. There are access modifiers.This link: http://staff.science.uva.nl/~heck/JAVAcourse/ch4/ss2_2.html (which is wrong because it talks about access specifiers) has a useful table: 

Summary of Access Modifiers

The following table summarizes the access level permitted by each modifier.

Page 2: mc0078

Situation public protected default private Accessible to class 

from same package? yes yes yes no Accessible to class from different package? yes no, unless it is a subclass no no

Note the difference between the default access which is in fact more restricted than the protected access. Without access specifier (the default choice), methods and variables are accessible only within the class that defines them and within classes that are part of the same package. They are not visible to subclasses unless these are in the same package. protected methods and variables are visible to subclasses regardless of which package they are in.

When To Use Interfaces

An interface allows somebody to start from scratch to implement your interface or implement your interface in some other code whose original or primary purpose was quite different from your interface. To them, your interface is only incidental, something that have to add on to the their code to be able to use your package. The disadvantage is every method in the interface must be public. You might not want to expose everything.

When To Use Abstract classes

An abstract class, in contrast, provides more structure. It usually defines some default implementations and provides some tools useful for a full implementation. The catch is, code using it must use your class as the base. That may be highly inconvenient if the other programmers wanting to use your package have already developed their own class hierarchy independently. In Java, a class can inherit from only one base class.

When to Use Both

You can offer the best of both worlds, an interface and an abstract class. Implementors can ignore your abstract class if they choose. The only drawback of doing that is calling methods via their interface name is slightly slower than calling them via their abstract class name.

Summary Table

Interfaces vs Abstract Classes

feature interface abstract class

multiple A class may implement several A class may extend only

Page 3: mc0078

Interfaces vs Abstract Classes

feature interface abstract class

inheritance interfaces. one abstract class.

default implementatio

n

An interface cannot provide any code at all, much less default code.

An abstract class can provide complete code, default code, and/or just stubs that have to be overridden.

constants

Static final constants only, can use them without qualification in classes that implement the interface. On the other paw, these unqualified names pollute the namespace. You can use them and it is not obvious where they are coming from since the qualification is optional.

Both instance and static constants are possible. Both static and instance intialiser code are also possible to compute the constants.

third party convenience

An interface implementation may be added to any existing third party class.

A third party class must be rewritten to extend only from theabstract class.

is-a vs -able or can-do

Interfaces are often used to describe the peripheral abilities of a class, not its central identity, e.g. An Automobile class might implement the Recyclable interface, which could apply to many otherwise totally unrelated objects.

An abstract class defines the core identity of its descendants. If you defined a Dog abstract class then Dalmatian descendants are Dogs, they are not merely dogable. Implemented interfaces enumerate the general things a class can do, not the things a class is.

In a Java context, users

Page 4: mc0078

Interfaces vs Abstract Classes

feature interface abstract class

should typically implement the Runnableinterface rather than extending Thread, because they’re not really interested in providing some new Thread functionality, they normally just want some code to have the capability of running independently. They want to create something that can be run in a thread, not a new kind of thread.The similar is-a vs has-a debate comes up when you decide to inherit or delegate.multiple inheritance for further discussion of is-a vs has-a

plug-in You can write a new replacement module for an interface that contains not one stick of code in common with the existing implementations. When you implement the interface, you start from scratch without any default implementation. You have to obtain your tools from other classes; nothing comes with the interface other than a few constants. This gives you freedom to implement a radically different

You must use the abstract class as-is for the code base, with all its attendant baggage, good or bad. The abstract class author has imposed structure on you. Depending on the cleverness of the author of the abstract class, this may be good or bad.

Page 5: mc0078

Interfaces vs Abstract Classes

feature interface abstract class

internal design.

homogeneity

If all the various implementations share is the method signatures, then an interface works best.

If the various implementations are all of a kind and share a common status and behaviour, usually an abstract class works best. Another issue that’s important is what I call heterogeneous vs. homogeneous. If implementors/subclasses are homogeneous, tend towards anabstract base class. If they are heterogeneous, use an interface. (Now all I have to do is come up with a good definition of hetero/homo-geneous in this context.) If the various objects are all of-a-kind, and share a common state and behavior, then tend towards a common base class. If all they share is a set of method signatures, then tend towards an interface.

maintenance If your client code talks only in terms of aninterface, you can easily change the concrete implementation behind it, using afactory method.

Just like an interface, if your client code talks only in terms of anabstract class, you can easily change the concrete implementation behind it, using

Page 6: mc0078

Interfaces vs Abstract Classes

feature interface abstract class

a factory method.

speed

Slow, requires extra indirection to find the corresponding method in the actual class. Modern JVMs (Java Virtual Machines)are discovering ways to reduce this speed penalty.

Fast

terseness

The constant declarations in an interfaceare all presumed public static final, so you may leave that part out. You can’t call any methods to compute the initial values of your constants. You need not declare individual methods of an interface abstract. They are all presumed so.

You can put shared code into an abstract class, where you cannot into an interface. If interfaces want to share code, you will have to write other bubblegum to arrange that. You may use methods to compute the initial values of your constants and variables, both instance and static. You must declare all the individual methods of anabstract class abstract.

adding functionality

If you add a new method to an interface, you must track down all implementations of that interface in the universe and provide them with a concrete implementation of that method.

If you add a new method to an abstract class, you have the option of providing a default implementation of it. Then all existing code will continue to work without change.

3. Describe Exception Handling in JAVA

Page 7: mc0078

Answer: n exception is a problem that arises during the execution of a program. An exception can occur for many different reasons, including the following:

A user has entered invalid data. A file that needs to be opened cannot be found.

A network connection has been lost in the middle of communications, or the JVM has run out of memory.

Some of these exceptions are caused by user error, others by programmer error, and others by physical resources that have failed in some manner.

To understand how exception handling works in Java, you need to understand the three categories of exceptions:

Checked exceptions: A checked exception is an exception that is typically a user error or a problem that cannot be foreseen by the programmer. For example, if a file is to be opened, but the file cannot be found, an exception occurs. These exceptions cannot simply be ignored at the time of compilation.

Runtime exceptions: A runtime exception is an exception that occurs that probably could have been avoided by the programmer. As opposed to checked exceptions, runtime exceptions are ignored at the time of compliation.

Errors: These are not exceptions at all, but problems that arise beyond the control of the user or the programmer. Errors are typically ignored in your code because you can rarely do anything about an error. For example, if a stack overflow occurs, an error will arise. They are also ignored at the time of compilation.

Exception Hierarchy:

All exception classes are subtypes of the java.lang.Exception class. The exception class is a subclass of the Throwable class. Other than the exception class there is another subclass called Error which is derived from the Throwable class.

Errors are not normally trapped form the Java programs. These conditions normally happen in case of severe failures, which are not handled by the java programs. Errors are generated to indicate errors generated by the runtime environment. Example : JVM is out of Memory. Normally programs cannot recover from errors.

The Exception class has two main subclasses : IOException class and RuntimeException Class.

Page 8: mc0078

Here is a list of most common checked and unchecked Java's Built-in Exceptions.

Exceptions Methods:

Following is the list of important medthods available in the Throwable class.

SN Methods with Description

1 public String getMessage()Returns a detailed message about the exception that has occurred. This message is initialized in the Throwable constructor.

2 public Throwable getCause()Returns the cause of the exception as represented by a Throwable object.

3 public String toString()Returns the name of the class concatenated with the result of getMessage()

4 public void printStackTrace()Prints the result of toString() along with the stack trace to System.err, the error output stream.

5 public StackTraceElement [] getStackTrace()Returns an array containing each element on the stack trace. The element at index 0 represents the top of the call stack, and the last element in the array represents the method at the bottom of the call stack.

6 public Throwable fillInStackTrace()Fills the stack trace of this Throwable object with the current stack trace, adding to any previous information in the stack trace.

Catching Exceptions:

A method catches an exception using a combination of the try and catch keywords. A try/catch block is placed around the code that might generate an exception. Code within a try/catch block is referred to as protected code, and the syntax for using try/catch looks like the following:

try{ //Protected code}catch(ExceptionName e1){ //Catch block}

A catch statement involves declaring the type of exception you are trying to catch. If an exception occurs in protected code, the catch block (or blocks) that follows the try is checked. If the type of exception that occurred is listed in a catch block, the exception is passed to the catch block much as an argument is passed into a method parameter.

Page 9: mc0078

Example:

The following is an array is declared with 2 elements. Then the code tries to access the 3rd element of the array which throws an exception.

// File Name : ExcepTest.javaimport java.io.*;public class ExcepTest{

public static void main(String args[]){ try{ int a[] = new int[2]; System.out.println("Access element three :" + a[3]); }catch(ArrayIndexOutOfBoundsException e){ System.out.println("Exception thrown :" + e); } System.out.println("Out of the block"); }}

Book ID: B0832 4. What do you mean by Object Adapter? Explain with an example?

Answer: ava 5 has a neat little feature, that is not widely known. You can change the return type of overridden methods. For example, clone() now returns the correct type of the object, so you do not need to downcast the result anymore.

One of my annoyances with Java has been that Collection.toArray() returns an Object[] and not the correct type. Say you have a collection containing Strings, then you have to pass a String[] into the toArray() method. This seems clumsy to me. It would have been nice if this had been changed in Java 5. However, generics cannot solve the problem due to erasure. There is no handle to the type of generic, once the code has been compiled. You therefore have to change the construction of the collection object to also have a handle to the class of the generic type.

My first solution was to write a Class Adapter, which extended java.util.ArrayList with my adapter, which I called BetterArrayList. I have put these classes in a package so that we can do static imports later on:

package com.maxoft.tjsn.util;

import java.lang.reflect.Array;import java.util.*;

public class BetterArrayList extends ArrayList {

Page 10: mc0078

private final Class valueType; public BetterArrayList(int initialCapacity, Class valueType) { super(initialCapacity); this.valueType = valueType; } public BetterArrayList(Class valueType) { this.valueType = valueType; } public BetterArrayList(Collectionextends T> ts, Class valueType) { super(ts); this.valueType = valueType; } // You can modify the return type of an overridden method in // Java 5, with some restrictions. public T[] toArray() { return toArray((T[]) Array.newInstance(valueType, size())); }}

We can now use this in our code instead of the ArrayList, and then we do not need to have such an awkward syntax for converting it to a type-safe array. We have to pass the class object into the constructor, but the compiler checks that it is the correct class object for the generic type.

package com.maxoft.tjsn.util;

public class BetterArrayListTest { public static void main(String[] args) { BetterArrayList names = new BetterArrayList(String.class); names.add("Wolfgang"); names.add("Leander"); names.add("Klaus"); names.add("Reinhard"); String[] nameArray = names.toArray(); for (String s : nameArray) { System.out.println(s); } }}

This would be a reasonable solution if we only ever wanted to use ArrayLists. However, we have to write a class adapter for every collection class that we might want to use.

Here is a new interface, called the BetterCollection, that extends the Collection interface, and changes the return type of the toArray() method:

Page 11: mc0078

package com.maxoft.tjsn.util;

import java.util.Collection;

public interface BetterCollection extends Collection { T[] toArray();}

We can then implement that interface in an object adapter (note how much more code this is!):

package com.maxoft.tjsn.util;

import java.lang.reflect.Array;import java.util.*;

public class BetterCollectionObjectAdapter implements BetterCollection { private final Collection adaptee; private final Class valueType; public BetterCollectionObjectAdapter(Collection adaptee, Class valueType) { this.adaptee = adaptee; this.valueType = valueType; } public T[] toArray() { return adaptee.toArray((T[]) Array.newInstance(valueType, adaptee.size())); } // this is a typical problem with the Object Adapter Design // Pattern - you have implement all the methods :-( public int size() { return adaptee.size(); } public boolean isEmpty() { return adaptee.isEmpty(); } public boolean contains(Object o) { return adaptee.contains(o); } public Iterator iterator() { return adaptee.iterator(); } public T[] toArray(T[] ts) { return adaptee.toArray(ts); } public boolean add(T t) { return adaptee.add(t); } public boolean remove(Object o) { return adaptee.remove(o); }

Page 12: mc0078

public boolean containsAll(Collection c) { return adaptee.containsAll(c); } public boolean addAll(Collection ts) { return adaptee.addAll(ts); } public boolean removeAll(Collection c) { return adaptee.removeAll(c); } public boolean retainAll(Collection c) { return adaptee.retainAll(c); } public void clear() { adaptee.clear(); }}

We can use this as an adapter for any type of collection, for example:

package com.maxoft.tjsn.util;

import java.util.LinkedList;

public class BetterCollectionTest { public static void main(String[] args) { BetterCollection names = new BetterCollectionObjectAdapter( new LinkedList(), String.class); names.add("Wolfgang"); names.add("Leander"); names.add("Klaus"); names.add("Reinhard"); String[] nameArray = names.toArray(); for (String s : nameArray) { System.out.println(s); } }}

This solution works, but I dont like being exposed to changes in the interface. Should Sun ever decide to add a new method to the Collection interface, our class would not compile anymore. Also, it is a lot of code to implement all those methods, and to support the extended interfaces of List, Set, SortedSet, etc., I would need to again write other adapters. I know the chance of Sun changing java.util.Collection is rather remote, but I did have this experience a few times with the java.sql.Connection interface that I had adapted.

Page 13: mc0078

Dynamic Object Adapter using Dynamic Proxies

Now that we have seen the problem, let's examine the solution based on dynamic proxies (with thanks to Dr Klaus Wiederaenders for the idea). In the past I have written several object adapters based on interfaces. Besides being a lot of boring work, we experience pain new methods are added to the interface. It can easily occur that your object adapter then only works for one specific version of Java.

The first piece of the puzzle is a DynamicObjectAdapterFactory. This contains the method adapt, which takes an adaptee (the object that we are adapting), the target (the interface that we want to return) and the adapter (the object that contains methods which override adaptee behaviour). We then create a dynamic proxy of the target interface. The invocation handler gets called whenever a method is called on the dymanic proxy. Each of the declared methods in the adapter is put into a map using an identifier that is based on the name and parameter list of the method. This way, there does not have to be an inheritance relationship between the adapter and the target.

package com.maxoft.tjsn.util;

import java.lang.reflect.*;import java.util.*;

public class DynamicObjectAdapterFactory { public static T adapt(final Object adaptee, final Class target, final Object adapter) { return (T) Proxy.newProxyInstance( Thread.currentThread().getContextClassLoader(), new Class[]{target}, new InvocationHandler() { private Map adaptedMethods = new HashMap(); // initializer block - find all methods in adapter object { Method[] methods = adapter.getClass().getDeclaredMethods(); for (Method m : methods) { adaptedMethods.put(new MethodIdentifier(m), m); } } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { Method other = adaptedMethods.get( new MethodIdentifier(method)); if (other != null) {

Page 14: mc0078

return other.invoke(adapter, args); } else { return method.invoke(adaptee, args); } } catch (InvocationTargetException e) { throw e.getTargetException(); } } }); }

private static class MethodIdentifier { private final String name; private final Class[] parameters; public MethodIdentifier(Method m) { name = m.getName(); parameters = m.getParameterTypes(); } // we can save time by assuming that we only compare against // other MethodIdentifier objects public boolean equals(Object o) { MethodIdentifier mid = (MethodIdentifier) o; return name.equals(mid.name) && Arrays.equals(parameters, mid.parameters); } public int hashCode() { return name.hashCode(); } }} 5. Describe the following with respect to implementation of Sockets in Java:a. Reading from and Writing to a Socketb. Writing the Server Side of a Socket

Answer: A)Socket:

A socket is one endpoint of a two-way communication link between two programs running on the network. A socket is bound to a port number so that the TCP layer can identify the application that data is destined to be sent.

Reading from and Writing to a Socket

1. Open a socket.

2. Open an input stream and output stream to the socket.

Page 15: mc0078

3. Read from and write to the stream according to the server's protocol.

4. Close the streams.

                       5. Close the socket.

Only step 3 differs from client to client, depending on the server. The other

steps remain largely the same.

 

(B)Port:

 The TCP and UDP protocols use ports to map incoming data to a particular process running on a computer. Port numbers range from 0 to 65,535 because ports are represented by 16-bit numbers. The port numbers ranging from 0 - 1023 are restricted; they are

reserved for use by well-known services such as HTTP and FTP and other

system services. These ports are called well-known ports. Your applications should not attempt to bind to them.

 

(C)Datagram:

          A datagram is an independent, self-contained message sent over the network whose arrival, arrival time, and content are not guaranteed. The java.net package contains three classes to help you write Java programs that use datagram’s to send and receive packets over the network: DatagramSocket. DatagramPacket, and MulticastSocket.

The example program implements a client, EchoClient, that connects to the Echo server. The Echo server simply receives data from its client and echoes it back. The Echo server is a well-known service that clients can rendezvous with on port 7.

 

Page 16: mc0078

EchoClient creates a socket thereby getting a connection to the Echo server. It reads input from the user on the standard input stream, and then forwards that text to the Echo server by writing the text to the socket. The server echoes the input back through the socket to the client. The client program reads and displays the data passed back to it from the server:

 

import java.io.*;

import java.net.*;

 

public class EchoClient {

    public static void main(String[] args) throws IOException {

 

        Socket echoSocket = null;

        PrintWriter out = null;

        BufferedReader in = null;

 

        try {

            echoSocket = new Socket("taranis", 7);

            out = new PrintWriter(echoSocket.getOutputStream(), true);

            in = new BufferedReader(new InputStreamReader(

                                        echoSocket.getInputStream()));

        } catch (UnknownHostException e) {

            System.err.println("Don't know about host: taranis.");

Page 17: mc0078

            System.exit(1);

        } catch (IOException e) {

            System.err.println("Couldn't get I/O for "

                               + "the connection to: taranis.");

            System.exit(1);

        }

 

          BufferedReader stdIn = new BufferedReader(

                                   new InputStreamReader(System.in));

          String userInput;

 

          while ((userInput = stdIn.readLine()) != null) {

              out.println(userInput);

              System.out.println("echo: " + in.readLine());

          }

 

          out.close();

          in.close();

          stdIn.close();

          echoSocket.close();

    }

Page 18: mc0078

}

 

Note that EchoClient both writes to and reads from its socket, thereby sending data to and receiving data from the Echo server.

 

Let's walk through the program and investigate the interesting parts. The three statements in the try block of the main method are critical. These lines establish the socket connection between the client and the server and open a PrintWriter and a BufferedReader on the socket:

 

echoSocket = new Socket("taranis", 7);

out = new PrintWriter(echoSocket.getOutputStream(), true);

in = new BufferedReader(new InputStreamReader(

                             echoSocket.getInputStream()));

 

The first statement in this sequence creates a new Socket object and names it echoSocket. The Socket constructor used here requires the name of the machine and the port number to which you want to connect. The example program uses the host name taranis. This is the name of a hypothetical machine on our local network. When you type in and run this program on your machine, change the host name to the name of a machine on your network. Make sure that the name you use is the fully qualified IP name of the machine to which you want to connect. The second argument is the port number. Port number 7 is the port on which the Echo server listens.

 

The second statement gets the socket's output stream and opens a PrintWriter on it. Similarly, the third statement gets the socket's input

Page 19: mc0078

stream and opens a BufferedReader on it. The example uses readers and writers so that it can write Unicode characters over the socket.

 

To send data through the socket to the server, EchoClient simply needs to write to the PrintWriter. To get the server's response, EchoClient reads from the BufferedReader. The rest of the program achieves this. If you are not yet familiar with the Java platform's I/O classes, you may wish to read Basic I/O.

 

The next interesting part of the program is the while loop. The loop reads a line at a time from the standard input stream and immediately sends it to the server by writing it to the PrintWriter connected to the socket:

 

String userInput;

 

while ((userInput = stdIn.readLine()) != null) {

    out.println(userInput);

    System.out.println("echo: " + in.readLine());

}

 

The last statement in the while loop reads a line of information from the BufferedReader connected to the socket. The readLine method waits until the server echoes the information back to EchoClient. When readline returns, EchoClient prints the information to the standard output.

 

The while loop continues until the user types an end-of-input character. That is, EchoClient reads input from the user, sends it to the Echo server,

Page 20: mc0078

gets a response from the server, and displays it, until it reaches the end-of-input. The while loop then terminates and the program continues, executing the next four lines of code:

 

out.close();

in.close();

stdIn.close();

echoSocket.close();

 

These lines of code fall into the category of housekeeping. A well-behaved program always cleans up after itself, and this program is well-behaved. These statements close the readers and writers connected to the socket and to the standard input stream, and close the socket connection to the server. The order here is important. You should close any streams connected to a socket before you close the socket itself.

 

This client program is straightforward and simple because the Echo server implements a simple protocol. The client sends text to the server, and the server echoes it back. When your client programs are talking to a more complicated server such as an HTTP server, your client program will also be more complicated. However, the basics are much the same as they are in this program:

 

    Open a socket.

    Open an input stream and output stream to the socket.

    Read from and write to the stream according to the server's protocol.

    Close the streams.

Page 21: mc0078

    Close the socket.

 

Only step 3 differs from client to client, depending on the server. The other steps remain largely the same.

5.Define RMI. Define the architecture of RMI invocation.Introduction to RMIRMI is the distributed object system that is built into the core Java environment. You can think of RMI as a built-in facility for Java that allows you to interact with objects that are actually running in Java virtual machines on remote hosts on the network. With RMI (and other distributed object APIs we discuss in this book), you can get a reference to an object that "lives" in a remote process and invoke methods on it as if it were a local object running within the same virtual machine as your code (hence the name, "Remote Method Invocation API").

RMI was added to the core Java API in Version 1.1 of the JDK (and enhanced for Version 1.2 of the Java 2 platform), in recognition of the critical need for support for distributed objects in distributed-application development. Prior to RMI, writing a distributed application involved basic socket programming, where a "raw" communication channel was used to pass messages and data between two remote processes. Now, with RMI and distributed objects, you can "export" an object as a remote object, so that other remote processes/agents can access it directly as a Java object. So, instead of defining a low-level message protocol and data transmission format between processes in your distributed application, you use Java interfaces as the "protocol" and the exported method arguments become the data transmission format. The distributed object system (RMI in this case) handles all the underlying networking needed to make your remote method calls work.Java RMI is a Java-only distributed object scheme; the objects in an RMI-based distributed application have to be implemented in Java. Some other distributed object schemes, most notably CORBA, are language-independent, which means that the objects can be implemented in any language that has a defined binding. With CORBA, for example, bindings exist for C, C++, Java, Smalltalk, and Ada, among other languages.The advantages of RMI primarily revolve around the fact that it is "Java-native." Since RMI is part of the core Java API and is built to work directly with Java objects within the Java VM, the integration of its remote object facilities into a Java application is almost seamless. You really can use RMI-enabled objects as if they live in the local Java environment. And since Java RMI is built on the assumption that both the client and server are Java objects, RMI can extend the internal garbage-collection mechanisms of the standard Java VM to provide distributed garbage collection of remotely exported objects.If you have a distributed application with heterogeneous components, some of which are written in Java and some that aren't, you have a few choices. You can use RMI, wrapping the non-Java code with RMI-enabled Java objects using the Java Native Interface (JNI). At the end of this chapter, we discuss this first option in some detail, to give you a feeling for where it could be useful and where it wouldn't. Another option is to use another object distribution scheme, such as CORBA, that supports language-independent object interfaces. Chapter 4, "Java IDL", covers the

Page 22: mc0078

Java interface to CORBA that is included in the Java 2 SDK. A third option involves the new RMI/IIOP functionality that allows RMI objects to communicate directly with remote CORBA objects over IIOP. We also discuss this option in some detail at the end of this chapter.

RMI in Action

Before we start examining the details of using RMI, let's look at a simple RMI remote object at work. We can create an Account object that represents some kind of bank account and then use RMI to export it as a remote object so that remote clients (e.g., ATMs, personal finance software running on a PC) can access it and carry out transactions.The first step is to define the interface for our remote object. Example 3-1 shows the Account interface. You can tell that it's an RMI object because it extends the java.rmi.Remote interface. Another signal that this is meant for remote access is that each method can throw a java.rmi.RemoteException. The Account interface includes methods to get the account name and balance and to make deposits, withdrawals, and transfers.

Example 3-1. A Remote Account Interface

import java.rmi.Remote;import java.rmi.RemoteException;import java.util.List;public interface Account extends Remote { public String getName() throws RemoteException; public float getBalance() throws RemoteException; public void withdraw(float amt) throws RemoteException; public void deposit(float amt) throws RemoteException; public void transfer(float amt, Account src) throws RemoteException; public void transfer(List amts, List srcs) throws RemoteException;}

The next step is to create an implementation of this interface, which leads to the AccountImpl class shown in Example 3-2. This class implements all the methods listed in the Account interface and adds a constructor that takes the name of the new account to be created. Notice that the AccountImpl class implements the Account interface, but it also extends the java.rmi.UnicastRemoteObject class. This RMI class provides some of the basic remote functionality for server objects.Example 3-2. Implementation of the Remote Account Interface

import java.rmi.server.UnicastRemoteObject;import java.rmi.RemoteException;import java.util.List;import java.util.ListIterator;

public class AccountImpl extends UnicastRemoteObject implements Account { private float mBalance = 0; private String mName = "";

Page 23: mc0078

// Create a new account with the given name public AccountImpl(String name) throws RemoteException { mName = name; }

public String getName() throws RemoteException { return mName; } public float getBalance() throws RemoteException { return mBalance; }

// Withdraw some funds public void withdraw(float amt) throws RemoteException { mBalance -= amt; // Make sure balance never drops below zero mBalance = Math.max(mBalance, 0); }

// Deposit some funds public void deposit(float amt) throws RemoteException { mBalance += amt; }

// Move some funds from another (remote) account into this one public void transfer(float amt, Account src) throws RemoteException { src.withdraw(amt); this.deposit(amt); }

// Make several transfers from other (remote) accounts into this one public void transfer(List amts, List srcs) throws RemoteException { ListIterator amtCurs = amts.listIterator(); ListIterator srcCurs = srcs.listIterator();

// Iterate through the accounts and the amounts to be transferred from // each (assumes amounts are given as Float objects) while (amtCurs.hasNext() && srcCurs.hasNext()) { Float amt = (Float)amtCurs.next(); Account src = (Account)srcCurs.next(); this.transfer(amt.floatValue(), src);

} }}

Once the remote interface and an implementation of it are complete, you need to compile both Java files with your favorite Java compiler. After this is done, you use the RMI stub/skeleton

Page 24: mc0078

compiler to generate a client stub and a server skeleton for the AccountImpl object. The stub and skeleton handle the communication between the client application and the server object. With Sun's Java SDK, the RMI compiler is called RMIC, and you can invoke it for this example like so:% rmic -d /home/classes AccountImplThe stub and skeleton classes are generated and stored in the directory given by the -d option (/HOME/CLASSES, in this case). This example assumes that the AccountImpl class is already in your CLASSPATH before you run the RMI compiler.There's just one more thing we need to do before we can actually use our remote object: register it with an RMI registry, so that remote clients can find it on the network. The utility class that follows, RegAccount, does this by creating an AccountImpl object and then binding it to a name in the local registry using the java.rmi.Naming interface. After it's done registering the object, the class goes into a wait(), which allows remote clients to connect to the remote object:

import java.rmi.Naming;public class RegAccount { public static void main(String argv[]) { try { // Make an Account with a given name AccountImpl acct = new AccountImpl("JimF");

// Register it with the local naming registry Naming.rebind("JimF", acct); System.out.println("Registered account."); } catch (Exception e) { e.printStackTrace();

} }}After you compile the RegAccount class, you can run its main() method to register an Account with the local RMI registry. First, however, you need to start the registry. With Sun's Java SDK, the registry can be started using the RMIREGISTRY utility. On a Unix machine, this can be done like so:objhost% rmiregistry &Once the registry is started, you can invoke the main() method on the RegAccount class simply by running it:objhost% java RegAccountRegistered account.Now we have a remote Account object that is ready and waiting for a client to access it and call its methods. The following client code does just this, by first looking up the remote Account object using the java.rmi.Naming interface (and assuming that the Account object was registered on a machine named OBJHOST.ORG), and then calling the deposit method on the

Page 25: mc0078

Account object:

import java.rmi.Naming;

public class AccountClient { public static void main(String argv[]) { try { // Lookup account object Account jimAcct = (Account)Naming.lookup("rmi://objhost.org/JimF");

// Make deposit jimAcct.deposit(12000);

// Report results and balance. System.out.println("Deposited 12,000 into account owned by " + jimAcct.getName()); System.out.println("Balance now totals: " + jimAcct.getBalance()); } catch (Exception e) { System.out.println("Error while looking up account:"); e.printStackTrace(); } }}The first time you run this client, here's what you'd do:% java AccountClientDeposited 12,000 into account owned by JimFBalance now totals: 12000.0For the sake of this example, I've assumed that the client process is running on a machine with all the necessary classes available locally (the Account interface and the stub and skeleton classes generated from the AccountImpl implementation). Later in the chapter, we'll see how to deal with loading these classes remotely when the client doesn't have them locally.

RMI Architecture

Now that we've seen a complete example of an RMI object in action, let's look at what makes remote objects work, starting with an overview of the underlying RMI architecture. There are three layers that comprise the basic remote-object communication facilities in RMI:The STUB/SKELETON layer, which provides the interface that client and server application objects use to interact with each other.The REMOTE REFERENCE layer, which is the middleware between the stub/skeleton layer and the underlying transport protocol. This layer handles the creation and management of remote object references.The TRANSPORT PROTOCOL layer, which is the binary data protocol that sends remote object requests over the wire.

Page 26: mc0078

These layers interact with each other as shown in Figure 3-1. In this figure, the server is the application that provides remotely accessible objects, while the client is any remote application that communicates with these server objects. In a distributed object system, the distinctions between clients and servers can get pretty blurry at times. Consider the case where one process registers a remote-enabled object with the RMI naming service, and a number of remote processes are accessing it. We might be tempted to call the first process the server and the other processes the clients. But what if one of the clients calls a method on the remote object, passing a reference to an RMI object that's local to the client. Now the server has a reference to and is using an object exported from the client, which turns the tables somewhat. The "server" is really the server for one object and the client of another object, and the "client" is a client and a server, too. For the sake of discussion, I'll refer to a process in a distributed application as a server or client if its role in the overall system is generally limited to one or the other. In peer-to-peer systems, where there is no clear client or server, I'll refer to elements of the system in terms of application-specific roles (e.g., chat participant, chat facilitator).

Figure 3-1. The RMI runtime architecture

As you can see in Figure 3-1, a client makes a request of a remote object using a client-side stub; the server object receives this request from a server-side object skeleton. A client initiates a remote method invocation by calling a method on a stub object. The stub maintains an internal reference to the remote object it represents and forwards the method invocation request through the remote reference layer by MARSHALLING the method arguments into serialized form and

Page 27: mc0078

asking the remote reference layer to forward the method request and arguments to the appropriate remote object. Marshalling involves converting local objects into portable form so that they can be transmitted to a remote process. Each object is checked as it is marshaled, to determine whether it implements the java.rmi.Remote interface. If it does, its remote reference is used as its marshaled data. If it isn't a Remote object, the argument is serialized into bytes that are sent to the remote host and reconstituted into a copy of the local object. If the argument is neither Remote nor Serializable, the stub throws a java.rmi.MarshalException back to the client. If the marshalling of method arguments succeeds, the client-side remote reference layer receives the remote reference and marshaled arguments from the stub. This layer converts the client request into low-level RMI transport requests according to the type of remote object communication being used. In RMI, remote objects can (potentially) run under several different communication styles, such as point-to-point object references, replicated objects, or multicast objects. The remote reference layer is responsible for knowing which communication style is in effect for a given remote object and generating the corresponding transport-level requests. In the current version of RMI (Version 1.2 of Java 2), the only communication style provided out of the box is point-to-point object references, so this is the only style we'll discuss in this chapter. For a point-to-point communication, the remote reference layer constructs a single network-level request and sends it over the wire to the sole remote object that corresponds to the remote reference passed along with the request.

On the server, the server-side remote reference layer receives the transport-level request and converts it into a request for the server skeleton that matches the referenced object. The skeleton converts the remote request into the appropriate method call on the actual server object, which involves UNMARSHALLING the method arguments into the server environment and passing them to the server object. As you might expect, unmarshalling is the inverse procedure to the marshalling process on the client. Arguments sent as remote references are converted into local stubs on the server, and arguments sent as serialized objects are converted into local copies of the originals. If the method call generates a return value or an exception, the skeleton marshals the object for transport back to the client and forwards it through the server reference layer. This result is sent back using the appropriate transport protocol, where it passes through the client reference layer and stub, is unmarshaled by the stub, and is finally handed back to the client thread that invoked the remote method. RMI Object Services On top of its remote object architecture, RMI provides some basic object services you can use in your distributed application. These include an object naming/registry service, a remote object activation service, and distributed garbage collection.3.1.3.1. Naming/registry serviceWhen a server process wants to export some RMI-based service to clients, it does so by registering one or more RMI-enabled objects with its local RMI registry (represented by the Registry interface). Each object is registered with a name clients can use to reference it. A client can obtain a stub reference to the remote object by asking for the object by name through the Naming interface. The Naming.lookup() method takes the fully qualified name of a remote object and locates the object on the network. The object's fully qualified name is in a URL-like syntax that includes the name of the object's host and the object's registered name.

Page 28: mc0078

It's important to note that, although the Naming interface is a default naming service provided with RMI, the RMI registry can be tied into other naming services by vendors. Sun has provided a binding to the RMI registry through the Java Naming and Directory Interface ( JNDI), Once the lookup() method locates the object's host, it consults the RMI registry on that host and asks for the object by name. If the registry finds the object, it generates a remote reference to the object and delivers it to the client process, where it is converted into a stub reference that is returned to the caller. Once the client has a remote reference to the server object, communication between the client and the server commences as described earlier. We'll talk in more detail about the Naming and Registry interfaces later in this chapter.

Object activation service

The remote object activation service is new to RMI as of Version 1.2 of the Java 2 platform. It provides a way for server objects to be started on an as-needed basis. Without remote activation, a server object has to be registered with the RMI registry service from within a running Java virtual machine. A remote object registered this way is only available during the lifetime of the Java VM that registered it. If the server VM halts or crashes for some reason, the server object becomes unavailable and any existing client references to the object become invalid. Any further attempts by clients to call methods through these now-invalid references result in RMI exceptions being thrown back to the client. The RMI activation service provides a way for a server object to be activated automatically when a client requests it. This involves creating the server object within a new or existing virtual machine and obtaining a reference to this newly created object for the client that caused the activation. A server object that wants to be activated automatically needs to register an activation method with the RMI activation daemon running on its host. We'll discuss the RMI activation service in more detail later in the chapter.

Distributed garbage collection

The last of the remote object services, distributed garbage collection, is a fairly automatic process that you as an application developer should never have to worry about. Every server that contains RMI-exported objects automatically maintains a list of remote references to the objects it serves. Each client that requests and receives a reference to a remote object, either explicitly through the registry/naming service or implicitly as the result of a remote method call, is issued this remote object reference through the remote reference layer of the object's host process. The reference layer automatically keeps a record of this reference in the form of an expirable "lease" on the object. When the client is done with the reference and allows the remote stub to go out of scope, or when the lease on the object expires, the reference layer on the host automatically deletes the record of the remote reference and notifies the client's reference layer that this remote reference has expired. The concept of expirable leases, as opposed to strict on/off references, is used to deal with situations where a client-side failure or a network failure keeps the client from notifying the server that it is done with its reference to an object. When an object has no further remote references recorded in the remote reference layer, it becomes a candidate for garbage collection. If there are also no further local references to the

Page 29: mc0078

object (this reference list is kept by the Java VM itself as part of its normal garbage-collection algorithm), the object is marked as garbage and picked up by the next run of the system garbage collector.

MC0078 – Java Programming – 4 Credits (Book ID: B0831 & B0832)

Assignment Set – 2

1. Write a program to demonstrate the concept of I/O streams in Java.

Answer: import java.io.DataInputStream;

            import java.io.DataOutputStream;

            import java.io.FileInputStream;

            import java.io.FileOutputStream;

        

           public class InputOutputDemoBinaryFile

{

           public static void main(String[] a) throws Exception

{

           //Write primitive values to a binary file "java2s.dat":

           DataOutputStream dos = new DataOutputStream(new

           FileOutputStream ("java2s.dat"));

           dos.writeInt(228);

           dos.writeChar(' ');

           dos.writeUTF("Java Source and Support at www.java2s.com");

           dos.close();

Page 30: mc0078

          //Read primitive values from binary file "java2s.dat":

           DataInputStream dis = new DataInputStream(new FileInputStream(

           "java2s.dat"));

           System.out.println(dis.readInt() + "|" + dis.readChar() + "|"

          + dis.readUTF());

            }

         }

2. How do you implements inheritance in java

Answer : Inheritance in Java: Inheritance is a compile-time mechanism in Java that allows you to extend a class (called the base

class or superclass) with another class (called the derived class or subclass). In Java,

Inheritance is used for two purposes:

1. Class inheritance - create a new class as an extension of another class, primarily for the purpose of code reuse. That is, the derived class inherits the public methods and public data of the base class. Java only allows a class to have one immediate base class, i.e., single class inheritance.

2. Interface inheritance - create a new class to implement the methods defined as part of an interface for the purpose of sub typing. That is a class that implements an interface “conforms to” (or is constrained by the type of) the interface. Java supports multiple interface inheritance. In Java, these two kinds of inheritance are made distinct by using different language syntax. For class inheritance, Java uses the keyword extends and for interface inheritance Java uses the keyword implements.

public class derived-class-name extends base-class-name {

// derived class methods extend and possibly override

Page 31: mc0078

// those of the base class

}

public class class-name implements interface-name {

// class provides an implementation for the methods

// as specified by the interface

}

 

Example of class inhertiance

package MyPackage;

class Base {

private int x;

public int f() { ... }

protected int g() { ... }

}

class Derived extends Base {

private int y;

public int f() { /* new implementation for Base.f() */ }

public void h() { y = g(); ... }

}

3. Explain the following with respect to Servlets in Java: a. Web Architecture b. Servlet Life cycleA servlet life cycle can be defined as the entire process from its creation till the destruction. The following are the paths followed by a servletThe servlet is initialized by calling the init () method.The servlet calls service() method to process a client's request.

Page 32: mc0078

The servlet is terminated by calling the destroy() method.Finally, servlet is garbage collected by the garbage collector of the JVM.Now let us discuss the life cycle methods in details.

The init() method :The init method is designed to be called only once. It is called when the servlet is first created, and not called again for each user request. So, it is used for one-time initializations, just as with the init method of applets.The servlet is normally created when a user first invokes a URL corresponding to the servlet, but you can also specify that the servlet be loaded when the server is first started.When a user invokes a servlet, a single instance of each servlet gets created, with each user request resulting in a new thread that is handed off to doGet or doPost as appropriate. The init() method simply creates or loads some data that will be used throughout the life of the servlet.

The init method definition looks like this:public void init() throws ServletException { // Initialization code...}

The service() method :The service() method is the main method to perform the actual task. The servlet container (i.e. web server) calls the service() method to handle requests coming from the client( browsers) and to write the formatted response back to the client.Each time the server receives a request for a servlet, the server spawns a new thread and calls service. The service() method checks the HTTP request type (GET, POST, PUT, DELETE, etc.) and calls doGet, doPost, doPut, doDelete, etc. methods as appropriate.

Here is the signature of this method:public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException{}

The service () method is called by the container and service method invokes doGe, doPost, doPut, doDelete, etc. methods as appropriate. So you have nothing to do with service() method but you override either doGet() or doPost() depending on what type of request you receive from the client.The doGet() and doPost() are most frequently used methods with in each service request. Here are the signature of these two methods.The doGet() MethodA GET request results from a normal request for a URL or from an HTML form that has no METHOD specified and it should be handled by doGet() method.public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Servlet code}

The doPost() MethodA POST request results from an HTML form that specifically lists POST as the METHOD and it should be handled by doPost() method.public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Servlet code}

The destroy() method :The destroy() method is called only once at the end of the life cycle of a servlet. This method gives your servlet a chance to close database connections, halt background threads, write cookie lists or hit counts to disk, and perform other such cleanup activities.

After the destroy() method is called, the servlet object is marked for garbage collection. The destroy method definition looks like this: public void destroy() { // Finalization code... }

Page 33: mc0078

Architecture Digram:The following figure depicts a typical servlet life-cycle scenario. First the HTTP requests coming to the server are delegated to the servlet container.The servlet container loads the servlet before invoking the service() method.Then the servlet container handles multiple requests by spawning multiple threads, each thread executing the service() method of a single instance of the servlet

Book ID: B0832 3. What is the difference between TCP and UDP?

Answer: TCP is a Transmission Control Protocol. UDP is a User Datagram Protocol.There are four major differences between UDP and TCP:1. TCP can establishes a Connection and UDP cannot.2. TCP provides a stream of unlimited length, UDP sends small packets.3.TCP gurantees that as long as you have a connection data sent will arrive at the destination, UDP provides not guarantee delivery.4.UDP is faster for sending small amounts of data since no connection setup is required, the data can be sent in less time then it takes for TCP to establish a connectionTCP is a connection oriented protocol, which means that everytime a packet is sent say from host A to B, we will get an acknowledgement. Whereas UDP on the other hand, is a connection less protocol.Where will it be used : TCP -> Say you have a file transfer and you need to ensure that the file reaches intact, and time is not a factor, in such a case we can use TCP.CP(Transmission Control Protocol). TCP is a connection-oriented protocol, a connection can be made from client to server, and from then on any data can be sent along that connection. o Reliable - when you send a message along a TCP socket, you know it will get there unless the connection fails completely. If it gets lost along the way, the server will re-request the lost part. This means complete integrity, things don't get corrupted.

Page 34: mc0078

o Ordered - if you send two messages along a connection, one after the other, you know the first message will get there first. You don't have to worry about data arriving in the wrong order. o Heavyweight - when the low level parts of the TCP "stream" arrive in the wrong order, resend requests have to be sent, and all the out of sequence parts have to be put back together, so requires a bit of work to piece together. 2. UDP(User Datagram Protocol). A simpler message-based connectionless protocol. With UDP you send messages(packets) across the network in chunks. o Unreliable - When you send a message, you don't know if it'll get there, it could get lost on the way. o Not ordered - If you send two messages out, you don't know what order they'll arrive in. o Lightweight - No ordering of messages, no tracking connections, etc. It's just fire and forget! This means it's a lot quicker, and the network card / OS have to do very little work to translate the data back from the packets.

4. Explain the life cycle of a Servlet?Answer: Servlet Life Cycle

Now that you have seen the basic structure of a servlet, let’s review the process by which a server invokes a servlet. This process can be broken down into the nine steps as follows:1. The server loads the servlet when it is first requested by the client or if configured to do so, at server start-up. The servlet may be loaded from either a local or a remote location using the standard Java class loading facility.This step is equivalent to the following code:

Class c=Class.forName(“com.sourcestream.MyServlet”);

It should be noted that when referring to servlets, the term load often refers to the process of both loading and instantiating the servlet.

2. The server creates one or more instances of the servlet class. Depending on implementation. The server may create a single instance that services all requests through multiple threads or create a pool

Page 35: mc0078

of instances from which one chosen to service each new request. This step is equivalent to the following Java code:Servlet s=(Servlet) c.newInstance (); where ‘c’ is the same Class object created in previous step.3. The server constructs a ServerConfig object that provides initialization information to the servlet.4. The server calls the servlet’s init () method, passing the object constructed in step 3 as a parameter. The init () method is guaranteed to finish execution prior to the servlet processing the first request. If the server has created multiple servlet instances (step 2), the init () method is called one time for each instance.5. The server constructs a ServletRequest or HttpServletRequest object from the data included in the client’s request. It also constructs a ServletResponse or HttpServletResponse object that provides methods for customizing the server’s response. The type of object passed in these two parameters depends on whether the servlet extends the GenericServlet class or the HttpServlet class, respectively.6. The server calls the servlet’s service() method passing the objects constructed in step 5 as parameters. When concurrent requests arrive, multiple service() methods can run in separate threads.7. The service () method processes the client request by evaluating the ServletRequest or HttpServletRequest object and responds using ServletResponse or HttpServletResponse object.8. If the server receives another request for this servlet, the process begins again at step 5.9. When instructed to unload the servlet, perhaps by the server administrator or programmatically by the servlet itself, the server calls the servlet’s destroy() method. The servlet is then eligible for garbage collection.The above mentioned nine steps illustrate the entire lifecycle of a servlet. The following figure shows the flow of the servlet lifecycle.

6. Describe the following with respect to CORBA: a. Implementing a CORBA Client b. Object Implementations

Also write code snippets to demonstrate the above conceptsAnswer: Exceptions in CORBA IDL: CORBA IDL allows exceptions to be defined in interfaces and thrown by their ethods. To illustrate this point, we have defined our list of shapes inthe server as a sequence of a fixed length (line 4) and have defined FullException (line6), which is thrown by the method newShape (line 7) if the client attempts to add a shape when the sequence is full.Invocation semantics: Remote invocation in CORBA has at-most-once call semantics as the default. However, IDL may specify that the invocation of a particular method has maybe semantics by using the oneway keyword. The client does not block on oneway requests, which can be used only for methods without results. For an example of aoneway request, see the example on callbacks at the end of Section 17.2.1.The CORBA Naming service◊ The CORBA Naming Service is discussed in Section17.3.1. It is a binder that provides operations including rebind for servers to register theremote object references of CORBA objects by name and resolve for clients to look them up by name. The names are structured in a hierarchic fashion, and each name in a path is inside a structure called a NameComponent. This makes access in a simple example seem rather complex.CORBA pseudo objects (Jaa 2 version 1.4) ◊ Implementations of CORBA provide some interfaces to the functionality of the ORB that programmers need to use. They are called pseudo-objects because they cannot be used like CORBA objects; for example, they cannot be passed as arguments in RMIs. They have IDL interfaces and are implemented as libraries. Those relevant to our simple example are:

Page 36: mc0078

• The ORB interface includes: The method init, which must be called to initialize the ORB; the method resolve_initial_references, which is used to find services such as the Naming Service and the root POA; other methods, which enable conversions between remote object references and strings.• The POA (Portable Object Adaptor – see Figure 17.6 and page 678) interface includes: A method for activating a POAmanager; a method servant_to_reference for registering a CORBA object.

CORBA client and server example (for Java 2 version 1.4)

This section outlines the steps necessary to produce client and server programs that use the IDL Shape and ShapeList interfaces shown in Figure 17.1. This is followed by a discussion of callbacks in CORBA. We use Java as the client and server languages, but the approach is similar for other languages. The interface compiler idlj can be applied to the CORBA interfaces to generate the following items: • The equivalent Java interfaces – two per IDL interface. For example, the interfaces ShapeListOperations and ShapeList are shown in Figure 17.2.• The server skeletons for each idl interface. The names of skeleton classes end in POA, for example ShapeListPOA.• The proxy classes or client stubs, one for each IDL interface. The names of these classes end in Stub, for example _ShapeListStub. CORBA CASE STUDY• A Java class to correspond to each of the structs defined with the IDL interfaces.In our example, classes Rectangle and GraphicalObject are generated. Each ofthese classes contains a declaration of one instance variable for each field in thecorresponding struct and a pair of constructors, but no other methods.• Classes called helpers and holders, one for each of the types defined in the IDLinterface. A helper class contains the narrow method, which is used to cast downfrom a given object reference to the class to which it belongs, which is lower downthe class hierarchy. For example, the narrow method in ShapeHelper casts down toclass Shape. The holder classes deal with out and inout arguments, which cannot bemapped directly onto Java. See Exercise 17.9 for an example of the use of holders.Server program◊ The server program should contain implementations of one or moreIDL interfaces. For a server written in an object-oriented language such as Java or C++,these implementations are implemented as servant classes. CORBA objects areinstances of servant classes.When a server creates an instance of a servant class, it must register it with thePOA, which makes the instance into a CORBA object and gives it a remote objectreference. Unless this is done, it will not be able to receive remote invocations. Readerswho studied Chapter 5 carefully may realize that registering the object with the POAcauses it to be recorded in the CORBA equivalent of the remote object table.In our example, the server contains implementations of the interfaces Shape andShapeList in the form of two servant classes, together with a server class that contains ainitialization section (see Section 5.2.5) in its main method.The servant classes: Each servant class extends the corresponding skeleton class andimplements the methods of an IDL interface using the method signatures defined inthe equivalent Java interface. The servant class that implements the ShapeListinterface is named ShapeListServant, although any other name could have beenchosen. Its outline is shown in Figure 17.3. Consider the method newShape in line 1,which is a factory method because it creates Shape objects. To make a Shape objecta CORBA object, it is registered with the POA by means of its servant_to_referencemethod, as shown in line 2. Complete versions of the IDL interface and the client andserver classes in this example are available at cdk3.net/corba.

Page 37: mc0078

The server: The main method in the server class ShapeListServer is shown in Figure17.4. It first creates and initializes the ORB (line 1). It gets a reference to the rootFigure 17.2 Java interfaces generated by idlj from CORBA interface ShapeList.public interface ShapeListOperations {Shape newShape(GraphicalObject g) throws ShapeListPackage.FullException;Shape[] allShapes();int getVersion();}public interface ShapeList extends ShapeListOperations, org.omg.CORBA.Object,org.omg.CORBA.portable.IDLEntity { } // interface ShapeListSECTION 17.2 CORBA RMI 675POA and activates the POAManager (lines 2 & 3). Then it creates an instance ofShapeListServant, which is just a Java object (line 4). It then makes it into a CORBAobject by registering it with the POA (line 5). After this, it registers the server withthe Naming Service. It then waits for incoming client requests (line 10).Servers using the Naming Service first get a root naming context (line 6), then make aNameComponent (line 7), define a path (line 8) and finally use the rebind method (line9) to register the name and remote object reference. Clients carry out the same steps butuse the resolve method as shown in Figure 17.5 line 2.The client program◊ An example client program is shown in Figure 17.5. It creates andinitializes an ORB (line 1), then contacts the Naming Service to get a reference to theremote ShapeList object by using its resolve method (line 2). After that it invokes itsmethod allShapes (line 3) to obtain a sequence of remote object references to all theShapes currently held at the server. It then invokes the getAllState method (line 4),giving as argument the first remote object reference in the sequence returned; the resultis supplied as an instance of the GraphicalObject class.Figure 17.3 ShapeListServant class of the Java server program for CORBA interface ShapeListimport org.omg.CORBA.*;import org.omg.PortableServer.POA;class ShapeListServant extends ShapeListPOA {private POA theRootpoa;private Shape theList[];private int version;private static int n=0;public ShapeListServant(POA rootpoa){theRootpoa = rootpoa;// initialize the other instance variables}public Shape newShape(GraphicalObject g) throws ShapeListPackage.FullException {1version++; Shape s = null;ShapeServant shapeRef = new ShapeServant( g, version);try {org.omg.CORBA.Object ref = theRoopoa.servant_to_reference(shapeRef); 2s = ShapeHelper.narrow(ref);} catch (Exception e) {}if(n >=100) throw new ShapeListPackage.FullException();theList[n++] = s;return s;}public Shape[] allShapes(){ ... }

Page 38: mc0078

public int getVersion() { ... }}CORBA CASE STUDYThe getAllState method seems to contradict our earlier statement that objectscannot be passed by value in CORBA, because both client and server deal in instancesof the class GraphicalObject. However, there is no contradiction: the CORBA objectreturns a struct, and clients using a different language might see it differently. Forexample, in the C++ language the client would see it as a struct. Even in Java, thegenerated class GraphicalObject is more like a struct because it has no methods.Client programs should always catch CORBA SystemExceptions, which report onerrors due to distribution (see line 5). Client programs should also catch the exceptionsdefined in the IDL interface, such as the FullException thrown by the newShape method.This example illustrates the use of the narrow operation: the resolve operation ofthe Naming Service returns a value of type Object; this type is narrowed to suit theparticular type required – ShapeList.Callbacks◊ Callbacks can be implemented in CORBA in a manner similar to the onedescribed for Java RMI in Section 5.5.1. For example, the WhiteboardCallbackinterface may be defined as follows:interface WhiteboardCallback {oneway void callback(in int version);};Figure 17.4 Java class ShapeListServerimport org.omg.CosNaming.*;import org.omg.CosNaming.NamingContextPackage.*;import org.omg.CORBA.*;import org.omg.PortableServer.*;public class ShapeListServer {public static void main(String args[]) {try{ORB orb = ORB.init(args, null); 1POA rootpoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));2rootpoa.the_POAManager().activate(); 3ShapeListServant shapeRef = new ShapeListServant(rootpoa); 4org.omg.CORBA.Object ref = rootpoa.servant_to_reference(SLSRef); 5ShapeList SLRef = ShapeListHelper.narrow(ref);org.omg.CORBA.ObjectobjRef= orb.resolve_initial_references("NameService");NamingContext ncRef = NamingContextHelper.narrow(objRef);NameComponent nc = new NameComponent("ShapeList", ""); 6NameComponent path[] = {nc}; 7ncRef.rebind(path, SLRef); 8orb.run(); 9} catch (Exception e) { ... }}}SECTION 17.2 CORBA RMI 677This interface is implemented as a CORBA object by the client, enabling the server tosend the client a version number whenever new objects are added. But before the servercan do this, the client needs to inform the server of the remote object reference of itsobject. To make this possible, the ShapeList interface requires additional methods suchas register and deregister, as follows:

Page 39: mc0078

int register(in WhiteboardCallback callback);void deregister(in int callbackId);After a client has obtained a reference to the ShapeList object and created an instance ofWhiteboardCallback, it uses the register method of ShapeList to inform the server thatit is interested in receiving callbacks. The ShapeList object in the server is responsiblefor keeping a list of interested clients and notifying all of them each time its versionnumber increases when a new object is added. The callback method is declared asoneway so that the server may use asynchronous calls to avoid delay as it notifies eachclient.17.2.2 The architecture of CORBAThe architecture is designed to support the role of an object request broker that enablesclients to invoke methods in remote objects, where both clients and servers can beimplemented in a variety of programming languages. The main components of theCORBA architecture are illustrated in Figure 17.6.Figure 17.5 Java client program for CORBA interfaces Shape and ShapeListimport org.omg.CosNaming.*;import org.omg.CosNaming.NamingContextPackage.*;import org.omg.CORBA.*;public class ShapeListClient{public static void main(String args[]) {try{ORB orb = ORB.init(args, null); 1org.omg.CORBA.Object objRef =orb.resolve_initial_references("NameService");NamingContext ncRef = NamingContextHelper.narrow(objRef);NameComponent nc = new NameComponent("ShapeList", "");NameComponent path [] = { nc };ShapeList shapeListRef =ShapeListHelper.narrow(ncRef.resolve(path)); 2Shape[] sList = shapeListRef.allShapes(); 3GraphicalObject g = sList[0].getAllState(); 4} catch(org.omg.CORBA.SystemException e) {...}}