mc0078 java programming

43
Master of Computer Applications Sikkim Manipal University Directorate of Distance Education Assignment Name : Gaurav Singh Jantwal Registration No. : Learning Center : Learning Center Code : Course : MCA Subject : MC0078 – Java Programming Semester : IV Semester Module No. : Date of submission : Marks awarded : Directorate of Distance Education Sikkim Manipal University II Floor, Syndicate House Manipal – 576104 _________________ ___ ________________ ____ ________________ ____ Signature of Coordinator Signature of Center Signature of Evaluator Gaurav Singh Jantwal 511230075

Upload: gaurav-singh-jantwal

Post on 06-Aug-2015

1.240 views

Category:

Documents


0 download

DESCRIPTION

SMUDE MC0078 Java ProgrammingIV / 4th SemesterMCA SMU Assigment

TRANSCRIPT

Page 1: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

Assignment

Name : Gaurav Singh Jantwal

Registration No. :

Learning Center :

Learning Center Code

:

Course : MCA

Subject : MC0078 – Java Programming

Semester : IV Semester

Module No. :

Date of submission :

Marks awarded :

Directorate of Distance EducationSikkim Manipal UniversityII Floor, Syndicate House

Manipal – 576104

_______________________________________

____________________

_Signature of Coordinator Signature of Center Signature of Evaluator

Gaurav Singh Jantwal 511230075

Page 2: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

Comments by the Subject Evaluator:

________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________

Suggestions for improvement:

________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________

Gaurav Singh Jantwal 511230075

Page 3: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

1. What are the difference between an interface and an abstract class?

Answer 1: An abstract class is a class that leaves one or more method implementations unspecified by declaring one or more methods abstract. An abstract method has no body (i.e., no implementation). A subclass is required to override the abstract method and provide an implementation. Hence, an abstract class is incomplete and cannot be instantiated, but can be used as a base class.

abstract public class abstract-base-class-name {// abstract class has at least one abstract methodpublic abstract return-type abstract-method-name ( formal-params );... // other abstract methods, object methods, class methods

}

public class derived-class-name extends abstract-base-class-name {public return-type abstract-method-name (formal-params) { stmt-list; }... // other method implementations

}

It would be an error to try to instantiate an object of an abstract type:

abstract-class-name obj = new abstract-class-name(); // ERROR!

That is, operator new is invalid when applied to an abstract class.

An interface is a specification, or contract, for a set of methods that a class that implements the interface must conform to in terms of the type signature of the methods. The class that implements the interface provides an implementation for each method, just as with an abstract method in an abstract class.

So, you can think of an interface as an abstract class with all abstract methods. The interface itself can have either public, package, private or protected access defined. All methods declared in an interface are implicitly abstract and implicitly public. It is not necessary, and in fact considered redundant to declare a method in an interface to be abstract.

You can define data in an interface, but it is less common to do so. If there are data fields defined in an interface, then they are implicitly defined to be:

public

static

final

In other words, any data defined in an interface are treated as public constants. Note that a class and an interface in the same package cannot share the same name. Methods declared in an interface cannot be declared final. Why?

Interface declarationInterface names and class names in the same package must be distinct.

public interface interface-name {// if any data are defined, they must be constantspublic static final type-name var-name = constant-expr;// one or more implicitly abstract and public methodsreturn-type method-name ( formal-params );

}

When to use an Interface versus when to use an abstract class:

Gaurav Singh Jantwal 511230075

Page 4: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

Having reviewed their basic properties, there are two primary differences between interfaces and abstract classes:

An abstract class can have a mix of abstract and non-abstract methods, so some default implementations can be defined in the abstract base class. An abstract class can also have static methods, static data, private and protected methods, etc. In other words, a class is a class, so it can contain features inherent to a class. The downside to an abstract base class is that since there is only single inheritance in Java, you can only inherit from one class.

An interface has a very restricted use, namely, to declare a set of public abstract method signatures that a subclass is required to implement. An interface defines a set of type constraints, in the form of type signatures, which impose a requirement on a subclass to implement the methods of the interface. Since you can inherit multiple interfaces, they are often a very useful mechanism to allow a class to have different behaviors in different situations of usage by implementing multiple interfaces.

It is usually a good idea to implement an interface when you need to define methods that are to be explicitly overridden by some subclass. If you then want some of the methods implemented with default implementations that will be inherited by a subclass, then create an implementation class for the interface, and have other class inherit (extend) that class, or just use an abstract base class instead of an interface.

Gaurav Singh Jantwal 511230075

Page 5: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

2. Explain the following with respect to Inheritance in Java: Answer 2:

a. Various Access Specifiers and their usage

In the previous lessons on inheritance, we’ve been making all of our data members public in order to simplify the examples. In this section, we’ll talk about the role of access specifiers in the inheritance process, as well as cover the different types of inheritance possible in C++.

To this point, you’ve seen the private and public access specifiers, which determine who can access the members of a class. As a quick refresher, public members can be accessed by anybody. Private members can only be accessed by member functions of the same class. Note that this means derived classes cannot access private members!

class Base{

private: int m_nPrivate; // can only be accessed by Base member functions (not derived classes)public: int m_nPublic; // can be accessed by anybody

};

When dealing with inherited classes, things get a bit more complex.

First, there is a third access specifier that we have yet to talk about because it’s only useful in an inheritance context. The protected access specifier restricts access to member functions of the same class, or those of derived classes.

class Base{

public: int m_nPublic; // can be accessed by anybodyprivate: int m_nPrivate; // can only be accessed by Base member functions (but not derived classes)protected: int m_nProtected; // can be accessed by Base member functions, or derived classes.

};

class Derived: public Base{public: Derived() {

// Derived's access to Base members is not influenced by the type of inheritance used, so the following is always true:

m_nPublic = 1; // allowed: can access public base members from derived classm_nPrivate = 2; // not allowed: cannot access private base members from derived classm_nProtected = 3; // allowed: can access protected base members from derived class

}};

int main(){

Base cBase;cBase.m_nPublic = 1; // allowed: can access public members from outside classcBase.m_nPrivate = 2; // not allowed: cannot access private members from outside classcBase.m_nProtected = 3; // not allowed: cannot access protected members from outside class

}

Second, when a derived class inherits from a base class, the access specifiers may change depending on the method of inheritance. There are three different ways for classes to inherit from other classes: public, private, and protected.

Gaurav Singh Jantwal 511230075

Page 6: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

To do so, simply specify which type of access you want when choosing the class to inherit from:

// inherit from Base publiclyclass Pub: public Base{}; // inherit from Base privatelyclass Pri: private Base{}; // inherit from Base protectedlyclass Pro: protected Base{}; class Def: Base // Defaults to private inheritance{};

If you do not choose an inheritance type, C++ defaults to private inheritance (just like members default to private access if you do not specify otherwise).

That gives us 9 combinations: 3 member access specifiers (public, private, and protected), and 3 inheritance types (public, private, and protected).

The rest of this section will be devoted to explaining the difference between these.

Before we get started, the following should be kept in mind as we step through the examples. There are three ways that members can be accessed:

A class can always access its own members regardless of access specifier. The public accesses the members of a class based on the access specifiers of that class. A derived class accesses inherited members based on the access specifiers of its immediate parent. A derived

class can always access its own members regardless of access specifier.

This may be a little confusing at first, but hopefully will become clearer as we step through the examples.

Public inheritance

Public inheritance is by far the most commonly used type of inheritance. In fact, very rarely will you use the other types of inheritance, so your primary focus should be on understanding this section. Fortunately, public inheritance is also the easiest to understand. When you inherit a base class publicly, all members keep their original access specifications. Private members stay private, protected members stay protected, and public members stay public.

class Base{

public: m_nPublic;private: int m_nPrivate;protected: int m_nProtected;

};

Gaurav Singh Jantwal 511230075

Page 7: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

class Pub: public Base{

// Public inheritance means:// m_nPublic stays public// m_nPrivate stays private// m_nProtected stays protected

Pub(){

// the derived class always uses the immediate parent's class access specifications// Thus, Pub uses Base's access specifiersm_nPublic = 1; // okay: anybody can access public membersm_nPrivate = 2; // not okay: derived classes can't access private members in the base class!m_nProtected = 3; // okay: derived classes can access protected members

}}; int main(){

// Outside access uses the access specifiers of the class being accessed.// in this case, the access specifiers of cPub. Because Pub has inherited publicly from Base,// no access specifiers have been changed.Pub cPub;cPub.m_nPublic = 1; // okay: anybody can access public memberscPub.m_nPrivate = 2; // not okay: cannot access private members from outside classcPub.m_nProtected = 3; // not okay: cannot access protected members from outside class

}

This is fairly straightforward. The things worth noting are:

1. Derived classes cannot directly access private members of the base class.2. The protected access specifier allows derived classes to directly access members of the base class while not

exposing those members to the public.3. The derived class uses access specifiers from the base class.4. The outside uses access specifiers from the derived class.

To summarize in table form:

Public inheritance

Base access specifier Derived access specifier Derived class access? Public access?

Public Public Yes Yes

Private Private No No

Protected Protected Yes No

Gaurav Singh Jantwal 511230075

Page 8: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

Private inheritance

With private inheritance, all members from the base class are inherited as private. This means private members stay private, and protected and public members become private.

Note that this does not affect that way that the derived class accesses members inherited from its parent! It only affects the code trying to access those members through the derived class.

class Base{

public: int m_nPublic;private: int m_nPrivate;protected: int m_nProtected;

}; class Pri: private Base{

// Private inheritance means:// m_nPublic becomes private// m_nPrivate stays private// m_nProtected becomes private Pri(){

// The derived class always uses the immediate parent's class access specifications// Thus, Pub uses Base's access specifiersm_nPublic = 1; // okay: anybody can access public membersm_nPrivate = 2; // not okay: derived classes can't access private members in the base class!m_nProtected = 3; // okay: derived classes can access protected members

}}; int main(){

// Outside access uses the access specifiers of the class being accessed.// Note that because Pri has inherited privately from Base,// all members of Base have become private when access through Pri.Pri cPri;cPri.m_nPublic = 1; // not okay: m_nPublic is now a private member when accessed through PricPri.m_nPrivate = 2; // not okay: cannot access private members from outside classcPri.m_nProtected = 3; // not okay: m_nProtected is now a private member when accessed through Pri

// However, we can still access Base members as normal through Base:Base cBase;cBase.m_nPublic = 1; // okay, m_nPublic is publiccBase.m_nPrivate = 2; // not okay, m_nPrivate is privatecBase.m_nProtected = 3; // not okay, m_nProtected is protected

}

Gaurav Singh Jantwal 511230075

Page 9: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

To summarize in table form:

Private inheritance

Base access specifier Derived access specifier Derived class access? Public access?

Public Private Yes No

Private Private No No

Protected Private Yes No

Protected inheritance

Protected inheritance is the last method of inheritance. It is almost never used, except in very particular cases. With protected inheritance, the public and protected members become protected, and private members stay private.

To summarize in table form:

Protected inheritance

Base access specifier Derived access specifier Derived class access? Public access?

Public Protected Yes No

Private Private No No

Protected Protected Yes No

Protected inheritance is similar to private inheritance. However, classes derived from the derived class still have access to the public and protected members directly. The public (stuff outside the class) does not.

Summary

The way that the access specifiers, inheritance types, and derived classes interact causes a lot of confusion. To try and clarify things as much as possible:

First, the base class sets it’s access specifiers. The base class can always access it’s own members. The access specifiers only affect whether outsiders and derived classes can access those members.

Second, derived classes have access to base class members based on the access specifiers of the immediate parent. The way a derived class accesses inherited members is not affected by the inheritance method used!

Finally, derived classes can change the access type of inherited members based on the inheritance method used. This does not affect the derived classes own members, which have their own access specifiers. It only affects whether outsiders and classes derived from the derived class can access those inherited members.

Gaurav Singh Jantwal 511230075

Page 10: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

A final example:

class Base{

public: int m_nPublic;private: int m_nPrivate;protected: int m_nProtected;

};

Base can access its own members without restriction. The public can only access m_nPublic. Derived classes can access m_nPublic and m_nProtected.

class D2: private Base{

public: int m_nPublic2;private: int m_nPrivate2;protected: int m_nProtected2;

}

D2 can access its own members without restriction. D2 can access Base’s members based on Base’s access specifiers. Thus, it can access m_nPublic and m_nProtected, but not m_nPrivate. Because D2 inherited Base privately, m_nPublic, m_nPrivate, and m_nProtected are now private when accessed through D2. This means the public can not access any of these variables when using a D2 object, nor can any classes derived from D2.

class D3: public D2{

public: int m_nPublic3;private: int m_nPrivate3;protected: int m_nProtected3;

};

D3 can access its own members without restriction. D3 can access D2 s members based on D2 s access specifiers. Thus, D3′ ′ has access to m_nPublic2 and m_nProtected2, but not m_nPrivate2. D3 access to Base members is controlled by the access specifier of its immediate parent. This means D3 does not have access to any of Base’s members because they all became private when D2 inherited them.

Gaurav Singh Jantwal 511230075

Page 11: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

b. Abstract classes and their applications

An abstract class is a class that leaves one or more method implementations unspecified by declaring one or more methods abstract. An abstract method has no body (i.e., no implementation). A subclass is required to override the abstract method and provide an implementation. Hence, an abstract class is incomplete and cannot be instantiated, but can be used as a base class.

abstract public class abstract-base-class-name {

// abstract class has at least one abstract method

public abstract return-type abstract-method-name ( formal-params );

... // other abstract methods, object methods, class methods

}

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

public return-type abstract-method-name (formal-params) { stmt-list; }

... // other method implementations

}

It would be an error to try to instantiate an object of an abstract type:

abstract-class-name obj = new abstract-class-name();

That is, operator new is invalid when applied to an abstract class.

abstract class Point {private int x, y;public Point(int x, int y) { this.x = x; this.y = y; }public void move(int dx, int dy) { x += dx; y += dy; plot(); }public abstract void plot(); // has no implementation

}

abstract class ColoredPoint extends Point {private int color;protected public ColoredPoint(int x, int y, int color){super(x, y); this.color = color; }

}

class SimpleColoredPoint extends ColoredPoint {public SimpleColoredPoint(int x, int y, int color) { super(x,y,color); }public void plot() { ... } // code to plot a SimpleColoredPoint

}

Since ColoredPoint does not provide an implementation of the plot method, it must be declared abstract. The SimpleColoredPoint class does implement the inherited plot method. It would be an error to try to instantiate a Point object or a ColoredPoint object. However, you can declare a Point reference and initialize it with an instance of a subclass object that implements the plot method:

Point p = new SimpleColoredPoint(a, b, red); p.plot();

An abstract class mixes the idea of mutable data in the form of instance variables, non-abstract methods, and abstract methods. An abstract class with only static final instance variables and all abstract methods is called an interface.

Gaurav Singh Jantwal 511230075

Page 12: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

3. Describe Exception Handling in JAVA

Answer 3:

Exception HandlingA Java exception is an object that describes an exceptional (that is, error) condition that has occurred in a piece of code. When an exceptional condition arises, an object representing that exception is created and thrown in the method that caused the error. That method may choose to handle the exception itself, or pass it on. Exceptions can be generated by the Java run-time system, or they can be manually generated by the code. Exceptions thrown by Java relate to fundamental errors that violate the rules of the Java language or the constraints of the Java execution environment. Manually generated exceptions are typically used to report some error condition to the caller of a method. Java exception handling is managed via five keywords: try, catch, throw, throws, and finally.

Program statements that must be monitored for exceptions are contained within a try block. If an exception occurs within the try block, it is thrown. The code can catch this exception (using catch) and handle it in some rational manner. System-generated exceptions are automatically thrown by the Java run-time system. To manually throw an exception, use the keyword throw. Any exception that is thrown out of a method must be specified as such by a throws clause. Any code that absolutely must be executed before a method returns is put in a finally block.

Finally

finally creates a block of code that will be executed after a try/catch block has completed and before the code following the try/catch block. The finally block will execute whether or not an exception is thrown. If an exception is thrown, the finally block will execute even if no catch statement matches the exception. Any time a method is about to return to the caller from inside a try/catch block, via an uncaught exception or an explicit return statement, the finally clause is also executed just before the method returns. This can be useful for closing file handles and freeing up any other resources that might have been allocated at the beginning of a method with the intent of disposing of them before returning. The finally clause is optional. However, each try statement requires at least one catch or a finally clause.

This is the general form of an exception-handling block: try {

// block of code to monitor for errors}catch (ExceptionType1 exOb) {

// exception handler for ExceptionType1}catch (ExceptionType2 exOb) {

// exception handler for ExceptionType2}finally {

// block of code to be executed before try block ends}

If a finally block is associated with a try, the finally block will be executed uponconclusion of the try.

Example for try and catch

The following program includes a try block and a catch clause which processes the Arithmetic Exception generated by the division-by-zero error

Gaurav Singh Jantwal 511230075

Page 13: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

class Exc2 {public static void main (String args []) {

int d, a;try {

// monitor a block of code.d = 0;a = 42 / d;System.out.println ("This will not be printed.");

} catch (Arithmetic Exception e) {// catch divide-by-zero error

System.out.println ("Division by zero.");}finally{}System.out.println ("After catch statement.");

}}

ThrowsA throws clause lists the types of exceptions that a method might throw. This is necessary for all exceptions, except those of type Error or Runtime Exception, or any of their subclasses. All other exceptions that a method can throw must be declared in the throws clause. If they are not, a compile-time error will result.

This is the general form of a method declaration that includes a throws clause:type method-name (parameter-list) throws exception-list{

// body of method}

ThrowIt is possible for the gram to throw an exception explicitly, using the throw statement. The general form of throw is shown here:

throw ThrowableInstance;

The flow of execution stops immediately after the throw statement; any subsequent statements are not executed.

A sample program that creates and throws an exceptionclass ThrowDemo {

static void demoproc() {try {

throw new NullPointerException("demo");} catch(NullPointerException e) {

System.out.println("Caught inside demoproc.");throw e; // rethrow the exception

}}public static void main(String args[]) {

try {demoproc();

} catch(NullPointerException e) {

System.out.println("Recaught: " + e);}

}}

Gaurav Singh Jantwal 511230075

Page 14: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

4. What do you mean by Object Adapter? Explain with an example?

Answer 4:

Object Adapters

The designs in Figures 1 and 2 are class adapters that adapt through subclassing. In a class adapter design, the new adapter

class implements the desired interface and subclasses an existing class. This approach will not always work, notably when

the set of methods that you need to adapt is not specified in an interface.

Figure 1 Figure 2

In such a case, you can create an object adapter—an adapter that uses delegation rather than subclassing. Figure 3 shows

this design. (Compare this to the earlier diagrams.)

Figure 3: You can create an object adapter by subclassing the class that you need, fulfilling the required methods by relying

on an object of an existing class.

The NewClass class in Figure 3 is an example of Adapter. An instance of this class is an instance of the RequiredClass class.

In other words, the NewClass class meets the needs of the client. The NewClass class can adapt the ExistingClass class to

meet the client’s needs by using an instance of ExistingClass.

Gaurav Singh Jantwal 511230075

Page 15: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

For a more concrete example, suppose that the simulation package worked directly with a Skyrocket class, without

specifying an interface to define the behaviors that the simulation needs. Figure 4 shows this class.

Figure 4 In this alternative design, the com.oozinoz.simulation package does not specify the interface it needs for modeling

a rocket.

The Skyrocket class uses a fairly primitive model of the physics of a rocket. For example, the class assumes that the rocket

is entirely consumed as its fuel burns. Suppose that you want to apply the more sophisticated physical model that the

Oozinoz PhysicalRocket class uses. To adapt the logic in the PhysicalRocket class to the needs of the simulation, you can

create an OozinozSkyrocket class as an object adapter that subclasses Skyrocket and that uses a PhysicalRocket object, as

Figure 5 shows.

Figure 5 When completed, this diagram will show an object adapter design that uses information from an existing class to

meet the needs that a client has of a Skyrocket object.

Gaurav Singh Jantwal 511230075

Page 16: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

As an object adapter, the OozinozSkyrocket class subclasses from Skyrocket, not PhysicalRocket. This will allow an

OozinozSkyrocket object to serve as a substitute wherever the simulation client needs a Skyrocket object. The Skyrocket

class supports subclassing by making its simTime variable protected.

The code for the OozinozSkyrocket class might be as follows:

package com.oozinoz.firework;import com.oozinoz.simulation.*;public class OozinozSkyrocket extends Skyrocket {

private PhysicalRocket rocket;public OozinozSkyrocket(PhysicalRocket r) {

super( r.getMass(0), r.getThrust(0), r.getBurnTime());rocket = r;

}public double getMass() {

return rocket.getMass(simTime); }

public double getThrust() { return rocket.getThrust(simTime); }}

The OozinozSkyrocket class lets you supply an OozinozSkyrocket object anywhere that the simulation package requires a

Skyrocket object. In general, object adapters partially overcome the problem of adapting an object to an interface that is

not expressly defined.

The object adapter for the Skyrocket class is a riskier design than the class adapter that implements the RocketSim

interface. But we should not complain too much. At least no methods were marked final, which would have prevented us

from overriding them.

Gaurav Singh Jantwal 511230075

Page 17: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

5. Describe the following with respect to implementation of Sockets in Java:

Answer 5:

a. Reading from and Writing to a Socket

Let's look at a simple example that illustrates how a program can establish a connection to a server program using the Socket class and then, how the client can send data to and receive data from the server through the socket.

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.

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.");System.exit(1);

} catch (IOException e) {System.err.println("Couldn't get I/O for the connection to: taranist.");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();

}}

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()));

Gaurav Singh Jantwal 511230075

Page 18: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

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 stream and opens aBufferedReader 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 theBufferedReader. 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, 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:

1. Open a socket.2. Open an input stream and output stream to the socket.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.

Gaurav Singh Jantwal 511230075

Page 19: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

b. Writing the Server Side of a Socket

This section shows you how to write a server and the client that goes with it. The server in the client/server pair serves up Knock Knock jokes. Knock Knock jokes are favored by children and are usually vehicles for bad puns. They go like this:

Server: "Knock knock!"Client: "Who's there?"Server: "Dexter."Client: "Dexter who?"Server: "Dexter halls with boughs of holly."Client: "Groan."

The example consists of two independently running Java programs: the client program and the server program. The client program is implemented by a single class, KnockKnockClient, and is very similar to the EchoClient example from the previous section. The server program is implemented by two classes: KnockKnockServer and KnockKnockProtocol, KnockKnockServer contains the main method for the server program and performs the work of listening to the port, establishing connections, and reading from and writing to the socket. KnockKnockProtocol serves up the jokes. It keeps track of the current joke, the current state (sent knock knock, sent clue, and so on), and returns the various text pieces of the joke depending on the current state. This object implements the protocol-the language that the client and server have agreed to use to communicate.

The following section looks in detail at each class in both the client and the server and then shows you how to run them.

The Knock Knock ServerThis section walks through the code that implements the Knock Knock server program. Here is the complete source for the KnockKnockServer class.

The server program begins by creating a new ServerSocket object to listen on a specific port (see the statement in bold in the following code segment). When writing a server, choose a port that is not already dedicated to some other service. KnockKnockServer listens on port 4444 because 4 happens to be my favorite number and port 4444 is not being used for anything else in my environment:

try {serverSocket = new ServerSocket(4444);

} catch (IOException e) {

System.out.println("Could not listen on port: 4444");System.exit(-1);

}

ServerSocket is a java.net class that provides a system-independent implementation of the server side of a client/server socket connection. The constructor forServerSocket throws an exception if it can't listen on the specified port (for example, the port is already being used). In this case, the KnockKnockServer has no choice but to exit.

If the server successfully binds to its port, then the ServerSocket object is successfully created and the server continues to the next step--accepting a connection from a client (shown in bold):

Socket clientSocket = null;try {

clientSocket = serverSocket.accept();} catch (IOException e) {

System.out.println("Accept failed: 4444");System.exit(-1);

}

The accept method waits until a client starts up and requests a connection on the host and port of this server (in this example, the server is running on the hypothetical machine taranis on port 4444). When a connection is requested and successfully established, the accept method returns a new Socket object which is bound to the same local port and has its

Gaurav Singh Jantwal 511230075

Page 20: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

remote address and remote port set to that of the client. The server can communicate with the client over this new Socket and continue to listen for client connection requests on the original ServerSocket This particular version of the program doesn't listen for more client connection requests.

After the server successfully establishes a connection with a client, it communicates with the client using this code:

PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));String inputLine, outputLine;

// initiate conversation with clientKnockKnockProtocol kkp = new KnockKnockProtocol();outputLine = kkp.processInput(null);out.println(outputLine);

while ((inputLine = in.readLine()) != null) { outputLine = kkp.processInput(inputLine);out.println(outputLine);if (outputLine.equals("Bye."))

break;}This code:

1. Gets the socket's input and output stream and opens readers and writers on them.2. Initiates communication with the client by writing to the socket (shown in bold).3. Communicates with the client by reading from and writing to the socket (the while loop).

Step 1 is already familiar. Step 2 is shown in bold and is worth a few comments. The bold statements in the code segment above initiate the conversation with the client. The code creates a KnockKnockProtocol object-the object that keeps track of the current joke, the current state within the joke, and so on.

After the KnockKnockProtocol is created, the code calls KnockKnockProtocol's process input method to get the first message that the server sends to the client. For this example, the first thing that the server says is "Knock! Knock!" Next, the server writes the information to the PrintWriter connected to the client socket, thereby sending the message to the client.

Step 3 is encoded in the while loop. As long as the client and server still have something to say to each other, the server reads from and writes to the socket, sending messages back and forth between the client and the server.

The server initiated the conversation with a "Knock! Knock!" so afterwards the server must wait for the client to say "Who's there?" As a result, the while loop iterates on a read from the input stream. The readLine method waits until the client responds by writing something to its output stream (the server's input stream). When the client responds, the server passes the client's response to the KnockKnockProtocol object and asks the KnockKnockProtocol object for a suitable reply. The server immediately sends the reply to the client via the output stream connected to the socket, using a call to println. If the server's response generated from the KnockKnockServer object is "Bye." this indicates that the client doesn't want any more jokes and the loop quits.

The KnockKnockServer class is a well-behaved server, so the last several lines of this section of KnockKnockServer clean up by closing all of the input and output streams, the client socket, and the server socket:

out.close();in.close();clientSocket.close();serverSocket.close();

The Knock Knock Protocol

The KnockKnockProtocol class implements the protocol that the client and server use to communicate. This class keeps track of where the client and the server are in their conversation and serves up the server's response to the client's statements. The KnockKnockServer object contains the text of all the jokes and makes sure that the client gives the proper

Gaurav Singh Jantwal 511230075

Page 21: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

response to the server's statements. It wouldn't do to have the client say "Dexter who?" when the server says "Knock! Knock!"

All client/server pairs must have some protocol by which they speak to each other; otherwise, the data that passes back and forth would be meaningless. The protocol that your own clients and servers use depends entirely on the communication required by them to accomplish the task.

The Knock Knock Client

The KnockKnockClient class implements the client program that speaks to the KnockKnockServer. KnockKnockClient is based on the EchoClient program in the previous section, Reading from and Writing to a Socket and should be somewhat familiar to you. But we'll go over the program anyway and look at what's happening in the client in the context of what's going on in the server.

When you start the client program, the server should already be running and listening to the port, waiting for a client to request a connection. So, the first thing the client program does is to open a socket that is connected to the server running on the hostname and port specified:

kkSocket = new Socket("taranis", 4444);out = new PrintWriter(kkSocket.getOutputStream(), true);in = new BufferedReader(new InputStreamReader(kkSocket.getInputStream()));

When creating its socket, KnockKnockClient uses the host name taranis, the name of a hypothetical machine on our network. When you type in and run this program, change the host name to the name of a machine on your network. This is the machine on which you will run the KnockKnockServer.

The KnockKnockClient program also specifies the port number 4444 when creating its socket. This is a remote port number--the number of a port on the server machine--and is the port to which KnockKnockServer is listening. The client's socket is bound to any available local port--a port on the client machine. Remember that the server gets a new socket as well. That socket is bound to local port number 4444 on its machine. The server's socket and the client's socket are connected.

Next comes the while loop that implements the communication between the client and the server. The server speaks first, so the client must listen first. The client does this by reading from the input stream attached to the socket. If the server does speak, it says "Bye." and the client exits the loop. Otherwise, the client displays the text to the standard output and then reads the response from the user, who types into the standard input. After the user types a carriage return, the client sends the text to the server through the output stream attached to the socket.

while ((fromServer = in.readLine()) != null) {System.out.println("Server: " + fromServer);if (fromServer.equals("Bye."))

break;fromUser = stdIn.readLine();if (fromUser != null) {

System.out.println("Client: " + fromUser);out.println(fromUser);

}}

The communication ends when the server asks if the client wishes to hear another joke, the client says no, and the server says "Bye."

Gaurav Singh Jantwal 511230075

Page 22: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

In the interest of good housekeeping, the client closes its input and output streams and the socket:

out.close();in.close();stdIn.close();kkSocket.close();

Running the Programs

You must start the server program first. To do this, run the server program using the Java interpreter, just as you would any other Java application. Remember to run the server on the machine that the client program specifies when it creates the socket.

Next, run the client program. Note that you can run the client on any machine on your network; it does not have to run on the same machine as the server.

If you are too quick, you might start the client before the server has a chance to initialize itself and begin listening on the port. If this happens, you will see a stack trace from the client. If this happens, just restart the client.

If you forget to change the host name in the source code for the KnockKnockClient program, you will see the following error message:

Don't know about host: taranis

To fix this, modify the KnockKnockClient program and provide a valid host name for your network. Recompile the client program and try again.

If you try to start a second client while the first client is connected to the server, the second client just hangs. The next section, Supporting Multiple Clients, talks about supporting multiple clients.

When you successfully get a connection between the client and server, you will see the following text displayed on your screen:

Server: Knock! Knock!

Now, you must respond with:

Who's there?

The client echoes what you type and sends the text to the server. The server responds with the first line of one of the many Knock Knock jokes in its repertoire. Now your screen should contain this (the text you typed is in bold):

Server: Knock! Knock!Who's there?Client: Who's there?Server: Turnip

Now, you respond with:

Turnip who?"

Again, the client echoes what you type and sends the text to the server. The server responds with the punch line. Now your screen should contain this:

Server: Knock! Knock!Who's there?

Gaurav Singh Jantwal 511230075

Page 23: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

Client: Who's there?Server: TurnipTurnip who?Client: Turnip who?Server: Turnip the heat, it's cold in here! Want another? (y/n)

If you want to hear another joke, type y; if not, type n. If you type y, the server begins again with "Knock! Knock!" If you type n, the server says "Bye." thus causing both the client and the server to exit.

If at any point you make a typing mistake, the KnockKnockServer object catches it and the server responds with a message similar to this:

Server: You're supposed to say "Who's there?"!

The server then starts the joke over again:

Server: Try again. Knock! Knock!

Note that the KnockKnockProtocol object is particular about spelling and punctuation but not about capitalization.

Supporting Multiple Clients

To keep the KnockKnockServer example simple, we designed it to listen for and handle a single connection request. However, multiple client requests can come into the same port and, consequently, into the same ServerSocket. Client connection requests are queued at the port, so the server must accept the connections sequentially. However, the server can service them simultaneously through the use of threads - one thread per each client connection.

The basic flow of logic in such a server is this:

while (true) {accept a connection;create a thread to deal with the client;

}

The thread reads from and writes to the client connection as necessary.

Gaurav Singh Jantwal 511230075

Page 24: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

6. Define RMI. Define the architecture of RMI invocation.

Answer 6: RMI applications often comprise two separate programs, a server and a client. A typical server program creates some remote objects, makes references to these objects accessible, and waits for clients to invoke methods on these objects. A typical client program obtains a remote reference to one or more remote objects on a server and then invokes methods on them. RMI provides the mechanism by which the server and the client communicate and pass information back and forth. Such an application is sometimes referred to as a distributed object application.

Designing a Remote Interface

At the core of the compute engine is a protocol that enables tasks to be submitted to the compute engine, the compute engine to run those tasks, and the results of those tasks to be returned to the client. This protocol is expressed in the interfaces that are supported by the compute engine. The remote communication for this protocol is illustrated in the following figure.

Fig. 2.2.1.1

Each interface contains a single method. The compute engine’s remote interface, Compute, enables tasks to be submitted to the engine. The client interface, Task, defines how the compute engine executes a submitted task.

The compute Compute interface defines the remotely accessible part, the compute engine itself. Here is the source code for the Compute interface:

package compute;import java.rmi.Remote;import java.rmi.RemoteException;public interface Compute extends Remote {

<T> T executeTask(Task<T> t) throws RemoteException;}

By extending the interface java.rmi.Remote, the Compute interface identifies itself as an interface whose methods can be invoked from another Java virtual machine. Any object that implements this interface can be a remote object.

As a member of a remote interface, the executeTask method is a remote method. Therefore, this method must be defined as being capable of throwing a java.rmi.RemoteException. This exception is thrown by the RMI system from a remote method invocation to indicate that either a communication failure or a protocol error has occurred. A RemoteException is a checked exception, so any code invoking a remote method needs to handle this exception by either catching it or declaring it in its throws clause.

The second interface needed for the compute engine is the Task interface, which is the type of the parameter to the executeTask method in the Compute interface. The compute.Task interface defines the interface between the compute engine and the work that it needs to do, providing the way to start the work. Here is the source code for the Task interface:

package compute;public interface Task<T> {

T execute();}

The Task interface defines a single method, execute, which has no parameters and throws no exceptions. Because the interface does not extend Remote, the method in this interface doesn’t need to list java.rmi.RemoteException in its throws clause.

Gaurav Singh Jantwal 511230075

Page 25: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

The Task interface has a type parameter, T, which represents the result type of the task’s computation. This interface’s execute method returns the result of the computation and thus its return type is T.

The Compute interface’s executeTask method, in turn, returns the result of the execution of the Task instance passed to it. Thus, the executeTask method has its own type parameter, T, that associates its own return type with the result type of the passed Task instance.

RMI uses the Java object serialization mechanism to transport objects by value between Java virtual machines. For an object to be considered serializable, its class must implement the java.io.Serializable marker interface. Therefore, classes that implement the Task interface must also implement Serializable, as must the classes of objects used for task results.

Different kinds of tasks can be run by a Compute object as long as they are implementations of the Task type. The classes that implement this interface can contain any data needed for the computation of the task and any other methods needed for the computation.

Here is how RMI makes this simple compute engine possible. Because RMI can assume that the Task objects are written in the Java programming language, implementations of the Task object that were previously unknown to the compute engine are downloaded by RMI into the compute engine’s Java virtual machine as needed. This capability enables clients of the compute engine to define new kinds of tasks to be run on the server machine without needing the code to be explicitly installed on that machine.

The compute engine, implemented by the ComputeEngine class, implements the Compute interface, enabling different tasks to be submitted to it by calls to its executeTask method. These tasks are run using the task’s implementation of the execute method and the results, are returned to the remote client.

Implementing a Remote Interface

This section discusses the task of implementing a class for the compute engine. In general, a class that implements a remote interface should at least do the following:

Declare the remote interfaces being implemented Define the constructor for each remote object Provide an implementation for each remote method in the remote interfaces

An RMI server program needs to create the initial remote objects and export them to the RMI runtime, which makes them available to receive incoming remote invocations. This setup procedure can be either encapsulated in a method of the remote object implementation class itself or included in another class entirely. The setup procedure should do the following:

Create and install a security manager Create and export one or more remote objects Register at least one remote object with the RMI registry (or with another naming service, such as a service

accessible through the Java Naming and Directory Interface) for bootstrapping purposes

The complete implementation of the compute engine follows. The enqine.ComputeEngine class implements the remote interface Compute and also includes the main method for setting up the compute engine. Here is the source code for the ComputeEngine class:

package engine;import java.rmi.RemoteException;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;import java.rmi.server.UnicastRemoteObject;import compute.Compute;import compute.Task;public class ComputeEngine implements Compute {

public ComputeEngine() {super();

}

Gaurav Singh Jantwal 511230075

Page 26: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

public <T> T executeTask(Task<T> t) {

return t.execute();}

public static void main(String[] args) {

if (System.getSecurityManager() == null) {System.setSecurityManager(new SecurityManager());

}try {

String name = "Compute";Compute engine = new ComputeEngine();

Compute stub = (Compute) UnicastRemoteObject.exportObject(engine, 0); Registry registry = LocateRegistry.getRegistry(); registry.rebind(name, stub);

System.out.println("ComputeEngine bound");} catch (Exception e) {

System.err.println("ComputeEngine exception:"); e.printStackTrace(); } }}

The following sections discuss each component of the compute engine implementation.

Declaring the Remote Interfaces Being Implemented

The implementation class for the compute engine is declared as follows:

public class ComputeEngine implements Compute

This declaration states that the class implements the Compute remote interface and therefore can be used for a remote object.

The ComputeEngine class defines a remote object implementation class that implements a single remote interface and no other interfaces. The ComputeEngine class also contains two executable program elements that can only be invoked locally. The first of these elements is a constructor for ComputeEngine instances. The second of these elements is a main method that is used to create a ComputeEngine instance and make it available to clients.

Defining the Constructor for the Remote Object

The ComputeEngine class has a single constructor that takes no arguments. The code for the constructor is as follows:

public ComputeEngine() {super();

}

This constructor just invokes the superclass constructor, which is the no-argument constructor of the Object class. Although the superclass constructor gets invoked even if omitted from the ComputeEngine constructor, it is included for clarity.

Providing Implementations for Each Remote Method

The class for a remote object provides implementations for each remote method specified in the remote interfaces. The Compute interface contains a single remote method, executeTask, which is implemented as follows:

public <T> T executeTask(Task<T> t) {return t.execute();

Gaurav Singh Jantwal 511230075

Page 27: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

}

This method implements the protocol between the ComputeEngine remote object and its clients. Each client provides the ComputeEngine with a Task object that has a particular implementation of the Task interface’s execute method. The ComputeEngine executes each client’s task and returns the result of the task’s execute method directly to the client.

Passing Objects in RMI

Arguments to or return values from remote methods can be of almost any type, including local objects, remote objects, and primitive data types. More precisely, any entity of any type can be passed to or from a remote method as long as the entity is an instance of a type that is a primitive data type, a remote object, or a serializable object, which means that it implements the interface java.io.Serializable.

Some object types do not meet any of these criteria and thus cannot be passed to or returned from a remote method. Most of these objects, such as threads or file descriptors, encapsulate information that makes sense only within a single address space. Many of the core classes, including the classes in the packages java.lang and java.util, implement the Serializable interface.

The rules governing how arguments and return values are passed are as follows:

Remote objects are essentially passed by reference. A remote object reference is a stub, which is a client-side proxy that implements the complete set of remote interfaces that the remote object implements.

Local objects are passed by copy, using object serialization. By default, all fields are copied except fields that are marked static or transient. Default serialization behavior can be overridden on a class-by-class basis.

Passing a remote object by reference means that any changes made to the state of the object by remote method invocations are reflected in the original remote object. When a remote object is passed, only those interfaces that are remote interfaces are available to the receiver. Any methods defined in the implementation class or defined in non-remote interfaces implemented by the class are not available to that receiver.

For example, if you were to pass a reference to an instance of the ComputeEngine class, the receiver would have access only to the compute engine’s executeTask method. That receiver would not see the ComputeEngine constructor, its main method, or its implementation of any methods of java.lang.Object.

In the parameters and return values of remote method invocations, objects that are not remote objects are passed by value. Thus, a copy of the object is created in the receiving Java virtual machine. Any changes to the object’s state by the receiver are reflected only in the receiver’s copy, not in the sender’s original instance. Any changes to the object’s state by the sender are reflected only in the sender’s original instance, not in the receiver’s copy.

Implementing the Server’s main Method

The most complex method of the ComputeEngine implementation is the main method. The main method is used to start the ComputeEngine and therefore needs to do the necessary initialization and housekeeping to prepare the server to accept calls from clients. This method is not a remote method, which means that it cannot be invoked from a different Java virtual machine. Because the main method is declared static, the method is not associated with an object at all but rather with the class ComputeEngine.

Gaurav Singh Jantwal 511230075

Page 28: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

Creating and Installing a Security Manager

The main method’s first task is to create and install a security manager, which protects access to system resources from untrusted downloaded code running within the Java virtual machine. A security manager determines whether downloaded code has access to the local file system or can perform any other privileged operations.

If an RMI program does not install a security manager, RMI will not download classes (other than from the local class path) for objects received as arguments or return values of remote method invocations. This restriction ensures that the operations performed by downloaded code are subject to a security policy.

Here’s the code that creates and installs a security manager:

if (System.getSecurityManager() == null) {System.setSecurityManager(new SecurityManager());

}

Making the Remote Object Available to Clients

Next, the main method creates an instance of ComputeEngine and exports it to the RMI runtime with the following statements:

Compute engine = new ComputeEngine(); Compute stub = (Compute) UnicastRemoteObject.exportObject(engine, 0);

The static UnicastRemoteObject.exportObject method exports the supplied remote object so that it can receive invocations of its remote methods from remote clients. The second argument, an int, specifies which TCP port to use to listen for incoming remote invocation requests for the object. It is common to use the value zero, which specifies the use of an anonymous port. The actual port will then be chosen at runtime by RMI or the underlying operating system. However, a non-zero value can also be used to specify a specific port to use for listening. Once the exportObject invocation has returned successfully, the ComputeEngine remote object is ready to process incoming remote invocations.

The exportObject method returns a stub for the exported remote object. Note that the type of the variable stub must be Compute, not ComputeEngine, because the stub for a remote object only implements the remote interfaces that the exported remote object implements.

The exportObject method declares that it can throw a RemoteException, which is a checked exception type. The main method handles this exception with its try/catch block. If the exception were not handled in this way, RemoteException would have to be declared in the throws clause of the main method. An attempt to export a remote object can throw a RemoteException if the necessary communication resources are not available, such as if the requested port is bound for some other purpose.

Before a client can invoke a method on a remote object, it must first obtain a reference to the remote object. Obtaining a reference can be done in the same way that any other object reference is obtained in a program, such as by getting the reference as part of the return value of a method or as part of a data structure that contains such a reference.

The system provides a particular type of remote object, the RMI registry, for finding references to other remote objects. The RMI registry is a simple remote object naming service that enables clients to obtain a reference to a remote object by name. The registry is typically only used to locate the first remote object that an RMI client needs to use. That first remote object might then provide support for finding other objects.

The java.rmi.registry.Registry remote interface is the API for binding (or registering) and looking up remote objects in the registry. The java.rmi.registry.LocateRegistry class provides static methods for synthesizing a remote reference to a registry at a particular network address (host and port). These methods create the remote reference object containing the specified network address without performing any remote communication. LocateRegistry also provides static methods for creating a new registry in the current Java virtual machine, although this example does not use those methods. Once a remote object is registered with an RMI registry on the local host, clients on any host can look up the remote object by

Gaurav Singh Jantwal 511230075

Page 29: MC0078 Java Programming

Master of Computer Applications Sikkim Manipal UniversityDirectorate of Distance Education

name, obtain its reference, and then invoke remote methods on the object. The registry can be shared by all servers running on a host, or an individual server process can create and use its own registry.

The ComputeEngine class creates a name for the object with the following statement:

String name = "Compute";

The code then adds the name to the RMI registry running on the server. This step is done later with the following statements:

Registry registry = LocateRegistry.getRegistry();registry.rebind(name, stub);

This rebind invocation makes a remote call to the RMI registry on the local host. Like any remote call, this call can result in a RemoteException being thrown, which is handled by the catch block at the end of the main method.

Note the following about the Registry.rebind invocation:

The no-argument overload of LocateRegistry.getRegistry synthesizes a reference to a registry on the local host and on the default registry port, 1099. You must use an overload that has an int parameter if the registry is created on a port other than 1099.

When a remote invocation on the registry is made, a stub for the remote object is passed instead of a copy of the remote object itself. Remote implementation objects, such as instances of ComputeEngine, never leave the Java virtual machine in which they were created. Thus, when a client performs a lookup in a server’s remote object registry, a copy of the stub is returned. Remote objects in such cases are thus effectively passed by (remote) reference rather than by value.

For security reasons, an application can only bind, unbind, or rebind remote object references with a registry running on the same host. This restriction prevents a remote client from removing or overwriting any of the entries in a server’s registry. A lookup, however, can be requested from any host, local or remote.

Once the server has registered with the local RMI registry, it prints a message indicating that it is ready to start handling calls. Then, the main method completes. It is not necessary to have a thread wait to keep the server alive. As long as there is a reference to the ComputeEngine object in another Java virtual machine, local or remote, the ComputeEngine object will not be shut down or garbage collected. Because the program binds a reference to the ComputeEngine in the registry, it is reachable from a remote client, the registry itself. The RMI system keeps the ComputeEngine’s process running. The ComputeEngine is available to accept calls and won’t be reclaimed until its binding is removed from the registry and no remote clients hold a remote reference to the ComputeEngine object.

The final piece of code in the ComputeEngine.main method handles any exception that might arise. The only checked exception type that could be thrown in the code is RemoteException, either by the UnicastRemoteObject.exportObject invocation or by the registry rebind invocation. In either case, the program cannot do much more than exit after printing an error message. In some distributed applications, recovering from the failure to make a remote invocation is possible. For example, the application could attempt to retry the operation or choose another server to continue the operation.

Gaurav Singh Jantwal 511230075