You are on page 1of 78

MCA Sem.

IV Java Programming

Assignment Set -1

Q. 1. Write a program to perform the basic arithmetic operations:

a) Addition class Prog21 { public static void main(String[] args) { int i = 10; int j = 20; i = i + j; System.out.println("The sum is: " + i); } } b) Subtraction class Prog21 { public static void main(String[] args) { int i = 20; int j = 10;

i = i - j; System.out.println("The sum is: " + i); } } c) Multiplication class Prog21 { public static void main(String[] args) { int i = 20; int j = 10; i = i * j; System.out.println("The sum is: " + i); } } d) Division class Prog21 { public static void main(String[] args) { int i = 20; int j = 10; i = i / j; System.out.println("The sum is: " + i); } }

Q. 2. Discuss the following with suitable example programs for each:

A) Data Types in Java

There are two kinds of data types in Java Primitives/standard data types. Abstract/derived data types. Primitives Data Types Primitive data types (also know as standard data types) are the data types that are built into the Java language. The Java compiler holds details instructions on each operation the data types that are built into the Java language. The Java compiler holds detailed instructions on each legal operation the data type supports. There are eight primitive data types in Java.

The data types byte, short, int, long, float and double are numeric data types. The first four of these can hold only whole numbers whereas the last two (float and double) can

hold decimal values like 5.05. All these data types can hold negative values. However, the keyword unsigned can be used to restrict the range of values to positive numbers. Amongst others, boolean can hold only the value true or false and char can hold only a single character. Abstract/Derived Data Types Abstract data types are based on primitives data types and have more functionality that the primitive data types. For example, String is an abstract data type that can store alphabets, digits and other characters like /, (); :$#. You cannot perform calculations on a variable of the string data type even if the data stored in it has digits.

B) Variables in Java When you learned algebraic equations in school, you used x and y to represent values in equations. Unlike pi which has a constant value of 3.14, the values of x and y are not constant in equations. Java provides constants and variables to store data in programs. Java allocates memory to each variable and constant you use in your program. As in algebra, the values of variables may change in a program, but the values of constants, as the name suggests, do not change. You must assign unique names to variables and constants. Variable names are used in a program in much the same way as they are in ordinary Algebra. Each variable used in a program must be declared. That is to say, the program must contain a statement specifying precisely what kind of information (data type) the variable will contain. This applies to every variable used in the program, regardless of the type. Naming Variables

A program refers to a variable using its name. Certain rules and conventions govern the naming of variables. You must adhere to rules. Conventions help improve the readability of the program, but following them is not mandatory. Rules for Naming Variables in Java A variable name: Must not be a keyword in Java. Must not begin with a digit. Must not contain embedded spaces. Can contain characters from various alphabets, like Japanese, Greek, and Cyrillic. Syntax for Defining Variables All the attributes of a class are defined as data members. The syntax used to declare a class variable is: <data_type> <variable_name> As the braces { } are used to mark the beginning and end of a class, a semicolon ; is used to mark the end of a statement.

Q. 3. What are the different types of control statements?

Ans. Following statements are used to control the flow of execution in a program. 1. Decision Making Statements If-else statement Switch case statement 2. Looping Statement For loop While loop Do-while loop 3. Other statement Break Continue Label If-else statement The if statement is Javas conditional branch statement. It can be used to route program execution through two different paths. Here is the general form of the if statement: if (condition) statement1; else statement2;

Here, each statement may be a single statement or a compound statement enclosed in curly braces (that is, a block). The condition is any expression that returns a boolean value. The else clause is optional. The if works like this: If the condition is true, then statement1 is executed. Otherwise, statement2 (if it exists) is executed. In no case will both statements be executed. For example, consider the following:

Figure 3.6 Most often, the expression used to control the if will involve the relational operators. However, this is not technically necessary. It is possible to control the if using a single boolean variable, as shown in this code fragment: boolean dataAvailable; // if (dataAvailable) ProcessData(); else

waitForMoreData(); Remember, only one statement can appear directly after the if or the else. If you want to include more statements, youll need to create a block, as in this fragment: int bytesAvailable; // if (bytesAvailable > 0) { ProcessData(); bytesAvailable -= n; } else waitForMoreData(); Here, both statements within the if block will execute if bytesAvailable is greater than zero. Some programmers find it convenient to include the curly braces when using the if, even when there is only one statement in each clause. This makes it easy to add another statement at a later date, and you dont have to worry about forgetting the braces. In fact, forgetting to define a block when one is needed is a common cause of errors. For example, consider the following code fragment: int bytesAvailable; // if (bytesAvailable > 0) { ProcessData();

bytesAvailable -= n; } else waitForMoreData(); bytesAvailable = n; It seems clear that the statement bytesAvailable = n; was intended to be executed inside the else clause, because of the indentation level. However, as you recall, whitespace is insignificant to Java, and there is no way for the compiler to know what was intended. This code will compile without complaint, but it will behave incorrectly when run. The preceding example is fixed in the code that follows: int bytesAvailable; // if (bytesAvailable > 0) { ProcessData(); bytesAvailable -= n; } else { waitForMoreData(); bytesAvailable = n; } The if-else-if Ladder

A common programming construct that is based upon a sequence of nested ifs is the ifelseif ladder. It looks like this: if(condition) statement; else if(condition) statement; else if(condition) statement; . . . else statement; The if statements are executed from the top down. As soon as one of the conditions controlling the if is true, the statement associated with that if is executed, and the rest of the ladder is bypassed. If none of the conditions is true, then the final else statement will be executed. The final else acts as a default condition; that is, if all other conditional tests fail, then the last else statement is performed. If there is no final else and all other conditions are false, then no action will take place.

Here is a program that uses an if-else-if ladder to determine which season a particular month is in. // Demonstrate if-else-if statements. class IfElse { public static void main(String args[ ]) { int month = 4; // April String season; if(month == 12 || month == 1 || month == 2) season = "Winter"; else if(month == 3 || month == 4 || month == 5) season = "Spring"; else if(month == 6 || month == 7 || month == 8) season = "Summer"; else if(month == 9 || month == 10 || month == 11) season = "Autumn"; else season = "Bogus Month"; System.out.println("April is in the " + season + ".");

} } Here is the output produced by the program: April is in the Spring. You might want to experiment with this program before moving on. As you will find, no matter what value you give month, one and only one assignment statement within the ladder will be executed. Switch Statement The switch statement is Javas multiway branch statement. It provides an easy way to dispatch execution to different parts of your code based on the value of an expression. As such, it often provides a better alternative than a large series of if-else-if statements. Here is the general form of a switch statement: switch (expression) { case value1: // statement sequence break; case value2: // statement sequence break;

. . . case valueN: // statement sequence break; default: // default statement sequence } The expression must be of type byte, short, int, or char; each of the values specified in the case statements must be of a type compatible with the expression. Each case value must be a unique literal (that is, it must be a constant, not a variable). Duplicate case values are not allowed. The switch statement works like this: The value of the expression is compared with each of the literal values in the case statements. If a match is found, the code sequence following that case statement is executed. If none of the constants matches the value of the expression, then the default statement is executed. However, the default statement is optional. If no case matches and no default is present, then no further action is taken. The break statement is used inside the switch to terminate a statement sequence. When a break statement is encountered, execution branches to the first line of code that follows the entire switch statement. This has the effect of "jumping out" of the switch.

Example

Figure 3.7 The break statement is optional. If you omit the break, execution will continue on into the next case. It is sometimes desirable to have multiple cases without break statements between them. For example, consider the following program: // In a switch, break statements are optional. class MissingBreak { public static void main(String args[ ]) { for(int i=0; i<12; i++) switch(i) { case 0: case 1:

case 2: case 3: case 4: System.out.println("i is less than 5"); break; case 5: case 6: case 7: case 8: case 9: System.out.println("i is less than 10"); break; default: System.out.println("i is 10 or more"); } } } This program generates the following output:

i is less than 5 i is less than 5 i is less than 5 i is less than 5 i is less than 5 i is less than 10 i is less than 10 i is less than 10 i is less than 10 i is less than 10 i is 10 or more i is 10 or more Nested switch Statements You can use a switch as part of the statement sequence of an outer switch. This is called a nested switch. Since a switch statement defines its own block, no conflicts arise between the case constants in the inner switch and those in the outer switch. For example, the following fragment is perfectly valid: switch(count) { case 1:

switch(target) { // nested switch case 0: System.out.println("target is zero"); break; case 1: // no conflicts with outer switch System.out.println("target is one"); break; } break; case 2: // Here, the case 1: statement in the inner switch does not conflict with the case 1: statement in the outer switch. The count variable is only compared with the list of cases at the outer level. If count is 1, then target is compared with the inner list cases. In summary, there are three important features of the switch statement to note: The switch differs from the if in that switch can only test for equality, whereas if can evaluate any type of Boolean expression. That is, the switch looks only for a match between the value of the expression and one of its case constants. No two case constants in the same switch can have identical values. Of course, a switch statement enclosed by an outer switch can have case constants in common. A switch statement is usually more efficient than a set of nested ifs.

The last point is particularly interesting because it gives insight into how the Java compiler works. When it compiles a switch statement, the Java compiler will inspect each of the case constants and create a "jump table" that it will use for selecting the path of execution depending on the value of the expression. Therefore, if you need to select among a large group of values, a switch statement will run much faster than the equivalent logic coded using a sequence of if-elses. The compiler can do this because it knows that the case constants are all the same type and simply must be compared for equality with the switch expression. The compiler has no such knowledge of a long list of if expressions. for Loop The usage of for loop is as follows for (initial statement; termination condition; increment instruction) statement; When multiple statements are to be included in the for loop, the statements are included inside flower braces. for (initial statement; termination condition; increment instruction) { statement1; statement2; } The example below prints numbers from 1 to 10

Figure 3.8 The results of the above program is shown below

Figure 3.9 Like all other programming languages, Java allows loops to be nested. That is, one loop may be inside another. For example, here is a program that nests for loops: // Loops may be nested. class Nested {

public static void main(String args[ ]) { int i, j; for(i=0; i<10; i++) { for(j=i; j<10; j++) System.out.print("."); System.out.println(); } } } The output produced by this program is shown here: . .. . .. While Statement

The while loop is Javas most fundamental looping statement. It repeats a statement or block while its controlling expression is true. Here is its general form: while (condition) { // body of loop } The condition can be any Boolean expression. The body of the loop will be executed as long as the conditional expression is true. When condition becomes false, control passes to the next line of code immediately following the loop. The curly braces are unnecessary if only a single statement is being repeated. Example

do.while statement As you just saw, if the conditional expression controlling a while loop is initially false, then the body of the loop will not be executed at all. However, sometimes it is desirable to execute the body of a while loop at least once, even if the conditional expression is false to begin with. In other words, there are times when you would like to test the

termination expression at the end of the loop rather than at the beginning. Fortunately, Java supplies a loop that does just that: the do-while. The do-while loop always executes its body at least once, because its conditional expression is at the bottom of the loop. Its general form is do { // body of loop } while (condition); Each iteration of the do-while loop first executes the body of the loop and then evaluates the conditional expression. If this expression is true, the loop will repeat. Otherwise, the loop terminates. As with all of Javas loops, condition must be a boolean expression. Example

Figure 3.11 The do-while loop is especially useful when you process a menu selection, because you will usually want the body of a menu loop to execute at least once. Consider the

following program which implements a very simple help system for Javas selection and iterationstatements: // Using a do-while to process a menu selection class Menu { public static void main(String args[]) throws java.io.IOException { char choice; do { System.out.println("Help on:"); System.out.println(" 1. if"); System.out.println(" 2. switch"); System.out.println(" 3. while"); System.out.println(" 4. do-while"); System.out.println(" 5. for\n"); System.out.println("Choose one:"); choice = (char) System.in.read(); } while( choice < 1 || choice > 5); System.out.println("\n");

switch(choice) { case 1: System.out.println("The if:\n"); System.out.println("if(condition) statement;"); System.out.println("else statement;"); break; case 2: System.out.println("The switch:\n"); System.out.println("switch(expression) {"); System.out.println(" case constant:"); System.out.println(" statement sequence"); System.out.println(" break;"); System.out.println(" // "); System.out.println("}"); break; case 3: System.out.println("The while:\n"); System.out.println("while(condition) statement;");

break; case 4: System.out.println("The do-while:\n"); System.out.println("do {"); System.out.println(" statement;"); System.out.println("} while (condition);"); break; case 5: System.out.println("The for:\n"); System.out.print("for(init; condition; iteration)"); System.out.println(" statement;"); break; } } } Here is a sample run produced by this program: Help on: 1. if

2. switch 3. while 4. do-while 5. for Choose one: The do-while: do { statement; } while (condition); In the program, the do-while loop is used to verify that the user has entered a valid choice. If not, then the user is reprompted. Since the menu must be displayed at least once, the do-while is the perfect loop to accomplish this. A few other points about this example: Notice that characters are read from the keyboard by calling System.in.read( ). This is one of Javas console input functions. Although Javas console I/O methods wont be discussed in detail until System.in.read( ) is used here to obtain the users choice. It reads characters from standard input (returned as integers, which is why the return value was cast to char). By default, standard input is line buffered, so you must press ENTER before any characters that you type will be sent to your program. Javas console input is quite limited and awkward to work with. Further, most real-world Java programs and applets will be graphical and window-based. For these reasons, not much use of console input has been made in this book. However, it is useful in this

context. One other point: Because System.in.read( ) is being used, the program must specify the throws java.io.IOException clause. This line is necessary to handle input errors. Break statement By using break, you can force immediate termination of a loop, bypassing the conditional expression and any remaining code in the body of the loop. When a break statement is encountered inside a loop, the loop is terminated and program control resumes at the next statement following the loop. Here is a simple example: // Using break to exit a loop. class BreakLoop { public static void main(String args[ ]) { for(int i=0; i<100; i++) { if(i == 10) break; // terminate loop if i is 10 System.out.println("i: " + i); } System.out.println("Loop complete."); } } This program generates the following output: i: 0

i: 1 i: 2 i: 3 i: 4 i: 5 i: 6 i: 7 i: 8 i: 9 Loop complete. As you can see, although the for loop is designed to run from 0 to 99, the break statement causes it to terminate early, when i equal 10. Continue Statement Sometimes it is useful to force an early iteration of a loop. That is, you might want to continue running the loop, but stop processing the remainder of the code in its body for this particular iteration. This is, in effect, a goto just past the body of the loop, to the loops end. The continue statement performs such an action. In while and do-while loops, a continue statement causes control to be transferred directly to the conditional expression that controls the loop. In a for loop, control goes first to the iteration portion of the for statement and then to the conditional expression. For all three loops, any intermediate code is bypassed.

Here is an example program that uses continue to cause two numbers to be printed on each line: // Demonstrate continue. class Continue { public static void main (String args[]) { for (int i=0; i<10; i++) { System.out.print (i + " "); if (i%2 == 0) continue; System.out.println (""); } } } This code uses the % operator to check if i is even. If it is, the loop continues without printing a newline. Here is the output from this program: 01 23 45 67 89

As with the break statement, continue may specify a label to describe which enclosing loops to continue. Here is an example program that uses continue to print a triangular multiplication table for 0 through 9.

Q. 4. Describe the following with respect to Exception Handling: A) Exception Classes The class at the top of the exception classes hierarchy is called Throwable. Two classes are derived from the Throwable class- Error and Exception. The Exception class is used fro the exceptional conditions that have to be trapped in a program. The Error class defines a condition that does not occur under normal circumstances. In other words, the Error class is used for catastrophic failures such as VirtualMachineError. These classes are available in the java.lang package B) Common Exceptions Java has several predefined exceptions. The most common exceptions that you may encounter are described below. Arithmetic Exception This exception is thrown when an exceptional arithmetic condition has occurred. For example, a division by zero generates such an exception. NullPointer Exception This exception is thrown when an application attempts to use null where an object is required. An object that has not been allocated memory holds a null value. The situations in which an exception is thrown include:

- Using an object without allocating memory for it. - Calling the methods of a null object. - Accessing or modifying the attributes of a null object. ArrayIndexOutOfBounds Exception The exception Array Index Out Of Bounds Exception is thrown when an attempt is made to access an array element beyond the index of the array. For example, if you try to access the eleventh element of an array thats has only ten elements, the exception will be thrown.

Q.5 What is the difference between bound property and constraint property? Ans. Bound Property Bound properties support the PropertyChangeListener (in the API reference documentation) class. Sometimes when a Bean property changes, another object might need to be notified of the change, and react to the change. Whenever a bound property changes, notification of the change is sent to interested listeners. The accessor methods for a bound property are defined in the same way as those for simple properties. However, you also need to provide the event listener registration methods forPropertyChangeListener classes and fire a PropertyChangeEvent (in the API

reference documentation) event to the PropertyChangeListener objects by calling their propertyChange methods The convenience PropertyChangeSupport (in the API reference documentation) class enables your bean to implement these methods. Your bean can inherit changes from the PropertyChangeSupportclass, or use it as an inner class. In order to listen for property changes, an object must be able to add and remove itself from the listener list on the bean containing the bound property. It must also be able to respond to the event notification method that signals a property change. The PropertyChangeEvent class encapsulates property change information, and is sent from the property change event source to each object in the property change listener list with the propertyChange method. Implementing Bound Property Support Within a Bean To implement a bound property in your application, follow these steps: 1. Import the java.beans package. This gives you access to the PropertyChangeSupport class. 2. Instantiate a PropertyChangeSupport object. This object maintains the property change listener list and fires property change events. You can also make your class a PropertyChangeSupport subclass. 3. Implement methods to maintain the property change listener list. Since a PropertyChangeSupport subclass implements these methods, you merely wrap calls to the property-change support objects methods. 4. Modify a propertys set method to fire a property change event when the property is changed.

Creating a Bound Property To create the title property as a bound property for the MyBean component in the NetBeans GUI Builder, perform the following sequence of operations: 1. Right-click the Bean Patterns node in the MyBean class hierarchy. 2. Select Add|Property from the pop-up menu. 3. Fill the New Property Pattern form as shown on the following figure and click OK.

Fig. 6.6.1 Note that the title property and the multicast event source pattern

PropertyChangeListener were added to the Bean Patterns structure. You can also modify existing code generated in the previous lesson to convert the title and lines properties to the bound type as follows (where newly added code is shown in bold): import java.awt.Graphics;

import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.Serializable; import javax.swing.JComponent; /** * Bean with bound properties. */ public class MyBean extends JComponent implements Serializable { private String title; private String[] lines = new String[10]; private final PropertyChangeSupport pcs = new PropertyChangeSupport( this ); public String getTitle() { return this.title; } public void setTitle( String title ) { String old = this.title; this.title = title; this.pcs.firePropertyChange( "title", old, title ); } public String[] getLines() { return this.lines.clone(); } public String getLines( int index )

{ return this.lines[index]; } public void setLines( String[] lines ) { String[] old = this.lines; this.lines = lines; this.pcs.firePropertyChange( "lines", old, lines ); } public void setLines( int index, String line ) { String old = this.lines[index]; this.lines[index] = line; this.pcs.fireIndexedPropertyChange( "lines", index, old, lines ); } public void addPropertyChangeListener( PropertyChangeListener listener ) { this.pcs.addPropertyChangeListener( listener ); } public void removePropertyChangeListener( PropertyChangeListener listener ) { this.pcs.removePropertyChangeListener( listener ); } protected void paintComponent( Graphics g ) { g.setColor( getForeground() ); int height = g.getFontMetrics().getHeight(); paintString( g, this.title, height ); if ( this.lines != null )

{ int step = height; for ( String line : this.lines ) paintString( g, line, height += step ); } } private void paintString( Graphics g, String str, int height ) { if ( str != null ) g.drawString( str, 0, height ); } }

Constrain Property A bean property is constrained if the bean supports the Vetoable ChangeListener(in the API reference documentation) and Property ChangeEvent(in the API reference documentation) classes, and if the set method for this property throws a PropertyVetoException(in the API reference documentation). Constrained properties are more complicated than bound properties because they also support property change listeners which happen to be vetoers. The following operations in the setXXX method for the constrained property must be implemented in this order: 1. Save the old value in case the change is vetoed. 2. Notify listeners of the new proposed value, allowing them to veto the change.

3. If no listener vetoes the change (no exception is thrown), set the property to the new value. The accessor methods for a constrained property are defined in the same way as those for simple properties, with the addition that the setXXX method throws a PropertyVetoException exception. The syntax is as follows: public void setPropertyName(PropertyType pt) throws PropertyVetoException {code} Handling Vetoes If a registered listener vetoes a proposed property change by throwing a PropertyVetoException exception, the source bean with the constrained property is responsible for the following actions: Catching exceptions. Reverting to the old value for the property. Issuing a new VetoableChangeListener.vetoableChange call to all listeners to report the reversion. The VetoableChangeListener class throws a PropertyVetoException and handles the PropertyChangeEvent event fired by the bean with the constrained property. The VetoableChangeSupport provides the following operations: Keeping track of VetoableChangeListener objects. Issuing the vetoableChange method on all registered listeners. Catching any vetoes (exceptions) thrown by listeners.

Informing all listeners of a veto by calling vetoableChange again, but with the old property value as the proposed "new" value. Creating a Constrained Property To create a constrained property, set the appropriate option in the New Property Pattern form as shown on the following figure.

Fig. 6.7.1 Note that the Multicast Source Event Pattern vetoableChangeListener was added to the Bean Patterns hierarchy. You can also modify the existing code generated in the previous lesson to make the title and lines properties constrained as follows (where newly added code is shown in bold): import java.io.Serializable; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.beans.PropertyVetoException;

import java.beans.VetoableChangeListener; import java.beans.VetoableChangeSupport; import java.awt.Graphics; import javax.swing.JComponent; /** * Bean with constrained properties. */ public class MyBean extends JComponent implements Serializable { private String title; private String[] lines = new String[10]; private final PropertyChangeSupport pcs = new PropertyChangeSupport( this ); private final VetoableChangeSupport vcs = new VetoableChangeSupport( this ); public String getTitle() { return this.title; } /** * This method was modified to throw the PropertyVetoException * if some vetoable listeners reject the new title value */ public void setTitle( String title ) throws PropertyVetoException { String old = this.title; this.vcs.fireVetoableChange( "title", old, title );

this.title = title; this.pcs.firePropertyChange( "title", old, title ); } public String[] getLines() { return this.lines.clone(); } public String getLines( int index ) { return this.lines[index]; } /** * This method throws the PropertyVetoException * if some vetoable listeners reject the new lines value */ public void setLines( String[] lines ) throws PropertyVetoException { String[] old = this.lines; this.vcs.fireVetoableChange( "lines", old, lines ); this.lines = lines; this.pcs.firePropertyChange( "lines", old, lines ); } public void setLines( int index, String line ) throws PropertyVetoException { String old = this.lines[index]; this.vcs.fireVetoableChange( "lines", old, line ); this.lines[index] = line;

this.pcs.fireIndexedPropertyChange( "lines", index, old, line ); } public void addPropertyChangeListener( PropertyChangeListener listener ) { this.pcs.addPropertyChangeListener( listener ); } public void removePropertyChangeListener( PropertyChangeListener listener ) { this.pcs.removePropertyChangeListener( listener ); } /** * Registration of the VetoableChangeListener */ public void addVetoableChangeListener( VetoableChangeListener listener ) { this.vcs.addVetoableChangeListener( listener ); } public void removeVetoableChangeListener( VetoableChangeListener listener ) { this.vcs.removeVetoableChangeListener( listener ); } protected void paintComponent( Graphics g ) { g.setColor( getForeground() ); int height = g.getFontMetrics().getHeight(); paintString( g, this.title, height ); if ( this.lines != null ) { int step = height;

for ( String line : this.lines ) paintString( g, line, height += step ); } } private void paintString( Graphics g, String str, int height ) { if ( str != null ) g.drawString( str, 0, height ); } } Q-6. Define RMI. Define the architecture of RMI invocation. Ans. 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 engines 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 doesnt need to list java.rmi.RemoteException in its throws clause. The Task interface has a type parameter, T, which represents the result type of the tasks computation. This interfaces execute method returns the result of the computation and thus its return type is T. The Compute interfaces 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 engines 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 tasks 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(); }

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

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 interfaces execute method. The ComputeEngine executes each clients task and returns the result of the tasks 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 engines 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 objects state by the receiver are reflected only in the receivers copy, not in the senders original instance. Any changes to the objects state by the sender are reflected only in the senders original instance, not in the receivers copy. Implementing the Servers 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. Creating and Installing a Security Manager The main methods 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. Heres 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 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 servers 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 servers 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 ComputeEngines process running. The ComputeEngine is available to accept calls and wont 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. Q. 7. Define the following terms: 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.

An endpoint is a combination of an IP address and a port number. Every TCP connection can be uniquely identified by its two endpoints. That way you can have multiple connections between your host and the server. The java.net package in the Java platform provides a class, Socket, that implements one side of a two-way connection between your Java program and another program on the network. The Socket class sits on top of a platform-dependent implementation, hiding the details of any particular system from your Java program. By using the java.net.Socket class instead of relying on native code, your Java programs can communicate over the network in a platform-independent fashion. Additionally, java.net includes the ServerSocket class, which implements a socket that servers can use to listen for and accept connections to clients. This lesson shows you how to use the Socket and ServerSocket classes. If you are trying to connect to the Web, the URL class and related classes (URLConnection, URLEncoder) are probably more appropriate than the socket classes. In fact, URLs are a relatively high-level connection to the Web and use sockets as part of the underlying implementation. See Working with URLs for information about connecting to the Web via URLs. B) Port Generally speaking, a computer has a single physical connection to the network. All data destined for a particular computer arrives through that connection. However, the data may be intended for different applications running on the computer. So how does the computer know to which application to forward the data? Through the use of ports. Data transmitted over the Internet is accompanied by addressing information that identifies the computer and the port for which it is destined. The computer is identified by its 32-bit IP address, which IP uses to deliver data to the right computer on the network.

Ports are identified by a 16-bit number, which TCP and UDP use to deliver the data to the right application. In connection-based communication such as TCP, a server application binds a socket to a specific port number. This has the effect of registering the server with the system to receive all data destined for that port. A client can then rendezvous with the server at the servers port, as illustrated here:

Fig. 3.1.1 Definition: The TCP and UDP protocols use ports to map incoming data to a particular process running on a computer. In datagram-based communication such as UDP, the datagram packet contains the port number of its destination and UDP routes the packet to the appropriate application, as illustrated in this figure:

Fig. 3.1.2

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 wellknown 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 Clients and servers that communicate via a reliable channel, such as a TCP socket, have a dedicated point-to-point channel between themselves, or at least the illusion of one. To communicate, they establish a connection, transmit the data, and then close the connection. All data sent over the channel is received in the same order in which it was sent. This is guaranteed by the channel. In contrast, applications that communicate via datagrams send and receive completely independent packets of information. These clients and servers do not have and do not need a dedicated point-to-point channel. The delivery of datagrams to their destinations is not guaranteed. Nor is the order of their arrival. Definition: 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 datagrams to send and receive packets over the network: Datagram Socket. Datagram Packet, and Multicast Socket An application can send and receive Datagram Packets through a Datagram Socket. In addition, Datagram Packets can be broadcast to multiple recipients all listening to a Multicast Socket

1. Write a complete program for each of the following: Decision Making Statements Ans: If-else statement The if statement is Javas conditional branch statement. It through two different paths. Here is the general form of the if statement: if (condition) statement1; else statement2; Here, each statement may be a single statement or a compound statement enclosed in curly braces (that is, a block). The condition is any expression that returns a boolean value. The else clause is optional. The if works like this: If the condition is true, then statement1 is executed. Otherwise, statement2(if it exists) is executed. In no case will bot Most often, the expression used to control the if will involve the relational operators. However, this is not technically necessary. It is possible to control the if using a single boolean va this code fragment: boolean dataAvailable; //
Master of Computer Application (MCA) MC0078 Java Programming (Book ID: B0831 & B0832

can be used to route program execution hat both statements be executed. For example, consider the

July 2011

Semester 4 4 Credits B0832) Assignment Set 2

h following: variable, as shown in if (dataAvailable) ProcessData(); else waitForMoreData(); Remember, only one statement can appear directly after the if or the else. If you want to include more statements, youll need to create a block, as in this fragment: int bytesAvailable; // if (bytesAvailable > 0) { ProcessData(); bytesAvailable -= n; } else waitForMoreData(); Here, both statements within the if block will execute if bytesAvailable is greater than zero. Some programmers find it convenient to include the curly braces when using the if, even when there is only

one statement in each clause. This makes it easy to add another statement at a later date, and you dont have to worry about forgetting the braces. In fact, forgetting to define a block when one is needed is a common cause of errors. For example, consider the following code fragment: int bytesAvailable; // if (bytesAvailable > 0) { ProcessData(); bytesAvailable -= n; } else waitForMoreData(); bytesAvailable = n; It seems clear that the statement bytesAvailable = n; was intended to be executed inside the else clause, because of the indentation level. However, as you recall, whitespace is insignificant to Java, and there is no way for the compiler to know what was intended. This code will compile without complaint, but it will behave incorrectly when run. The preceding example is fixed in the code that follows: int bytesAvailable; // if (bytesAvailable > 0) { ProcessData(); bytesAvailable -= n; } else { waitForMoreData(); bytesAvailable = n; } The if-else-if Ladder A common programming construct that is based upon a sequence of nested ifs is the ifelseif ladder. It looks like this: if(condition) statement; else if(condition) statement; else if(condition) statement; . . . else statement; The if statements are executed from the top down. As soon as one of the conditions controlling the if is true, the statement associated with that if is executed, and the rest of the ladder is bypassed. If

none of the conditions is true, then the final else statement will be executed. The final else acts as a default condition; that is, if all other conditional tests fail, then the last else statement is performed. If there is no final else and all other conditions are false, then no action will take place. Here is a program that uses an if-else-if ladder to determine which season a particular month is in. // Demonstrate if-else-if statements. class IfElse { public static void main(String args[ ]) { int month = 4; // April String season; if(month == 12 || month == 1 || month == 2) season = "Winter"; else if(month == 3 || month == 4 || month == 5) season = "Spring"; else if(month == 6 || month == 7 || month == season = "Summer"; else if(month == 9 || month == 10 || month == 11) season = "Autumn"; else season = "Bogus Month"; System.out.println("April is in the " + season + "."); } } Here is the output produced by the program: April is in the Spring. You might want to experiment with this program before moving on. As you will find, no matter what value you give month, one and only one assignment statement within the ladder will be executed. Switch Statement The switch statement is Javas multiway branch statement. It provides an easy way to dispatch execution to different parts of your code based on the value of an expression. As such, it often provides a better alternative than a large series of if-else-if statements. Here is the general form of a switch statement: switch (expression) { case value1: // statement sequence break; case value2: // statement sequence break; . . . case valueN:

// statement sequence break; default: // default statement sequence } The expression must be of type byte, short, int, or char; each of the values specified in the case statements must be of a type compatible with the expression. Each case value must be a unique literal (that is, it must be a constant, not a variable). Duplicate case values are not allowed. The switch statement works like this: The value of the expression is compar values in the case statements. If a match is found, the code sequence following that case statement is executed. If none of the constants matches the value of the expression, then the default statement is executed. However, the default statement is optional. If no case matches and no default is present, then no further action is taken. The break statement is used inside the switch to terminate a statement sequence. When a break statement is encountered, execution branches to the statement. This has the effect of "jumping out" of the switch. Example The break statement is optional. If you omit the break, execution will continue on into the next case. It is sometimes desirable to h example, consider the following program: // In a switch, break statements are optional. class MissingBreak { public static void main(String args[ ]) { for(int i=0; i<12; i++) switch(i) { case 0: compared with each of the literal first line of code that follows the entire switch have multiple cases without break statements between them. For ed ave case 1: case 2: case 3: case 4: System.out.println("i is less than 5"); break; case 5: case 6: case 7: case 8: case 9: System.out.println("i is less than 10");

break; default: System.out.println("i is 10 or more"); } } } This program generates the following output: i is less than 5 i is less than 5 i is less than 5 i is less than 5 i is less than 5 i is less than 10 i is less than 10 i is less than 10 i is less than 10 i is less than 10 i is 10 or more i is 10 or more Nested switch Statements You can use a switch as part of the statement sequence of an outer switch. This is called a nested switch. Since a switch statement defines its own block, no conflicts arise between the case constants in the inner switch and those in the outer switch. For example, the following fragment is perfectly valid: switch(count) { case 1: switch(target) { // nested switch case 0: System.out.println("target is zero"); break; case 1: // no conflicts with outer switch System.out.println("target is one"); break; } break; case 2: // Here, the case 1: statement in the inner switch does not conflict with the case 1: statement in the outer switch. The count variable is only compared with the list of cases at the outer level. If count is 1, then target is compared with the inner list cases. In summary, there are three important features of the switch statement to note: The switch differs from the if in that switch can only test for equality, whereas if can evaluate any type of Boolean expression. That is, the switch looks only for a match between the value of the expression and one of its case constants.

No two case constants in the same switch can have identical values. Of course, a

switch statement enclosed by an outer switch can have case constants in common. A switch statement is usually more efficient than a set of nested ifs. The last point is particularly interesting because it gives insight into how the Java compiler works. When it compiles a switch statement, the Java compiler will inspect each of the case constants and create a "jump table" that it will use for selecting the path of execution depending on the value of the expression. Therefore, if you need to select among a large group of values, a switch statement will run much faster than the equivalent logic coded using a sequence of if-elses. The compiler can do this because it knows that the case constants are all the same type and simply must be compared for equality with the switch expression. The compiler has no such knowledge of a long list of if expressions. Looping Statements Ans: for Loop The usage of for loop is as follows for (initial statement; termination condition; increment instruction) statement; When multiple statements are to be included in the for loop, the statements are included inside flower braces. for (initial statement; termination condition; increment instruction) { statement1; statement2; } The example below prints numbers from 1 to 10 The results of the above program is shown below Like all other programming languages, Java allows loops to be nested. That is, one loop may be inside another. For example, here is a program that nests for loops: // Loops may be nested. class Nested { public static void main(String args[ ]) { int i, j; for(i=0; i<10; i++) { for(j=i; j<10; j++) System.out.print("."); System.out.println(); } } } The output produced by this program is shown here: .

.. . .. While Statement The while loop is Javas most fundamental looping statement. It repeats a statement or block while its controlling expression is true. Here is its general form: while (condition) { // body of loop } The condition can be any Boolean expression. The body of the loop will be executed as long as the conditional expression is true. When condition becomes false, control passes to the next line of code immediately following the loop. The curly braces are unnecessary if only a single statement is being repeated. Example do.while statement As you just saw, if the conditional expression controlling a while loop is initially false, then the body the loop will not be executed at all. However, sometimes it is desirable to execute the body of a while loop at least once, even if the conditional expression is false to begin with. In other words, there are times when you would like to test the termi beginning. Fortunately, Java supplies a loop that does just that: the do always executes its body at least once, because its conditional expression is at the bottom of the Its general form is do { // body of loop } while (condition); Each iteration of the do-while loop first executes the body of the loop and then evaluates the conditional expression. If this expression is true, the loop will repeat. Otherwise, the loo As with all of Javas loops, condition must be a boolean expression. Example termination expression at the end of the loop rather than at the do-while. The do of nation do-while loop loop. loop terminates. The do-while loop is especially useful when you process a menu selection, because you will usually want the body of a menu loop to execute at least once. Consider the following program which

implements a very simple help system for Javas selection and iterationstatements: // Using a do-while to process a menu selection class Menu { public static void main(String args[]) throws java.io.IOException { char choice; do { System.out.println("Help on:"); System.out.println(" 1. if"); System.out.println(" 2. switch"); System.out.println(" 3. while"); System.out.println(" 4. do-while"); System.out.println(" 5. for\n"); System.out.println("Choose one:"); choice = (char) System.in.read(); } while( choice < 1 || choice > 5); System.out.println("\n"); switch(choice) { case 1: System.out.println("The if:\n"); System.out.println("if(condition) statement;"); System.out.println("else statement;"); break; case 2: System.out.println("The switch:\n"); System.out.println("switch(expression) {"); System.out.println(" case constant:"); System.out.println(" statement sequence"); System.out.println(" break;"); System.out.println(" // "); System.out.println("}"); break; case 3: System.out.println("The while:\n"); System.out.println("while(condition) statement;"); break; case 4: System.out.println("The do-while:\n"); System.out.println("do {"); System.out.println(" statement;"); System.out.println("} while (condition);"); break; case 5: System.out.println("The for:\n"); System.out.print("for(init; condition; iteration)"); System.out.println(" statement;"); break; } } }

Here is a sample run produced by this program: Help on: 1. if 2. switch 3. while 4. do-while 5. for Choose one: The do-while: do { statement; } while (condition); In the program, the do-while loop is used to verify that the user has entered a valid choice. If not, then the user is reprompted. Since the menu must be displayed at least once, the do-while is the perfect loop to accomplish this. A few other points about this example: Notice that characters are read from the keyboard by calling System.in.read( ). This is one of Javas console input functions. Although Javas console I/O methods wont be discussed in detail until System.in.read( ) is used here to obtain the users choice. It reads characters from standard input (returned as integers, which is why the return value was cast to char). By default, standard input is line buffered, so you must press ENTER before any characters that you type will be sent to your program. Javas console input is quite limited and awkward to work with. Further, most realworld Java programs and applets will be graphical and window-based. For these reasons, not much use of console input has been made in this book. However, it is useful in this context. One other point: Because System.in.read( ) is being used, the program must specify the throws java.io.IOException clause. This line is necessary to handle input errors. 2. How do you implements inheritance in java? Ans: Inheritance is one of the cornerstones of object-oriented programming because it allows the creation of hierarchical classifications. Using inheritance, you can create a general class that defines traits common to a set of related items. This class can then be inherited by other, more specific classes, each adding those things that are unique to it. In the terminology of Java, a class that is inherited is called a superclass. The class that does the inheriting is called a subclass. Therefore, a subclass is a specialized version of a superclass. It inherits all of the instance variables and methods defined by the

superclass and add its own, unique elements. Implementing Inheritance in Java: - The extends keyword is used to derive a class from a superclass, or in other words, extend the functionality of a superclass. Syntax public class <subclass_name>extends<superclass_name> Example public class confirmed extends ticket { } Rules for Overriding Methods The method name and the order of arguments should be identical to that of the superclass method. The return type of both the methods must be the same. The overriding method cannot be less accessible than the method it overrides. For example, if the method to override is declared as public in the superclass, you cannot override it with the private keyword in the subclass. An overriding method cannot raise more exceptions than those raised by the superclass. Example // Create a superclass. class A { int i, j; void showij() { System.out.println("i and j: " + i + " " + j); } } // Create a subclass by extending class A. class B extends A { int k; void showk() { System.out.println("k: " + k); } void sum() { System.out.println("i+j+k: " + (i+j+k)); } } class SimpleInheritance { public static void main(String args[]) { A superOb = new A(); B subOb = new B(); // The superclass may be used by itself. superOb.i = 10; superOb.j = 20; System.out.println("Contents of superOb: "); superOb.showij(); System.out.println();

/* The subclass has access to all public members of its superclass. */ subOb.i = 7; subOb.j = 8; subOb.k = 9; System.out.println("Contents of subOb: "); subOb.showij(); subOb.showk(); System.out.println(); System.out.println("Sum of i, j and k in subOb:"); subOb.sum(); } } The output from this program is shown here: Contents of superOb: i and j: 10 20 Contents of subOb: i and j: 7 8 k: 9 Sum of i, j and k in subOb: i+j+k: 24 As you can see, the subclass B includes all of the members of its superclass, A. This is why subOb can access i and j and call showij ( ). Also, inside sum ( ), i and j can be referred to directly, as if they were part of B. Even though A is a superclass for B, it is also a completely independent, standalone class. Being a superclass for a subclass does not mean that the superclass cannot be used by itself. Further, a subclass can be a superclass for another subclass. The general form of a class declaration that inherits a superclass is shown here: class subclass-name extends superclass-name { // body of class } You can only specify one superclass for any subclass that you create. Java does not support the inheritance of multiple superclasses into a single subclass. (This differs from C++, in which you can inherit multiple base classes.) You can, as stated, create a hierarchy of inheritance in which a subclass becomes a superclass of another subclass. However, no class can be a superclass of itself. 3. Draw and explain the JDBC Application Architecture? Ans: The JDBC API is a Java API that can access any kind of tabular data, especially data stored in a Relational Database. JDBC helps you to write java applications that manage these three programming activities: 1. Connect to a data source, like a database

2. Send queries and update statements to the database 3. Retrieve and process the results received from the database in answer to your query JDBC Architecture: - The JDBC API supports both two-tier and three-tier processing models for database access.
Two-tier Architecture for Data Access

In the two-tier model, a Java application talks directly to the data source. This requires a JDBC driver that can communicate with the particular data source being accessed. A users commands are delivered to the database or other data source, and the results of those statements are sent back to the user. The data source may be located on another machine to which the user is connected via a network. This is referred to as a client/server configuration, with the users machine as the client, and the machine housing the data source as the server. The network can be an intranet, which, for example, connects employees within a corporation, or it can be the Internet. In the three-tier model, commands are sent to a "middle tier" of services, which then sends the commands to the data source. The data source processes the commands and sends the results back to the middle tier, which then sends them to the user. MIS directors find the threetier model very attractive because the middle tier makes it possible to maintain control over access and the kinds of updates that can be made to corporate data. Another advantage is that it simplifies the deployment of applications. Finally, in many cases, the three-tier architecture can provide performance advantages. DBMS Client Machine DBMS Proprietary Protocol Database Server Java Application JBDC Until recently, the middle tier has often been written in languages such as C or C+ +, which offer fast performance. However, with the introduction of optimizing compilers into efficient machine-specific code and technologies such as Enterprise JavaBeans, the Java platform is fast becoming the standard platform for middle making it possible to take advantage With enterprises increasingly using the Java programming language for writing server code, the JDBC API is being used more and more in the middle tier of a three

that make JDBC a server technology are its support for connection pooling, distributed transactions, and disconnected rowsets. The JDBC API is also what allows access to a data source from a Java middle tier.
Three-tier Architecture for Data Access

that translate Java bytecode middle-tier development. This is a big plus, of Javas robustness, multithreading, and security features. three-tier architecture. Some of the f features 4. What are the difference between an interface and an abstract class? Ans: 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(); // 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, and

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 declaration Interface names and class names in the same package must be distinct. public interface interface-name { // if any data are defined, they must be constants public static final type-name var-name = constant-expr; // one or more implicitly abstract and public methods return-type method-name ( formal-params );} When to use an Interface vs when to use an abstract class 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 their 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 that 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 5. Explain the working of struts with an example. Ans: Struts is modeled after the MVC design pattern, you can follow a standard development process for all of your Struts Web applications.

Identificaty of the application Views, the Controller objects that will service those Views, and the Model components being operated on. 1. Define and create all of the Views, in relation to their purpose, that will represent the user interface of our application. Add all Action Forms used by the created Views to the strutsconfig. xml file. 2. Create the components of the applications Controller. 3. Define the relationships that exist between the Views and the Controllers (strutsconfig.xml). 4. Make the appropriate modifications to the web.xml file, describe the Struts components to the Web application. Lets Start with step one. We will create the view file named index.jsp index.jsp <%@ page language="java" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <html> <head> <title>Sample Struts Application</title> </head> <body> <html:form action="Name" name="nameForm" type="example.NameForm"> <table width="80%" border="0"> <tr> <td>Name:</td> <td> <html:text property="name" /></td> </tr> <tr> <td><html:submit /></td> </tr> </table> </html:form> </body> </html> Action: Represents the URL to which this form will be submitted. This attribute is also used to find the appropriate Action Mapping in the Struts configuration file, which we will describe later in this section. The value used in our example is Name, which will map to an Action Mapping with a path attribute equal to Name Name: Identifies the key that the ActionForm will be referenced by. We use the value NameForm. An ActionForm is an object that is used by Struts to represent the form data as a JavaBean. It main purpose is to pass form data between View and Controller components. We will discuss NameForm later in this section.

Type: Names the fully qualified class name of the form bean to use in this request. For this example, we use the value example. NameForm, which is an ActionForm object containing data members matching the inputs of this form. NameForm.java package example; //import statements import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; public class NameForm extends ActionForm { private String name = null; public String getName() { return (name); } public void setName(String name) { this.name = name; } public void reset(ActionMapping mapping, HttpServletRequest request) { this.name = null; } } displayname.jsp <html> <head> <title>Sample Struts Display Name</title> </head> <body> <table width="80%" border="0"> <tr> <td>Hello <%= request.getAttribute("NAME") %> !!</td> </tr> </table> </body> </html> NameAction.java package example; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; public class NameAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

String target = new String("success"); if ( form != null ) { // Use the NameForm to get the request parameters NameForm nameForm = (NameForm)form; String name = nameForm.getName(); }// if no mane supplied Set the target to failure if ( name == null ) { target = new String("failure"); } else { request.setAttribute("NAME", name); } return (mapping.findForward(target)); } } Moving to step three, to deploy the NameAction to our Struts application, weneed to compile the NameAction class and move the class file to /WEB-INF/classes/example directory, and add the following entry to the <action-mappings> section of the /WEB-INF/struts-config.xml file: <action path="/Name" type="example.NameAction" name="nameForm"input="/index.jsp"> <forward name="success" path="/displayname.jsp"/> <forward name="failure" path="/index.jsp"/> </action> For step four we modify the web.xml file. We have to to tell the Web applicationabout our ActionServlet. This is accomplished by adding the following servlet definition to the /WEBINF/ web.xml file: <servlet> <servlet-name>action</servlet-name> <servlet-class> org.apache.struts.action.ActionServlet </servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> Once we have told the container about the ActionServlet, we need to tell it whenthe action should be executed. To do this, we have to add a <servlet-mapping>element to the /WEB-INF/ web.xml file: <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> 6. Write a program in Java to demonstrate the complete life cycle of a Servlet.

Ans: CODE: import database.BookDB; import javax.servlet.*; import util.Counter; public final class ContextListener implements ServletContextListener { private ServletContext context = null; public void contextInitialized(ServletContextEvent event) { context = event.getServletContext(); try { BookDB bookDB = new BookDB(); context.setAttribute("bookDB", bookDB); } catch (Exception ex) { System.out.println( "Couldn't create database: " + ex.getMessage()); } Counter counter = new Counter(); context.setAttribute("hitCounter", counter); context.log("Created hitCounter" + counter.getCounter()); counter = new Counter(); context.setAttribute("orderCounter", counter); context.log("Created orderCounter" + counter.getCounter()); } public void contextDestroyed(ServletContextEvent event) { context = event.getServletContext(); BookDB bookDB = context.getAttribute( "bookDB"); bookDB.remove(); context.removeAttribute("bookDB"); context.removeAttribute("hitCounter"); context.removeAttribute("orderCounter"); } } 7. Explain the life cycle of a Servlet? Ans: Servlet Life Cycle: The life cycle of a servlet is controlled by the container in which the servlet has been deployed. When a request is mapped to a servlet, the container performs the following steps. 1. If an instance of the servlet does not exist, the Web container 2. Loads the servlet class. 3. Creates an instance of the servlet class. 4. Initializes the servlet instance by calling the init method. 5. Invokes the service method, passing a request and response object. If the container needs to remove the servlet, it finalizes the servlet by calling theservlet's destroy method. Handling Servlet Life-Cycle Events

You can monitor and react to events in a servlet's life cycle by defining listener objects whose methods get invoked when life cycle events occur. To use these listener objects, you must define the listener class and specify the listener class. The listeners.ContextListener class creates and removes the database helper and counter objects used in the Duke's Bookstore application. The methods retrieve the Web context object from ServletContextEvent and then store (and remove) the objects as servlet context attributes. CODE: import database.BookDB; import javax.servlet.*; import util.Counter; public final class ContextListener implements ServletContextListener { private ServletContext context = null; public void contextInitialized(ServletContextEvent event) { context = event.getServletContext(); try { BookDB bookDB = new BookDB(); context.setAttribute("bookDB", bookDB); } catch (Exception ex) { System.out.println( "Couldn't create database: " + ex.getMessage()); } Counter counter = new Counter(); context.setAttribute("hitCounter", counter); context.log("Created hitCounter" + counter.getCounter()); counter = new Counter(); context.setAttribute("orderCounter", counter); context.log("Created orderCounter" + counter.getCounter()); } public void contextDestroyed(ServletContextEvent event) { context = event.getServletContext(); BookDB bookDB = context.getAttribute( "bookDB"); bookDB.remove(); context.removeAttribute("bookDB"); context.removeAttribute("hitCounter"); context.removeAttribute("orderCounter"); } } 8. Explain the importance, applications and working of Java Struts. Ans: Struts is an application development framework that is designed for and used with the popular J2EE

(Java 2, Enterprise Edition) platform. It cuts time out of the development process and makes developers more productive by providing them a series of tools and components to build applications with. Struts fall sunder the Jakarta subproject of the Apache Software Foundation and comes with an Open Source license. An example of a Struts Flow server-side script which logs the user on to an application: function login() {userManager = struts.applicationScope["userManager"]; error = ""; while (struts.sessionScope["curUser"] == null) { forwardAndWait("loginForm", {"error" : error}); user = struts.param["user"]; passwd = struts.param["passwd"]; if (userManager.login(user, passwd)) { struts.sessionScope["curUser"] = user; } else { error = "Invalid login, please try again"; } } } Features of Struts are as follows: Easily script complex workflows Full access to Struts features Can exist side-by-side regular Struts actions Ability to run in non-Struts environments (uses Jakarta's Commons-Chain) Enhanced Java API methods and Collections integration Remote RPC support (termed Ajax but with JSON instead of XML) for callingflow methods from the client Includes Wizard library to help easily create complex wizards Includes Javascript Templates library to replace JSP for a 100% Javascriptview layer. Includes number guessing, remote rpc, Javascript Templates, and wizardexamples Struts are a Web Application 'Framework'. Strutsa collection of Java code designed to help you build solid applications while saving time. Struts are based on the time-proven Model-View-Controller (MVC) design pattern. The MVC pattern is widely recognized as being among the most well-developed and mature design patterns in use. By using the MVC design pattern, processing is broken into three distinct sections aptly named the Model, the View, and the Controller. Model Components Model components are generally standard Java classes. View Components

View components are generally built using Java Server Page (JSP) files. Controller Components Controller components in Struts are Java classes and must be built using specificrules. They are usually

referred to as "Action classes."

You might also like