Documente Academic
Documente Profesional
Documente Cultură
1.1.1. Applets
Applets, are Java programs that are developed over the World Wide Web and
executed by a Web browser on the reader’s machine. Applets depend on a Java-capable
browser in order to run.
Creating a Java Applet:
Creating applets is different from creating a simple application, because Java
applet rules for how they behave. Because of these special rules for applets in many cases
(particularly the simple ones), creating an applet may be more complex than creating an
application. For example, to do a simple Hello World applet, instead of merely being able
to print a message, you have to create an applet to make space for your message and then
use graphics operations to paint the message to the screen.
2
In the next example, you create that simple Hello World applet, place it inside a
Web page, and view the result. First, you set up on environment so that your Java-capable
browser can find your HTML files and your applets. Much of the time, you’ll keep your
HTML files and your applet code in the same directory.
Program:
import java.awt.Graphics;
public class HelloWorldApplet extends
java.applet.Applet
{
public void paint(Graphics g)
{
g.drawString(“Hello World!”, 5, 25);
}
}
Save the file just like with Java applications, give your file a name that has the
same name as the class. In this case, the filename would be HelloWorldApplet.java.
Features of Applets:
The import line at the top of the file is somewhat analogous to an #include
statement in C; it enables this applet to get access to the JDk classes for creating
applets and for drawing graphics on the screen.
The paint() method displays the content of the applet onto the screen. Here, the
string Hello World gets drawn. Applets use several standard methods to take the
place of main(), which include init() to initialize the applet, start(0 to start it
running , and paint() to display it to the screen.
Now, compile the applet just as you did the application, using javac, the Java
compiler.
javac HelloWorldApplet.java
Again, just as for application, you should now have a file called
HelloWorldApplet.class in your directory.
To include an applet in a Web page, you refer to that applet in the HTML code for
that Web page. Here, you create a very simple HTML file in the directory.
<HTML>
<HEAD>
<TITLE>
Hello to Everyone!
</TITLE>
</HEAD>
<BODY>
<P> My Java applet says:
<APPLET CODE=“HelloWorldApplet.class” WIDTH = 150 HEIGHT = 25>
</APPLET>
</BODY>
</HTML>
3
class HelloWorld
{
public static void main(String args[])
{
System.out.println(“Hello World!”);
}
}
Once you finish typing the program, save the file. Most of the time, Java source
files are named the same name as the class they define, with an extension of .java. This
file should therefore be called HelloWorld.java. now, let’s compile the source file using
the Java compiler. In sun’s JDK, the Java compiler is called javac. To compile your Java
program, make sure the javac program is in your execution path and type javac followed
by the name of your source file: javac HelloWorld.java.
The compiler should compile the file without any errors. If you get errors, go back
and make sure that you’ve typed the program exactly. When the program compiles
without errors, you end up with a file called HelloWorld.class, in the same directory as
your source file. This is your Java bytecode file. You can then run that bytecode file
using the Java interpreter. This is you rJava interpretor is called simply java. Make sure
the kjava program is in your path and type java followed by the name of ht efile without
the .class extension: java HelloWorld
If your program was typed and compiled correctly, you should get the string
“Hello World!” printed to your screen as a response.
4
The AWT was designed from the start to have a platform-independent API and
yet to preserve each platform's look and feel. For example, the AWT has just one API for
buttons (provided by the Button class), but a button looks different on a Macintosh than
on a PC running Windows 95.
AWT Components
Component are java’s building blocks for creating graphical user interface. Some
component types, such as buttons and scroll bars, are used directly for GUI control. Other
components provide spatial organization. GUI are an important part of any program.
Java’s Abstract Windowing Toolkit provides extensive functionality.
1. Buttons.
2. Checkboxes
3. Choices
4. Labels
5. Panels
6. Scrollbars
7. Textarea And Textfield
Let us now look at some of the basic components in detail and also learn how to use
them.
1.2.1. Buttons
A Button is a simple control that generates an action event when the user clicks it.
The onscreen appearance of Buttons depends on the platform they're running on and on
whether the Button is enabled. If you want your program's Buttons to look the same for
every platform or to otherwise have a special look, you should create a Canvas subclass
to implement this look; you can't change the look using a Button subclass. The only
facets of a Button's appearance that you can change without creating your own class are
the font and text it displays, its foreground and background colors, and (by enabling or
disabling the button) whether the Button looks enabled or disabled.
Example of buttons
The following figure shows a few Buttons used with FlowLayout( explained later)
7
public ButtonDemo()
{
setLayout(new FlowLayout());
add(b1);
add(b2);
add(b3);
}
The above code sample shows how to use all but one of the commonly used
Button methods. In addition, Button defines a getLabel() method, which lets you find
out what text is displayed on a particular Button.
8
1.2.2. Checkboxes
When the user clicks a checkbox, the Checkbox State changes and it generates an
action event. Other ways of providing groups of items the user can select are choices,
lists, and menus.
If you want a group of checkboxes in which only one checkbox at a time can be
"on", you can add a CheckboxGroup object to oversee the state of the checkboxes.
(You call this element as a radio button.)
Below is an example that has two columns of checkboxes. On the left are three
independent checkboxes. You can select all three of the checkboxes, if you like. On
the right are three checkboxes that are coordinated by a CheckboxGroup object. The
CheckboxGroup ensures that no more than one of its checkboxes is selected at a time.
To be specific, a checkbox group can come up with no checkboxes selected, but once
the user selects a checkbox, exactly one of the checkboxes will be selected forever
after.
Following is the code that creates both groups of checkboxes. Note that only the
second, mutually exclusive group of checkboxes is controlled by a CheckboxGroup.
import java.awt.*;
add(cb1);add(cb4);
add(cb2);add(cb5);
add(cb3);add(cb6);
9
Besides the Checkbox methods shown above, Checkbox has two additional
methods you might want to use: getCheckboxGroup() and setCheckboxGroup().
Besides the single CheckboxGroup constructor used in the code example,
CheckboxGroup also defines the following methods: getCurrent() and
setCurrent(). These methods get and set (respectively) the current selected
Checkbox.
Note: CheckboxGroup is only a helper class, it is not a component by itself. Its basic
use is to generate RadioButtons.
1.2.3. Choices
10
import java.awt.*;
public ChoiceDemo()
{
setTitle("This shows use of Choice component");
setSize(200,100);
setLayout(new FlowLayout());
ch.addItem("India");
ch.addItem("Pakistan");
ch.addItem("Bangladesh");
ch.addItem("Nepal");
ch.addItem("Bhutan");
add(ch);
Besides the methods used above, the Choice class defines these other useful
methods:
int countItems()
Returns the number of items in the choice.
String getItem(int)
Returns the String displayed by the item at the specified index.
void select(int)
Selects the item at the specified index.
void select(String)
Selects the item that's displaying the specified String.
1.2.4. Labels
The Label class provides an easy way of putting unselectable text in your program's
GUI. Labels are aligned to the left of their drawing area, by default. You can specify that
they be centered or right-aligned by specifying Label.CENTER or Label.RIGHT either to
the Label constructor or to the setAlignment() method. As with every Component,
you can also specify the font and color of a Label.
Label Example
There are three labels, each one with a different alignment. If each label's display
area were equal to the width of the text the label displayed, you wouldn't see any
difference in the alignment of the labels. Each label's text would simply be displayed
using all the available space.
12
Below is the code that the program uses to create the labels and set their alignment.
import java.awt.*;
import java.awt.event.*;
public LabelDemo()
{
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent we)
{
dispose();
System.exit(0);
}
});
l1.setAlignment(l1.LEFT);
l2.setAlignment(l2.CENTER);
l3.setAlignment(l3.RIGHT);
add(l1);
add(l2);
add(l3);
}
13
1.2.5. Panels
The Panel class is a general-purpose Container subclass. You can use it as-is to
hold Components, or you can define a subclass to perform special functionality, such as
event handling for the objects the Panel contains.
The Applet class is a Panel subclass with special hooks to run in a browser or other applet
viewer. Whenever you see a program that can run both as an applet and as an application,
chances are that it defines an Applet subclass but doesn't use any of the special Applet
capabilities, relying instead on the methods it inherits from the Panel class.
Here's an example of a Panel subclass that draws a frame around its contents..
14
g.setColor(bg);
g.draw3DRect(0, 0, d.width - 1, d.height - 1, true);
g.draw3DRect(3, 3, d.width - 7, d.height - 7, false);
}
1.2.6. Scrollbars
As shown above, a scrollbar can act as a slider that the user manipulates to set a
value.
As controls for scroll panes. The ScrollPane class, which was introduced in
1.1, lets you display part of a component that's too large for the available display
area. Scrollbars in scroll panes let the user choose exactly which part of the region
is visible. To customize scrolling behavior, you sometimes need to invoke
methods on a ScrollPane's scrollbars.
Scrollbar Properties.
int orientation
The initial value of the scrollbar. For scrollbars that control a scrollable area, this
usually means the x value (for horizontal scrollbars) or y value (for vertical scrollbars) of
the part of the area that's visible when the user first sees the scrollable area. For example,
when the applet above starts up, both the horizontal and vertical scrollbars' values are 0,
and the image portion that's displayed starts at (0,0).
int visible
The size in pixels of the visible portion of the scrollable area. This value, if set
before the scrollbar is visible, determines how many pixels a click in the scrollbar (but
not on the knob) causes the display area to shift. Setting this value after the scrollbar is
visible has no effect. After the scrollbar is visible, you should use the
setPageIncrement() method to get the same effect.
int minimum
The minimum value the scrollbar can have. For scrollbars controlling scrollable
areas, this value is usually 0 (the left/upper part of the area).
int maximum
The maximum value the scrollbar can have. For scrollbars controlling scrollable
areas, this value is usually: (total width/height, in pixels, of the component that's being
partially displayed) - (currently visible width/height of the scrollable area).
The TextArea and TextField classes display selectable text and, optionally, allow
the user to edit the text. You can subclass TextArea and TextField to perform such tasks
as checking for errors in the input. As with any Component, you can specify the
background and foreground colors and font used by TextAreas and TextFields. You can't,
however, change their basic appearance.
Both TextArea and TextField are subclasses of TextComponent. From
TextComponent they inherit methods that allow them to set and get the current selection,
enable and disable editing, get the currently selected text (or all the text), and set the text.
16
Here's the program. Here's just its code that creates, initializes, and handles events
in the TextArea and TextField:
int getColumns()
17
setEchoChar()
Sets the echo character, which is useful for password fields.
In the above lesson we discussed about the two different types of Java programs
(Applets and Applications). AWT components such as Buttons, Checkboxes, Choices,
Labels, Panels, Scrollbars, Textarea And Textfield were discussed with examples.
Write an application interface that asks for a user name and a password. The interface
should have two text fields and two buttons.
Write an interface to a calculator application. (hint: you may have to use GridLayout)
Write an application that diaplays an image.
Write a small note pad application. The application should be able to open and save a
file (ASCII).
18
1.6. REFERENCES
Campione, Walrath and Huml, “The Java Tutorial”, Addison Wesley 1999
Cays, Horstmann & Gary Gornell, “core Java 2 Vol-1 Fundamentals”, Pearson Education
Asia, 2001
19
2.1. INTRODUCTION
Events are signals which are fired when the state of a component is changed (eg:
when a button is pressed, when a menu is pressed etc.). In the event of a signal firing it is
necessary for us to handle the event based on our requirements. For example you would
want to open a new window or close it when a button is pressed, or you would want to
list a menu when a menu box is activated (pressed).
Sources:
The previous paragraph only gives you a gist of what happens when a
component is activated. Actually when the internal state of the component is modified a
source is generated. This is nothing but a source to the event.
Listeners:
A single component can take events from different sources. For Example an
applet can have sources from the keyboard or from the mouse. So you should make the
applet be ready to receive the events from the different sources. This is done by the
Listeners which are nothing but interfaces with abstract methods which could be
implemented on generation of the corresponding event.
20
Event Handling:
The actions that have to be performed on the component listening to an event like
a mouse clicked on an applet are specified. This is called Event Handling .
Once you know which events a particular component supports, you don’t need to
look anything up to react to that event. You simply:
Take the name of the event class and remove the word “ Event.” Add the word “
Listener” to what remains. This is the listener interface you need to implement in your
inner class.
Implement the interface above and write out the methods for the events you want
to capture. For example, you might be looking for mouse movements, so you write code
for the mouseMoved( ) method of the MouseMotionListener interface. (You must
implement the other methods, of course, but there’s a shortcut for that which you’ll see
soon.)
Create an object of the listener class in step 2. Register it with your component
with the method produced by prefixing “ add” to your listener name. For example,
addMouseMotionListener( ).
To finish what you need to know, here are the listener interfaces:
windowDeactivated(WindowEvent)
windowIconified(WindowEvent)
windowDeiconified(WindowEvent)
ItemListener itemStateChanged(ItemEvent)
TextListener textValueChanged(TextEvent)
//: Button2New.java
// Capturing button presses
import java.awt.*;
import java.awt.event.*; // Must add this
import java.applet.*;
In the previous table, you can see that some listener interfaces have only one
method. These are trivial to implement since you’ll implement them only when you want
to write that particular method. However, the listener interfaces that have multiple
methods could be less pleasant to use. For example, something you must always do when
creating an application is provide a WindowListener to the Frame so that when you get
the windowClosing( ) event you can call System.exit(0) to exit the application. But since
WindowListener is an interface, you must implement all of the other methods even if
they don’t do anything. This can be annoying.
To solve the problem, each of the listener interfaces that have more than one
method are provided with adapters, the names of which you can see in the table above.
Each adapter provides default methods for each of the interface methods. (Alas,
WindowAdapter does not have a default windowClosing( ) that calls System.exit(0).)
Then all you need to do is inherit from the adapter and override only the methods you
need to change. For example, the typical WindowListener you’ll use looks like this:
The whole point of the adapters is to make the creation of listener classes easy.
{
public void WindowClosing(WindowEvent e)
{
System.exit(0);
}
}
This doesn’t work, but it will drive you crazy trying to figure out why, since
everything will compile and run fine – except that closing the window won’t exit the
program. Can you see the problem? It’s in the name of the method: WindowClosing( )
instead of windowClosing( ). A simple slip in capitalization results in the addition of a
completely new method. However, this is not the method that’s called when the window
is closing, so you don’t get the desired results.
Often you’ll want to be able to create a class that can be invoked as either a
window or an applet. To accomplish this, you simply add a main( ) to your applet that
builds an instance of the applet inside a Frame. As a simple example, let’s look at
Button2New.java modified to work as both an application and an applet:
//: Button2NewB.java
// An application and an applet
import java.awt.*;
import java.awt.event.*; // Must add this
import java.applet.*;
The inner class WL and the main( ) are the only two elements added to the applet,
and the rest of the applet is untouched. In fact, you can usually copy and paste the WL
class and main( ) into your own applets with little modification. The WL class is static so
26
it can be easily created in main( ). (Remember that an inner class normally needs an outer
class handle when it’s created. Making it static eliminates this need.) You can see that in
main( ), the applet is explicitly initialized and started since in this case the browser isn’t
available to do it for you. Of course, this doesn’t provide the full behavior of the browser,
which also calls stop( ) and destroy( ), but for most situations it’s acceptable. If it’s a
problem, you can:
Make the handle applet a static member of the class (instead of a local variable of
main( )), and then:
Call applet.stop( ) and applet.destroy( ) inside WindowAdapter.windowClosing( )
before you call System.exit( ).
aFrame.addWindowListener(new WL());
will become:
aFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
This has the advantage that it doesn’t require yet another class name. You must
decide for yourself whether it makes the code easier to understand or more difficult.
However, for the remainder of the book an anonymous inner class will usually be used
for the window listener.
Text fields
This is similar to TextField1.java, but it adds significant extra behavior:
//: TextNew.java
// Text fields with Java 1.1 events
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
t1 = new TextField(30),
t2 = new TextField(30),
t3 = new TextField(30);
String s = new String();
public void init() {
b1.addActionListener(new B1());
b2.addActionListener(new B2());
t1.addTextListener(new T1());
t1.addActionListener(new T1A());
t1.addKeyListener(new T1K());
add(b1);
add(b2);
add(t1);
add(t2);
add(t3);
}
class T1 implements TextListener {
public void textValueChanged(TextEvent e) {
t2.setText(t1.getText());
}
}
class T1A implements ActionListener {
private int count = 0;
public void actionPerformed(ActionEvent e) {
t3.setText("t1 Action Event " + count++);
}
}
class T1K extends KeyAdapter {
public void keyTyped(KeyEvent e) {
String ts = t1.getText();
if(e.getKeyChar() ==KeyEvent.VK_BACK_SPACE) {
// Ensure it's not empty:
if( ts.length() > 0) {
ts = ts.substring(0, ts.length() - 1);
t1.setText(ts);
}
}
else
t1.setText(t1.getText()
+Character.toUpperCase(e.getKeyChar()));
t1.setCaretPosition(t1.getText().length());
// Stop regular character from appearing:
e.consume();
}
}
class B1 implements ActionListener {
public void actionPerformed(ActionEvent e) {
s = t1.getSelectedText();
if(s.length() == 0) s = t1.getText();
t1.setEditable(true);
}
}
class B2 implements ActionListener {
public void actionPerformed(ActionEvent e) {
28
The TextField t3 is included as a place to report when the action listener for the
TextField t1 is fired. You’ll see that the action listener for a TextField is fired only when
you press the “enter” key.
The TextField t1 has several listeners attached to it. The T1 listener copies all text
from t1 into t2 and the T1K listener forces all characters to upper case. You’ll notice that
the two work together, and if you add the T1K listener after you add the T1 listener, it
29
doesn’t matter: all characters will still be forced to upper case in both text fields. It would
seem that keyboard events are always fired before TextComponent events, and if you
want the characters in t2 to retain the original case that was typed in, you must do some
extra work.
T1K has some other activities of interest. You must detect a backspace (since
you’re controlling everything now) and perform the deletion. The caret must be explicitly
set to the end of the field; otherwise it won’t behave as you expect. Finally, to prevent the
original character from being handled by the default mechanism, the event must be
“consumed” using the consume( ) method that exists for event objects. This tells the
system to stop firing the rest of the event handlers for this particular event.
This example also quietly demonstrates one of the benefits of the design of inner
classes. Note that in the inner class:
TextAreas
The most significant change to text areas in Java 1.1 concerns scroll bars. With
the TextArea constructor, you can now control whether a TextArea will have scroll bars:
vertical, horizontal, both, or neither. This example show the Java scrollbar constructors:
//: TextAreaNew.java
// Controlling scrollbars with the TextArea
// component in Java 1.1
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
TextArea.SCROLLBARS_VERTICAL_ONLY);
TextArea t5 = new TextArea("t5", 4, 30,
TextArea.SCROLLBARS_HORIZONTAL_ONLY);
TextArea t6 = new TextArea("t6", 10, 10,
TextArea.SCROLLBARS_BOTH);
public void init() {
b1.addActionListener(new B1L());
add(b1);
add(t1);
b2.addActionListener(new B2L());
add(b2);
add(t2);
b3.addActionListener(new B3L());
add(b3);
b4.addActionListener(new B4L());
add(b4);
add(t3);
add(t4);
add(t5);
add(t6);
}
class B1L implements ActionListener {
public void actionPerformed(ActionEvent e) {
t5.append(t1.getText() + "\n");
}
}
class B2L implements ActionListener {
public void actionPerformed(ActionEvent e) {
t2.setText("Inserted by Button 2");
t2.append(": " + t1.getText());
t5.append(t2.getText() + "\n");
}
}
class B3L implements ActionListener {
public void actionPerformed(ActionEvent e) {
String s = " Replacement ";
t2.replaceRange(s, 3, 3 + s.length());
}
}
class B4L implements ActionListener {
public void actionPerformed(ActionEvent e) {
t2.insert(" Inserted ", 10);
}
}
public static void main(String[] args) {
TextAreaNew applet = new TextAreaNew();
Frame aFrame = new Frame("TextAreaNew");
aFrame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
aFrame.add(applet, BorderLayout.CENTER);
aFrame.setSize(300,725);
applet.init();
31
applet.start();
aFrame.setVisible(true);
}
} ///:~
The output would be something like
You’ll notice that you can control the scrollbars only at the time of construction of
the TextArea. Also, even if a TextArea doesn’t have a scrollbar, you can move the cursor
such that scrolling will be forced. (You can see this behavior by playing with the
example.)
When dealing with a group of check boxes or radio buttons, you have a choice.
You can either create a new inner class to handle the event for each different Checkbox
or you can create one inner class that determines which Checkbox was clicked and
register a single object of that inner class with each Checkbox object. The following
example shows both approaches:
32
//: RadioCheckNew.java
// Radio buttons and Check Boxes in Java 1.1
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
}
}
public static void main(String[] args) {
RadioCheckNew applet = new RadioCheckNew();
Frame aFrame = new Frame("RadioCheckNew");
aFrame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
aFrame.add(applet, BorderLayout.CENTER);
aFrame.setSize(300,200);
applet.init();
applet.start();
aFrame.setVisible(true);
}
} ///:~
The output would look like:
ILCheck has the advantage that it automatically adapts when you add or subtract
Checkboxes. Of course, you can use this with radio buttons as well. It should be used,
however, only when your logic is general enough to support this approach. Otherwise
you’ll end up with a cascaded if statement, a sure sign that you should revert to using
independent listener classes.
Drop-down lists (Choice) since Java 1.1 also use ItemListeners to notify you
when a choice has changed:
//: ChoiceNew.java
// Drop-down lists with Java
import java.awt.*;
34
import java.awt.event.*;
import java.applet.*;
aFrame.setVisible(true); }} ///:~
Nothing else here is particularly new (except that Java 1.1 has significantly fewer bugs in
the UI classes).
2.5. LISTS
You’ll recall that one of the problems with the Java 1.0 List design is that it took
extra work to make it do what you’d expect: react to a single click on one of the list
elements. Java 1.1 has solved this problem:
//: ListNew.java
// Java 1.1 Lists are easier to use
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
}
class LL implements ItemListener {
public void itemStateChanged(ItemEvent e) {
t.setText("");
String[] items = lst.getSelectedItems();
for(int i = 0; i < items.length; i++)
t.append(items[i] + "\n");
}
}
class BL implements ActionListener {
public void actionPerformed(ActionEvent e) {
if(count < flavors.length)
lst.addItem(flavors[count++], 0);
}
}
public static void main(String[] args) {
ListNew applet = new ListNew();
Frame aFrame = new Frame("ListNew");
aFrame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
aFrame.add(applet, BorderLayout.CENTER);
aFrame.setSize(300,200);
applet.init();
applet.start();
aFrame.setVisible(true);
}
} ///:~
You can see that no extra logic is required to support a single click on a list item. You
just attach a listener like you do everywhere else.
2.6. MENUS
The event handling for menus does seem to benefit from the Java 1.1 event
model, but Java’s approach to menus is still messy and requires a lot of hand coding. The
right medium for a menu seems to be a resource rather than a lot of code. Keep in mind
that program-building tools will generally handle the creation of menus for you, so that
will reduce the pain somewhat (as long as they will also handle the maintenance!).
In addition, you’ll find the events for menus are inconsistent and can lead to
confusion: MenuItems use ActionListeners, but CheckboxMenuItems use ItemListeners.
The Menu objects can also support ActionListeners, but that’s not usually helpful. In
general, you’ll attach listeners to each MenuItem or CheckboxMenuItem, but the
following example (revised from the earlier version) also shows ways to combine the
capture of multiple menu components into a single listener class. As you’ll see, it’s
probably not worth the hassle to do this.
//: MenuNew.java
import java.awt.*;
import java.awt.event.*;
new MenuItem("Bar"),
new MenuItem("Baz"),
};
// Initialization code:
{
ML ml = new ML();
CMIL cmil = new CMIL();
safety[0].setActionCommand("Guard");
safety[0].addItemListener(cmil);
safety[1].setActionCommand("Hide");
safety[1].addItemListener(cmil);
file[0].setActionCommand("Open");
file[0].addActionListener(ml);
file[1].setActionCommand("Exit");
file[1].addActionListener(ml);
other[0].addActionListener(new FooL());
other[1].addActionListener(new BarL());
other[2].addActionListener(new BazL());
}
Button b = new Button("Swap Menus");
public MenuNew() {
FL fl = new FL();
for(int i = 0; i < flavors.length; i++) {
MenuItem mi = new MenuItem(flavors[i]);
mi.addActionListener(fl);
m.add(mi);
// Add separators at intervals:
if((i+1) % 3 == 0)
m.addSeparator();
}
for(int i = 0; i < safety.length; i++)
s.add(safety[i]);
f.add(s);
for(int i = 0; i < file.length; i++)
f.add(file[i]);
mb1.add(f);
mb1.add(m);
setMenuBar(mb1);
t.setEditable(false);
add(t, BorderLayout.CENTER);
// Set up the system for swapping menus:
b.addActionListener(new BL());
add(b, BorderLayout.NORTH);
for(int i = 0; i < other.length; i++)
fooBar.add(other[i]);
mb2.add(fooBar);
}
class BL implements ActionListener {
public void actionPerformed(ActionEvent e) {
MenuBar m = getMenuBar();
if(m == mb1) setMenuBar(mb2);
else if (m == mb2) setMenuBar(mb1);
}
}
class ML implements ActionListener {
public void actionPerformed(ActionEvent e) {
39
}
}
public static void main(String[] args) {
MenuNew f = new MenuNew();
f.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.setSize(300,200);
f.setVisible(true);
}
} ///:~
This code is similar to the Java 1.0 version, until you get to the initialization
section (marked by the opening brace right after the comment “Initialization code:”).
Here you can see the ItemListeners and ActionListeners attached to the various menu
components.
Java 1.1 and later versions support “menu shortcuts,” so you can select a menu
item using the keyboard instead of the mouse. These are quite simple; you just use the
overloaded MenuItem constructor that takes as a second argument a MenuShortcut
object. The constructor for MenuShortcut takes the key of interest, which magically
appears on the menu item when it drops down. The example above adds Control-E to the
“Exit” menu item.
You can also see the use of setActionCommand( ). This seems a bit strange
because in each case the “action command” is exactly the same as the label on the menu
component. Why not just use the label instead of this alternative string? The problem is
internationalization. If you retarget this program to another language, you want to change
only the label in the menu, and not go through the code changing all the logic that will no
doubt introduce new errors. So to make this easy for code that checks the text string
41
associated with a menu component, the “action command” can be immutable while the
menu label can change. All the code works with the “action command,” so it’s unaffected
by changes to the menu labels. Note that in this program, not all the menu components
are examined for their action commands, so those that aren’t don’t have their action
command set.
Much of the constructor is the same as before, with the exception of a couple of calls to add listeners. The bulk of the work
happens in the listeners. In BL, the MenuBar swapping happens as in the previous example. In ML, the “figure out who rang”
approach is taken by getting the source of the ActionEvent and casting it to a MenuItem, then getting the action command string
to pass it through a cascaded if statement. Much of this is the same as before, but notice that if “Exit” is chosen, a new
WindowEvent is created, passing in the handle of the enclosing class object ( MenuNew.this) and creating a
WINDOW_CLOSING event. This is handed to the dispatchEvent( ) method of the enclosing class object, which then ends up
calling windowClosing( ) inside the window listener for the Frame (this listener is created as an anonymous inner class, inside
main( )), just as if the message had been generated the “normal” way. Through this mechanism, you can dispatch any message
you want in any circumstances, so it’s quite powerful.
The FL listener is simple even though it’s handling all the different flavors in the
flavor menu. This approach is useful if you have enough simplicity in your logic, but in
general, you’ll want to take the approach used with FooL, BarL, and BazL, in which they
are each attached to only a single menu component so no extra detection logic is
necessary and you know exactly who called the listener. Even with the profusion of
classes generated this way, the code inside tends to be smaller and the process is more
foolproof.
//: ToeTestNew.java
// Demonstration of dialog boxes
// and creating your own components
import java.awt.*;
import java.awt.event.*;
else
state = (state == XX ? OO : XX);
repaint();
}
}
}
}
class BL implements ActionListener {
public void actionPerformed(ActionEvent e) {
Dialog d = new ToeDialog(
Integer.parseInt(rows.getText()),
Integer.parseInt(cols.getText()));
d.show();
}
}
public static void main(String[] args) {
Frame f = new ToeTestNew();
f.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.setSize(200,100);
f.setVisible(true);
}
} ///:~
Because statics can be at only the outer level of the class, inner classes cannot
have static data or static inner classes.
//: FileDialogNew.java
// Demonstration of File dialog boxes
import java.awt.*;
import java.awt.event.*;
d.setDirectory(".");
d.show();
String saveFile;
if((saveFile = d.getFile()) != null) {
filename.setText(saveFile);
directory.setText(d.getDirectory());
}
else {
filename.setText("You pressed cancel");
directory.setText("");
}
}
}
public static void main(String[] args) {
Frame f = new FileDialogNew();
f.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.setSize(250,110);
f.setVisible(true);
}
} ///:~
It would be nice if all the conversions were this easy, but they’re usually easy enough, and your code benefits from the improved
readability.
1. Create a paint brush like application. Buttons need not have icons
2. Create a text field, get input from the user and check whether it’s a prime number.
Without using buttons.
3. Create three text fields and a button, concatenate the text from the two fields and put
it into the third text field.
4. Create a list and a choice which listens to item listener. Such that when the user
selects an item from the list it should get added in the choice
5. Redo the above program but this time an item should be added to the list when the
user selects an item from the choice
2.12. REFERENCES
Campione, Walrath and Huml, “The Java Tutorial”, Addison Wesley 1999
Ken Arnold, James Gosling, David Holmes, “The Java Programming Language”, 3ed,
Addision Wesley, 2000.
48
3.1. INTRODUCTION
Most computer games use graphics and sound. Have you noticed that the
graphics, the score and the music run simultaneously. Imagine a situation where you see
the screen changing first, your score getting updated next, and then finally you hear the
sound. A single game has all these elements being processed at the same time. In other
words, the program has been divided into three sub-units, each unit being handled by a
thread.
Threads are very useful when you have large computations that take several
seconds to complete and you don’t want the user to perceive the delay. Animation is also
an area where threads are used.
There is nothing new in the concept of a single thread. The real hoopla
surrounding threads is not about a single sequential thread. Rather, it's about the use of
multiple threads in a single program, running at the same time and performing different
tasks.
Some texts use the name lightweight process instead of thread. A thread is similar
to a real process in that a thread and a running program are both a single sequential flow
of control. However, a thread is considered lightweight because it runs within the context
of a full-blown program and takes advantage of the resources allocated for that program
and the program's environment.
As a sequential flow of control, a thread must carve out some of its own resources
within a running program. (It must have its own execution stack and program counter for
example.) The code running within the thread works only within that context. Thus, some
other texts use execution context as a synonym for thread.
A process having more than one thread is called multithreaded. Multiple threads in a
process run at the same time, perform different tasks, and interact with one another.
50
When an instance of the Thread class is created, the thread enters the new thread
state. The following code segment illustrates the instantiation of the Thread class
// this keyword signifies that the run() method needs to be invoked from the
// current object
Thread newThread = new Thread(this)
The above code creates a new thread and, as of now, no resources are allocated for it. It is
an empty object. You have to invoke the start() method to start the thread.
newThread.start() ;
51
When the start() method of a thread is invoked, the thread enters the runnable
state. Since a single processor cannot execute more than one thread at a time, the
processor maintains a thread queue. Once started, a thread is queued up for the processor
and waits for its turn to be executed. Therefore at any given point of time, a thread maybe
waiting for the attention of the processor. This is why the state of the thread is said to be
runnable and not running.
A thread is put in the sleeping mode with the sleep() method. A sleeping thread
enters the runnable state after the specified time of sleep has elapsed. Until the specified
time has elapsed the thread will not execute.
A thread can be made to wait on a conditional variable until a condition is
satisfied. A thread can be notified of the condition by invoking the notify() method of the
Thread Class.When the thread is blocked by an input-output operation, it enters the not
runnable state although it might otherwise qualify as runnable.
A thread can either die or be naturally killed. A thread dies a natural death when
the loop in the run() method is complete. For example if the loop in the run() method has
a hundred iterations, the life of the thread is a hundred iterations of the loop. Assigning
null to a thread object kills a thread. The isAlive() method of the Thread class is used to
determine whether the thread has been started.
Single Thread
Every program has at least one thread. This thread can be accessed using the
currentThread() method of the Thread class. This method is a static method and hence
you do not have to create an object of the Thread class to invoke the method. The code
below uses the currentThread method.
{
System.out.println(i);
Thread.sleep(1000);
}
}
catch (InterruptedException e)
{
System.out.println(“I was interrupted”);
}
}
}
The output is
0
2
3
6
8
In the application above, the current thread is obtained using the currentThread()
method. Everytime the thread prints the value of i , the thread is put to sleep for 1000
milliseconds. The thread might throw an exception if another thread interrupts the
sleeping one. Therefore the sleep() method is guarded by the try block
Multiple threads are created in a program using any of the two methods below:
Subclassing the Thread class
Using the Runnable interface
53
The first way to customize what a thread does when it is running is to subclass
Thread (itself a Runnable object) and override its empty run method so that it does
something. Let's look at the SimpleThread class, the first of two classes in this
example, which does just that:
The next method in the SimpleThread class is the run() method. The run()
method is the heart of any Thread and where the action of the Thread takes place. The
run() method of the SimpleThread class contains a for loop that iterates ten times. In
each iteration the method displays the iteration number and the name of the Thread, then
sleeps for a random interval of up to 1 second. After the loop has finished, the run
method prints DONE! along with the name of the thread. That's it for the SimpleThread
class.
54
0 Ooty
0 Kodai
1 Kodai
1 Ooty
2 Ooty
2 Kodai
3 Kodai
3 Ooty
4 Ooty
4 Kodai
5 Ooty
5 Kodai
6 Kodai
6 Ooty
7 Ooty
7 Kodai
8 Kodai
9 Kodai
8 Ooty
DONE! Kodai
9 Ooty
DONE! Ooty
(Looks like we are going to Kodai!!) Notice how the output from each thread is
intermingled with the output from the other. This is because both SimpleThread threads
are running concurrently. Thus, both run methods are running at the same time and each
thread is displaying its output at the same time as the other.
Applets extend from the Applet class. Since Java doesn’t support multiple
inheritance, a class cannot be inherited from the Applet class as well as the Thread class.
55
Java provides the Runnable interface to solve this problem. The Runnable interface
consists of a single method, run(), which is executed when the thread is activated. Hence
we can extend from the Applet class, implement the Runnable interface and code the
run() method. With applications, you have a choice of extending from the Thread class.
In other words, when a program needs to inherit from a class apart from the Thread class,
you need to implement the Runnable interface.
Example:
public class ClockThread extends Applet implements Runnable
{
-----------------
}
NOTE: When the Runnable interface is used, the thread becomes a part of the
Applet class and hence can grant full access to the data members and methods. A subclass
of the Thread class is limited to only the public components of the class. Therefore, when
the thread depends strongly on the components of the Applet class, use the Runnable
interface.
The start() method of the Thread class is responsible for starting the thread. It
allocates the system resources that are necessary for the thread, schedules the thread to
run, and calls the run() method of the thread.
Example:
Once started, the thread enters the runnable state. All the activities of a thread
take place in the body of the thread, which is defined by the run() method. After a thread
is created and initialized, the run() method is called. The run() method usually contains a
loop.
{
while (ClockThread != null)
{
------------
}
}
The thread is put into a sleeping mode with the sleep() method. When the thread is
sleeping, other threads in the queue are executed.
Syntax
static void sleep(long no_of_milliseconds);
Example:
The above code continuously updates the time on the screen. This is achieved by
using a thread. The method repaints the screen after every 100 milliseconds. The paint()
57
Stopping a Thread
A thread dies a natural death when the loop in the run() method is complete. A thread can
be killed using the stop() method.
The stop() method of the applet releases the memory allocated to the thread, and thereby
stops it when page on which the applet runs is left. This method sets clockThread to null
and causes the loop in the run() method to terminate. If the page is revisited, the start()
method is called again and a new thread is started.
g.drawString(dateFormatter.format(date), 5, 10);
}
Consider this analogy: A family of four members is served a bowl of soup but only one
spoon. All the four are very hungry. They have now two options.
Option1: The first member of the family uses the spoon to have his soup first, passes it
onto the second member and so on. The last member waits for everyone else to finish,
and by then his soup is cold and very little of it is left.
Option2: Each member has one spoonful of soup each and passes the spoon around to
the next member. This will ensure that every member gets an equal share and nobody is
kept waiting.
59
Which option would you prefer if you were the last member?
When two threads need to share data, it must be ensured that one thread doesnot
change the data used by the other thread. Java enables you to co-ordinate the actions of
multiple threads using synchronized methods or synchronized statements.
Synchronizing Threads
All objects and classes are associated with a monitor. The monitor controls
the way in which synchronized methods access an object or class. It ensures that
only one thread has access to the resource at any given point of time. A
synchronized method acquires the monitor of an object when it is invoked for that
object. During the execution of a synchronized method, the object is locked so that
no other synchronized method can be invoked. The monitor is automatically
released as soon as the method completes its execution. The monitor may also be
released when the synchronized method executes certain methods like the wait()
method. The thread associated with the synchronized method becomes not runnable
until the wait condition is satisfied. When the wait condition is satisfied, the thread
has to acquire the monitor of the object to become runnable.
The following code shows how synchronized methods and object monitors are
used to co-ordinate access to a common object by multiple threads.
{
super(id);
}
Sync.displayList(getName(), message);
}
void waiting()
{
try
{
sleep(1000);
}
catch (InterruptedException e)
{
System.out.println(“I was interrupted”); //
Sleep interrupted
}
}
}
class Sync
{
public static synchronized void displayList(String name,
String list[])
{
int i;
for ( i = 0; i < list.length; i++)
{
MyThread thread =
(MyThread)Thread.currentThread();
thread.waiting();
System.out.println(name + list[i]);
}
}
}
class ThreadSync
{
public static void main (String args[])
{
MyThread threadA = new MyThread(“Thread A: “);
MyThread threadB = new MyThread(“Thread B: “);
threadA.start(); //starts first thread
threadB.start(); //starts second thread
}
}
Output
Thread A: I
Thread A: love
Thread A: Object
Thread A: Oriented
Thread A: Programs
Thread A: in
Thread A: java.
Thread B: I
Thread B: love
Thread B: Object
Thread B: Oriented
61
Thread B: Programs
Thread B: in
Thread B: java.
For example, imagine a Java application where one thread (the producer) writes
data to a file while a second thread (the consumer) reads data from the same file. Or, as
you type characters on the keyboard, the producer thread places key events in an event
queue and the consumer thread reads the events from the same queue. Both of these
examples use concurrent threads that share a common resource: the first shares a file, the
second shares an event queue. Because the threads share a common resource, they must
be synchronized in some way.
What is the producer could communicate to the consumer once it has finished
producing the required data? The consumer would then not use up CPU cycles just to
check whether the producer has done its job. This communication between threads is
called inter-thread communication. Inter-thread communication is achieved using four
methods, wait(), notify(), notifyAll(), and yield(). All these methods are declared final in
the Object class. They can only be called from synchronized methods.
The wait() method tells the current thread to give up the monitor and sleep until
another thread calls to notify() method. Wait() method can also be used to synchronize
threads.
Syntax
public final void wait() throws InterruptedException;
The wait() method makes the current thread wait until another thread invokes the
notify() or notifyAll() method of the current object. It is necessary for the current thread to
own the monitor of the object.
The notify() method wakes up a single thread that is waiting for the current
monitor of the object. If multiple threads are waiting, one of them is chosen arbitrarily.
62
The awakened thread is not able to proceed until the current thread releases the lock from
the monitor. A thread that is the owner of the monitor of the object should call this
method.
A thread becomes the owner of the monitor of an object in one of the three ways
Only one thread can own the monitor of an object at any time.
Syntax
public final void notify();
The method notifyAll() is used to wake up all the threads that are waiting for the monitor
of the object. To call notify() or notifyAll() method, the thread must own the monitor of
the object.
The yield() method causes the runtime system to put the current thread to sleep and
execute the next thread in the queue. The yield method can be used to ensure that the low
priority threads also get processor time
Syntax
public void static yield();
Example:
Consider an employment agency. As new job openings arise, they are made
available to the candidates. This has to be done carefully since the candidates cannot take
up more jobs than those that are available. The agency hence puts up one notice at a time
and wait for a candidate to take up the job. Hence, until the first job offer is filled, the
second is not put up. At the same time, only one candidate can be selected for a particular
job.
The problem is solved below using the wait() and notify() methods.
class JobOpening
{
int count;
boolean valueSet = false;
{
if (!valueSet)
{
try
{
wait();
}
catch(InterruptedException e) {}
}
JobOpening job;
JobOpening job;
/*Output would be
Put: 1
Got: 1
Put: 2
Got: 2
Put: 3
Got: 3
Put: 4
Got: 4
Put: 5
Got: 5
Put: 6
Got: 6
Put: 7
Got: 7
Put: 8
Got: 8
Put: 9
Got: 9
Put: 10
Got: 10
... It goes on infinitely
*/
65
When a Java thread is created, it inherits its priority from the thread that created
it. You can also modify a thread's priority at any time after its creation using the
setPriority method. The default property for uer is NORMAL_PROPETIES or 5.
Thread priorities are integers ranging between MIN_PRIORITY or 0 and MAX_PRIORITY or
10(constants defined in the Thread class). The higher the integer, the higher the priority.
At any given time, when multiple threads are ready to be executed, the runtime system
chooses the runnable thread with the highest priority for execution. Only when that thread
stops, yields, or becomes not runnable for some reason will a lower priority thread start
executing. If two threads of the same priority are waiting for the CPU, the scheduler
chooses one of them to run in a round-robin fashion. The chosen thread will run until one
of the following conditions is true:
Thread.MIN_PRIORITY 1
Thread.NORMAL_PRIORITY 5
Thread.MAX_PRIORITY 10
Then the second thread is given a chance to run, and so on, until the interpreter
exits. The Java runtime system's thread scheduling algorithm is also preemptive. If at any
time a thread with a higher priority than all other runnable threads becomes runnable, the
runtime system chooses the new higher priority thread for execution. The new higher
priority thread is said to preempt the other threads.
Note: At any given time, the highest priority thread is running. However, this is not
guaranteed. The thread scheduler may choose to run a lower priority thread to avoid
starvation. For this reason, use priority only to affect scheduling policy for efficiency
purposes. Do not rely on thread priority for algorithm correctness.
66
Syntax:
Public final void setPriority(int newPriority)
Example:
This given program implements an applet that animates a race between two
"runner" threads with different priorities. When you click the mouse down over the
applet, it starts the two runners. The top runner, labelled "2", has a priority of 2. The
second runner, labelled "3", has a priority of 3.
import java.applet.*;
import java.util.*;
import java.awt.*;
import java.text.*;
import java.awt.event.*;
runners[i].setPriority(i+2);
else
runners[i].setPriority(2);
}
if (updateThread == null)
{
updateThread = new Thread(this, "Thread
Race");
updateThread.setPriority(NUMRUNNERS+2);
}
addMouseListener(new MyAdapter());
}
67
Java was designed to meet the real-world requirements of creating interactive, networked
programs. To achieve this, Java supports multithreaded programming, which allows the
user to write programs that performs many functions simultaneously. The Java run-time
system enables the user to construct smoothly running interactive systems. Java’s easy-
to-use approach to multithreading allows the user to think about the specific behaviour of
his/her own program, not the multitasking subsystem.
Every time you start a program, thread is automatically started. This is the main thread,
which starts as soon the execution of the program starts,
from which are other threads can be spawned and
which stops when the program is terminated.
Threads can be created in two ways. They are:
By extending the Thread class
By implementing the Runnable interface
Difference between Multi threading and Time sharing are given below, Illustrate
these differences with some practical examples
Multi Threading Time Sharing
1. Threads are a popular way to improve In Traditional Time sharing OS the basic unit of CPU
application performance through parallelism. utilization is a process.
2. Here the basic unit of CPU utilization is Each process has its own program counter, its own
thread which consist of single address space register status, its own stack, and its own address
and one or more threads of control. space.
3. Each thread of a process has its own In time sharing each and every process use same
program counter, its own register status, and program counter, register and stack but they have their
its own stack, but all these share a same own address space and use local variables.
address space and same global variables.
4. Due to sharing of a same address space Since time sharing uses there own address space, it is
70
6. The overheads involved in creating a new The overheads involved in creating a process are
process is less. more.
7. Resource sharing can be achieved more Resource sharing can be done with some
efficiently and naturally. programming effort.
8. This is referred to as light weight processes. This is referred as heavy weight processes.
Solution 1
A thread is a line of execution. It is the smallest unit of code that is dispatched by the scheduler.
States of a Thread:
There are four states associated with a thread namely
new
runnable
dead and
blocked
New:
When a thread is created, it is new state. New implies that the thread object has
been created but it has not started running. It requires the start() method to start it.
Runnable:
A thread is said to be in runnable state, when it is executing a set of instructions. The run() method
contains the set of instructions. This method is called automatically after start() method.
Dead:
71
The normal way for a thread to die is by returning it’s run() method. We can also call stop(), but
this throws an exception that’s a subclass of Error (which means we normally do not catch it). Remember
that throwing an exception should be a special event and not part of normal program execution; thus the use
of stop() is discouraged. There is also a destroy() method (which is never been implemented) that should
never be called if we can avoid it, since it is drastic and does not release object locks.
Blocked:
The thread could be run but there is something that prevents it. While thread is in the blocked state
the scheduler will simply skip over it and not give it any CPU time. Until a thread re-enters the runnable
state it will not perform any operations.
Common Thread Methods:
start():
The start method starts execution of the invoking object. It canthrow an
IllegalThreadStateException if the thread was already started.
stop():
This method terminates the invoking object.
suspend():
This method suspends the invoking object. The thread will become runnable again
if it gets the resume() method.
sleep():
This sleep method suspends execution thread for the specified number of milliseconds. It can
throw an InterruptedException.
Syntax:
public static void sleep(long ms)
The following statement can suspend execution of the executing thread for the specified number of
milliseconds plus nanoseconds.
public static void sleep(long ms, int ns)
resume():
The resume() method restarts the suspended thread at the point at which it was halted. The
resume() method is called by some thread outside the suspended one, there is a separate class called
Resumer which does just that. Each of the classes demonstrating suspend/resume has an associated
resumer.
3.8. REFERENCES
Herbert Schidt, “The Complete Reference Java 2”, 5th Ed., TMH, 2002
Jane Jawroski, “Java Unleashed”, SAMS Techmedia Publications, 1999
72
5.1. INTRODUCTION
A collection is an object that contains a group of objects within it. These objects
are called the elements of the collection. The elements of a collection usually descend
from a common parent type. Java supports collection classes like Vector, Bits, Stack,
Hashtable and Linkedlist. Collections hold references to objects of type Object. These
new enhancements to the Java language are part of the java.util package.
In addition to the collections, the collection framework also defines several map
interfaces and classes. Maps store key/value pairs. Although maps are not “collections” in
the true sense of the word, they are fully integrated with collections.
73
The objects in a Collection interface are not ordered. It enables one to work with
a group of objects, and is at the top of the collections hierarchy.
The core collection interfaces encapsulate different types of collections, which are shown
in the figure below. These interfaces allow collections to be manipulated independently
of the details of their representation. Core collection interfaces are the foundation of the
Java Collections Framework. As you can see in the following figure, the core collection
interfaces form a hierarchy.
A Set interface extends collection to handle sets, i.e a group of objects with no
duplication.
The Collection interface is the foundation upon which the collection framework is built.
It declares the core methods that all collections must have. These methods are given
below:
74
Method Description
boolean add(Object obj) Adds obj to the invoking collection. Returns true
if obj was added to the collection. Returns false if
obj is already a member, and no duplication is
allowed.
boolean addAll(Collection c) Adds all the elements of c to the invoking
collection. Returns true if the operation succeeded
(i.e the elements were added). Else returns false.
void clear() Removes all elements from the invoking collection
boolean contains(Object obj) Returns true if obj is an element of the invoking
collection. Else returns false
boolean containsAll(Collection c) Returns true if the invoking collection contains all
elements of c. Otherwise it returns false.
boolean equals(Object obj) Returns true if the invoking collection and object
obj are equal. Otherwise returns false.
int hashCode() Returns the hash code for the invoking collection
boolean isEmpty() Returns true if the invoking collection is empty.
Otherwise returns false
Iterator iterator() Returns an iterator for the invoking collection
boolean remove(object Obj) Removes one instance of obj from the invoking
collection. Returns true if the element was
removed. Otherwise returns false
boolean removeAll(Collection c) Removes all elements of c from the invoking
collection. Returns true if the collection changed,
(i.e elements were removed). Otherwise returns
false
boolean retainAll(Collection c) Removes all elements from the invoking collection
except those in c. Returns true if the collection
changed, (i.e elements were removed). Otherwise
returns false
int size() Returns the number of elements contained in the
invoking collection.
Object[] to Array() Returns an array that contains all the elements
stored in the invoking collection. The array
elements are copies of the collection elements
Object[] to Array(Object array[]) Returns an array containing only those collection
elements whose type matches that of array. The
array elements are copies of the collection
elements.
The List interface extends the Collection interface and declares the behavior of a
collection that stores a sequence of elements. Elements can be inserted or accessed by
their position in the list, using a zero-based index. A list may contain duplicate elements.
75
In addition to the methods defined by Collection, List defines its own methods. They are
given below:
Method Description
void add(int index, Object obj) Inserts obj into the invoking list at the index
passed in index. Any pre-existing elements at
or beyond the point of insertion are shifted up.
No elements are overwritten
boolean addAll(int index, Collection c) Inserts all elements of c into the invoking list at
the index passed in index. Any pre-existing
elements at or beyond the point of insertion are
shifted up. No elements are overwritten.
Returns true if the invoking list changes.
Otherwise returns false.
Object get(int index) Returns the object stored at the specified index
within the invoking collection
int indexOf(Object obj) Returns the index of the first instance of obj in
the invoking list. If obj is not an element in the
list, -1 is returned.
int lastIndexOf(Object obj) Returns the index of the last instance of obj in
the invoking list. If obj is not an element in the
list, -1 is returned.
ListIterator Listiterator() Returns an iterator to the start of the invoking
list.
ListIterator Listiterator(int index) Returns an iterator to the invoking list that
begins at the specified index.
Object remove(int index) Removes the element at position index from
the invoking list and returns the deleted
element. The resulting list is compacted. That
is, the indexes of the subsequent elements are
decremented by one
Object set(int index, Object obj) Assigns obj to the location specified by index
within the invoking list.
List subList(int start, int end) Returns a list that includes elements from start
to end –1 in the invoking list. Elements in the
returned list are also referenced by the
invoking object.
The SortedSet interface extends Set and declares the behavior of a set sorted in
ascending order. In addition to those methods defined in Set, the SortedSet defines
declares the methods given below:
Method Description
Comparator comparator() Returns the invoking sorted set’s
comparator. If natural ordering is used, it
returns null.
Object first() Returns the first element in the invoking
sorted set.
Object last() Returns the last element in the invoking
sorted set.
SortedSet headset(Object end) Returns a SortedSet containing those
elements less than end that are contained in
the invoking sorted set. Elements in the
returned sorted set are also referenced by
the invoking sorted set.
SortedSet subSet(Object start, Object end) Returns a SortedSet that includes those
elements between start and end -1.
Elements in the returned set are also
referenced by the invoking object.
SortedSet tailSet(Object start) Returns a SortedSet that contains those
elements greater than or equal to start that
are contained in the sorted set. Elements in
the returned set are also referenced by the
invoking object.
There are a number of standard classes that are used to implement the interfaces
described above. Some of the classes provide full implementations that can be used as
they are. Others are abstract, providing skeletal implementations that are used as starting
points for creating concrete collections.
Class Description
AbstractCollection Implements most of the Collection
interface
AbstractList Extends AbstractCollection and
implements most of the List interface
LinkedList Implements a linked list by extending
AbstractSequentialList
77
The ArrayList class extends AbstractList and implements the List interface.
ArrayList supports dynamic arrays that can grow as needed. In essence ArrayList is a
variable length array of object references. Dynamic arrays are also supported by the
legacy class Vector, which has been re-engineered to support collections.
ArrayList()
This builds an empty array list.
ArrayList(Collection c)
This builds an array list that is initialized with the elements of the collection c.
ArrayList(int capacity)
This builds an array list that has the specified initial capacity capacity.
//Demonstrate ArrayList
import java.util.*;
class ArrayListDemonstration
{
public static void main(String args[])
{
// Create an array list
ArrayList arr = new ArrayList();
Sometimes there is a need to obtain an actual array that contains the contents of the array
list. The following program illustrates how to do so:
class ArrayListtoArray
{
public static void main(String args[])
{
// Create an array list
ArrayList arr = new ArrayList();
}
}
LinkedList()
This builds an empty linked list.
LinkedList(Collection c)
This builds linked list that is initialized with the elements of the collection c.
In addition to the methods that it inherits, the LinkedList class defines some useful
methods of its own. They are:
addFirst()
addLast()
getFirst()
Syntax:
Object getFirst()
getLast()
removeFirst()
removeLast()
Example:
// Demonstrate LinkedList
import java.util.* ;
class LinkedListDemo
{
public static void main (String args[])
{
//Create a linked list
LinkedList llist = new LinkedList();
//Add elements
llist.add(“A”);
llist.add(“B”);
llist.add(“C”);
llist.add(“D”);
llist.add(“E”);
llist.addFirst(“F”);
llist.addLast(“Z”);
llist.add(1,”ZZ”);
}
}
This initializes both the capacity and the fill ratio (load capacity) of the hash set from its arguments.
The fill ratio must be between 0.0 and 1.0
82
Example
//Demonstrate HashSet
import java.util.* ;
class HashSetDemonstration
{
public static void main (String args[])
{
//Create a HashSet
HashSet hset = new HashSet();
Output:
TreeSet provides an implementation of the Set interface that uses a tree for
storage. Objects are stored in sorted, ascending order. Aceess and retrieval times are quite
fast, which makes TreeSet an excellent choice when storing large amounts of sorted
information that must be found quickly.
Example
//Demonstrate TreeSet.
import java.util.* ;
class TreeSetDemonstration
{
public static void main (String args[])
{
//Create a tree set
TreeSet tset = new TreeSet();
Output:
5.5. ITERATOR
An Iterator provides the easiest way to cycle through the elements of the collection. It enables
cycling through a collection, obtaining or removing elements. ListIterator extends Iterator to allow bi-
directional traversal of a list.
Using an Iterator
Each of the collection classes provides an iterator() method that returns an iterator to the start of
the collection. The following steps are followed:
1. Obtain an iterator to the start of the collection by calling the collection’s iterator() method.
2. Set up a loop that makes a call to hasNext(), Have the loop iterate as long as hasNext() returns
True.
84
Example
//Demonstrate iterators
import java.util.*;
System.out.println();
}
}
A map is an object that stores associations between keys and values, or key/value pairs. Given a
key, you can find its value. Both keys and values are objects. The keys must be unique, but values may be
duplicated. Some maps even accept null key and null values.
Map Interfaces
Interface Description
Map Maps unique keys to values
Map.Entry Describes an element (a key/value pair) in a map. This is an inner class
of Map
SortedMap Extends Map so that the keys are maintained in an ascending order.
The Map Interface
The Map interface maps unique keys to values. A key is an object that can be
used to retrieve a value at a later date. Given a key and a value, the value can be stored in
a Map object After storing the value, it can be retrieved using its key. The methods used
by Map are:
Method Description
void clear() Removes all key/value pairs from the invoking map
Boolean containsKey(Object k) Returns true if the invoking map contains k as a key.
Otherwise returns false.
Boolean containsValue(Object v) Returns true if the map contains v as a value.
Otherwise returns false.
Set entrySet() Returns a Set that contains the entries in the map.
The set contains objects of type Map.Entry. This
method provides a set-view of the invoking map
Boolean equals(Object obj) Returns true if obj is a Map and contains the same
entries. Otherwise returns false.
Object get(Object k) Returns the value associated with the key k
int hashCode() Returns the hash code for the invoking map
Boolean isEmpty() Returns true if the invoking map is empty.
Otherwise returns false.
86
Set keySet Returns a Set that contains the keys in the invoking
map.
Object put(Object k, Object v) Puts an entry in the invoking map, overwriting any
previous value associated with the key. The key and
value are k and v, respectively. Returns null if the
key didn’t exist already. Otherwise the previous
value linked to the key is returned.
void putAll(Map m) Puts all entries from m into this map
Object remove (Object k) Removes the entry whose key equals k
int size() Returns the number of key/value pairs in the map
Collection values() Returns a collection containing the values in the
map. This method provides a collection-view of
values in the map.
This helps in working with a map entry. Recall from above that the entrySet()
method declared by the Map interface returns a Set containing the map entries. Each of
these entries is a Map.Entry object. The methods for the Map.Entry interface is given
below:
Method Description
Boolean equals(Object obj) Returns true if obj is a Map.Entry whose key and value
are equal to that of the invoking object.
Object getKey() Returns the key for this map entry
Object getValue Returns the hash code for this map entry
Int hashCode Returns the hash code for this map entry
Object setValue(Object v) Sets the value for this map entry to v
The SortedMap interface extends Map. It ensures that the entries are maintained
in the ascending order. The methods are given below:
Method Description
Comparator comparator() Returns the invoking sorted map’s
comparator. If the natural ordering is
used for the invoking map, null is
returned.
Object firstKey() Returns the first key in the invoking map
SortedMap headMap(Object end) Returns a sorted map for those map
entries whose keys are less than end
Object lastKey() Returns the last key in the invoking map.
SortedMap subMap(Object start, Object end) Returns a map containing those entries
with keys that are greater than or equal to
87
Several classes provide implementations of the map interfaces. The classes that are used
for maps are given below:
Class Description
AbstractMap Implements most of the Map interface
HashMap Extends AbstractMap to use a hash table
TreeMap Extends AbstractMap to use a tree
WeakHashMap Extends AbstractMap to use a hash table with weak keys
The HashMap class uses a hash table to implement the Map interface. The constructors
are:
HashMap()
This constructs a default hash map
HashMap(Map m)
This initializes the hash map by using the elements of m
HashMap(int capacity)
This initializes the capacity of the hash map to capacity
HashMap(int capacity, float fillRatio)
This initializes both the capacity and the fill ratio (load capacity) of the hash map from its arguments.
The fill ratio must be between 0.0 and 1.0
The HashMap implements Map and extends AbstractMap. It does not add any methods of its own.
Example
class HashMapDemonstration
{
public static void main (String args[])
{
//Create a Hash Map
88
//Get an iterator
Iterator i = set.iterator();
//Display elements
while (i.hasNext())
{
Map.Entry men = (Map.Entry)i.next();
System.out.print(men.getKey() + “: “);
System.out.println(men.getValue());
}
System.out.println();
Output
Thomas Mathew: 3421.56
Ram Gopal: 1234.56
Ayesha Kannan: 5612.34
Suhasini Akbar: 2345.61
Mohan Shankar: 6543.21
Abdul Gafoor: 4321.65
The TreeMap class implements the Map interface by using a tree. A TreeMap
provides an efficient means of storing key/value pairs in a sorted order, and allows rapid
retrieval. The constructors are as follows:
TreeMap()
89
This constructs an empty tree map that will be sorted according to the natural
order of its keys.
TreeMap(Comparator comp)
This constructs an empty tree-based map that will be sorted according to the
comparator specified by comp.
TreeMap(Map m)
This builds a tree map that contains the entries of m.
TreeMap(SortedMap sm)
This builds a tree map that contains the entries of sm, which will be sorted in the
same order an sm
The TreeMap implements SortedMap and extends AbstractMap. It does not add any methods of its own.
Example
class TreeMapDemonstration
{
public static void main (String args[])
{
//Create a Tree Map
TreeMap tmap = new TreeMap();
// Add elements to the map
tmap.put(“Ram Gopal”, new Double(1234.56));
tmap.put(“Mohan Shankar”, new Double(6543.21));
tmap.put(“Abdul Gafoor”, new Double(4321.65));
tmap.put(“Thomas Mathew”, new Double(3421.56));
tmap.put(“Ayesha Kannan”, new Double(5612.34));
tmap.put(“Suhasini Akbar”, new Double(2345.61));
//Get an iterator
Iterator i = set.iterator();
//Display elements
while (i.hasNext())
{
Map.Entry men = (Map.Entry)i.next();
System.out.print(men.getKey() + “: “);
System.out.println(men.getValue());
}
System.out.println();
tmap.get(“Ram Gopal”));
}
}
Output
The above are sorted according to the first names. Using a comparator however one can
change the behavior of sorting.
The function hasMoreElements () returns true if there are still more elements to extract and
false when all the elements have been enumerated.
5.6. VECTOR
Vector implements a dynamic array. It is similar to an array list but with two
differences. All vectors are synchronized and contain many methods that are not part of
the collection framework.
All vectors start with an initial capacity. After this initial capacity is reached the
next time you attempt to store an object the vector automatically allocates space for that
object.
Int capacityIncrement;
91
Int elementCount;
Object elementData [];
import java.io.*;
import java.util.*;
class VectorDemo
{
public static void main(String s[])
{
Vector v = new Vector(3,2); //initial size = 3 increments
by 2
v.addElement(new Integer(1));
v.addElement(new Integer(2));
v.addElement(new Integer(3));
v.addElement(new Integer(4));
v.addElement(new Double(5.45));
System.out.println("Current Capacity"+v.capacity());
v.addElement(new Double(6.08));
v.addElement(new Integer(7));
v.addElement(new Float(2.4));
v.addElement(new Integer(8));
if(v.contains(new Integer(3)))
System.out.println("Vector Contains 3");
while(venum.hasMoreElements())
{
System.out.println(venum.nextElement()+"");
}
System.out.println(" ");
}
}
Elements In Vector
1
2
3
4
5.45
6.08
7
2.4
8
*/
Many data structures provide sorting and searching routines. The idea of sorting
presupposes that the data items are ordered in some way. Searching does not presuppose
an order, but it is quicker to search for an item if the items have previously been sorted.
Many data types have an intrinsic ordering. This is obvious for the primitive numeric
types. Characters are also ordered by their ASCII or Unicode values. This is the same as
the usual alphabetic ordering for letters of the alphabet. The ordering of characters can be
extended to the usual lexicographic ordering for strings.
When writing a sorting or searching algorithm, the nature of the elements sorted is
usually unimportant. It is only necessary to refer to their ordering relation.
5.7.1. Linked List
Class LinkedList
java.lang.Object
|
93
+--DataStructures.LinkedList
which removes the first item from the list. Lists can be traversed using an iterator, for
example:
for (Iterator i = list.iterator(); i.hasNext();) {
System.out.println(e.next());
{
**
* Class: LinkedListDemo
* Purpose: To demonstrate the use of a single linked list
*/
import DataStructures.LinkedList;
import java.util.*;
Iterator i;
System.out.print("enumeration:");
for (i = list.iterator(); i.hasNext();) {
System.out.print(" " + i.next());
}
System.out.println();
list.removeFirst();
System.out.println("list = " + list);
System.out.println("size = " + list.size());
list.reverse();
System.out.println("reversed list = " + list);
}
}
5.8. SORTING
Sorting data (i.e., placing the data into some particular order, such as ascending or
descending) is one of the most important computing applications. A bank sorts all checks
by account number so that it can prepare individual bank statements at the end of each
month. Telephone companies sort their lists of accounts by last name and, further, by first
name to make it easy to find phone numbers. Virtually every organization must sort
some data, and often, massive amounts of it. Sorting data is an intriguing, computer-
intensive problem that has attracted intense research efforts.
An important item to understand about sorting is that the end result-the sorted
array-will be the same no matter which algorithm you use to sort the array. The choice of
algorithm affects only the run time and memory use of the program.
index, leaving the largest element in the last index. After the ith iteration, the smallest i
items of the array will be sorted into increasing order in the first I elements of the array.
The following declares the StringOrdering class. This demonstrates the selection sort for
given strings.
class StringOrdering
{
static String name[] = {"Ambika", "Ramya", "Kamala",
"Suresh", "Akaash"};
public static void main(String args[])
{
int size = name.length;
String temp = null;
for (int i=0; i<size; i++)
{
for(int j = i+1; j<size; j++)
{
if(name[j].compareTo(name[i]) < 0)
{
temp = name[i];
name[i] = name[j];
name[j] = temp;
}
}
}
for(int i = 0; i<size; i++)
{
System.out.println(name[i]);
}
}
}
Output:
96
into increasing order. For this to make sense, the elements must be comparable with
respect to order. So we assume that array elements implement the Comparable interface.
Note that the array itself may be of length greater than n. The specification only requires
that the first n elements should be sorted.
1. The simple algorithm requires auxiliary storage for the heap. In fact it is possible
to use the original array itself as the heap. This would provide a genuinely ``in-
place'' sorting routine.
2. Insertion of the array elements one by one, and restoring the heap order property
after each insertion, is not the most efficient way of building the heap. That was
necessary for the priority queue implementation, since the next method to be
called might be the remove method, so the heap had to be properly ordered at all
times. In our case we only want to remove elements after all of them have been
inserted. In that case, it turns out there is a more efficient way of building the
heap.
Sorting by removal
Now we have converted the original array to a heap, it is simple to order it by repeatedly
applying the heap removal algorithm.
When implementing priority queues, using binary heaps, the remove method returned the
maximum element. Instead of returning it, we now just move it to the appropriate place at
the end of the array. The reason we can do this, is that the heap is smaller by one when
we remove an element, so another place is always freed up at the end each time.
Consider where we have got to as a result of heapifying the array. This was
Now when we remove the maximum element, which is always the first, the remove
algorithm tells us to put the last element in the first position, and then demote it until we
reestablish heap order. We can do both relocations at once by swapping the first and last
element. This gives
where the thick line indicates that we are now only concerned with the first four
elements. The segment of the array after the thick line is the sorted array that we are
building up.
Now the first four elements are not in heap order. So we need to apply the demote
method, with size reduced by 1, beginning with the root node as parent. This is easily
seen to produce the array
Repeating the same procedure, of swapping the first and last elements of the heap
(ignoring the 42 which is no longer part of the heap), we obtain
which again needs to be restored to heap order. Repeating this routine until the heap is
empty, will provide us with a sorted array. The code for this part of the routine is simple:
for (int i = n - 1; i > 0; i--) {
swap(a, i, 0);
demote(a, i, 0);
}
This assumes that the array is originally in heap order. The index i begins with the last
element of the array which is at n-1. This is swapped with the first element, which is at
0, and then demote is called with i as the current size of the array, and with the root 0 as
parent. The swap routine simply exchanges the contents of a[i] and a[0].
The final code for the heapSort routine is shown below:
public class Sort {
private Sort() {}
98
}
Figure : A class providing the heap sort method.
The code has been placed in a Sort class which might include other sorting routines such
as quickSort, mergeSort, shellSort etc. One advantage of heapSort is that it is a genuinely
/**
* Class: HeapSortDemo
* Purpose: To demonstrate the use of heap sort
*/
import DataStructures.*;
import java.util.*;
System.out.print("random:");
for (int i = 0; i < n; i++) {
System.out.print(" " + array[i]);
}
System.out.println();
long t1 = System.currentTimeMillis();
Sort.heapSort(array, n);
long t2 = System.currentTimeMillis();
System.out.print("sorted:");
for (int i = 0; i < n; i++) {
System.out.print(" " + array[i]);
}
System.out.println();
System.out.println();
System.out.println("That took " + (t2-t1) + " milliseconds");
}
}
5.9. TREES
Linked lists, stacks and queues are linear data structures (i.e., sequences). A tree is
a non linear, two-dimensional data structure with special properties. Tree nodes contain
two or more links. This section discusses binary trees whose nodes each contain two
links (one or both of which may be null). The root node is the first node in a tree. Each
link in the root node refers to a child. The left child is the first node in the left subtree
(also known as the root node of the left subtree), and the right child is the first node in the
right subtree (also know as the root note of the right subtree). The children of a specific
node are called siblings. A node with no children is called a leaf node. Computer
scientists normally draw trees from the root node down-exactly the opposite of the way
most trees grow in nature.
or
or even
in which there are paths from some leaf to the root whose lengths differ by more than 1.
We want trees in which every level is fully occupied except, possibly, for the bottom
level.
It is also very convenient, as you will see, if the bottom level is filled from left to right. (It
could alternatively be filled from right to left, but we need to agree on one or the other.)
Binary trees of this type are called complete. They are defined as being completely filled,
except possibly for the bottom level, which is filled from left to right. A complete binary
tree which also satisfies the ordering property (H) is called a binary heap.
Arrays as complete binary trees
Suppose the array to be sorted is [31, 35, 40, 10, 42]. Let us picture this as
101
where the empty spaces marked indicate that we are not concerned with these extra
entries or, indeed, how many there are of them. Now there is nothing to prevent us from
thinking of this as the array representation of the complete binary tree
Evidently any array can be pictured in this way as a complete binary tree. The problem is
that it is not a heap, as it stands, since it fails to satisfy the heap order property.
Fortunately there is an efficient algorithm for restoring heap order, which we can apply to
the original array. The original array will then play the part of our working binary heap,
without the need for auxiliary storage.
(S)A binary search tree is a binary tree in which the value stored at each node of the tree
is greater than the values stored in its left subtree and less than the values stored in its
right subtree.
Binary search trees can be constructed with other types of data. All that matters is that the
data items can be compared with regard to order.
If we want to find out whether a given object is present in a binary search tree, we can
proceed as follows. Suppose the item is the number 39. Beginning at the root of the tree,
we see that 39 is greater than 21, so that if 39 is present in the tree, it must occur in the
right hand sub-tree because of the (S) property. Since 39 is less than 40, it must occur in
the left-hand sub-tree of the tree rooted at 40. We next compare 39 with 31, move to the
right and finally compare 39 with 35. Since 39 is greater than 35, it must occur in the
right hand sub-tree of the tree rooted at 35, if it occurs at all. But the right-hand sub-tree
at 35 is empty, and nothing occurs in the empty tree. We have therefore established that
39 is not present in the tree.
102
Note that all the comparisons made occurred on a path through the tree, beginning at the
root and ending at one of the leaves. For efficiency, binary search trees are much more
useful if they are balanced. This means that the path lengths from the root node to each of
the leaf nodes are roughly the same. The tree shown above is not as well balanced as it
could be. The same data could just as well be stored in the balanced tree
There are several algorithms for re-balancing binary search trees. These will be discussed
in a later course.
/**
* Class: SearchTreeDemo
* Purpose: To demonstrate the use of a binary search tree
*/
import DataStructures.*;
import java.util.*;
SearchTree t = SearchTree.empty();
System.out.println("tree in order:");
for (Enumeration e = t.elementsInOrder(); e.hasMoreElements();)
{
System.out.print(" " + e.nextElement());
}
System.out.println();
while (!t.isEmpty()) {
103
}
}
1. Write a class that holds a number (long) and its factors. The factors should be stored
in a Vector. A member function should take in the number from the user and find its
factors and put it in a Vector.
2. Redo the above problem but this time with ArrayList. A member function in that
class should check if the number is a perfect number or not (A perfect number is the
one whose sum of all its factors except itself sums upto itself).
3. Write a class that holds two numbers and their factor. This time there should be
function that should check if the numbers are amicable numbers. (Two numbers are
said to be amicable if one number’s factors sum upto the other and vice-versa)
4. In the above problem try to use TreeMap to give a structure to the factors of the two
numbers.
1. This lesson mentions three ways to traverse a List. Describe them, and
note the limitations of each.
2. Consider the four core interfaces, Set, List, Queue, and Map. For each
of the following four assignments, specify which of the four core interfaces
is best suited, and explain how to use it to implement the assignment.
104
WPMC has decided that each new product will be named after an
employee — but only first names will be used, and each name will
be used only once. Prepare a list of unique first names.
WPMC decides that it only wants to use the most popular names for
its toys. Count the number of employees who have each first name.
import java.util.*;
public class SortMe {
public static void main(String args[]) {
SortedSet<StringBuffer> s = new
TreeSet<StringBuffer>();
s.add(new StringBuffer("Red"));
s.add(new StringBuffer("White"));
s.add(new StringBuffer("Blue"));
System.out.println(s.first());
}
}
5.10. REFERENCES
6.1. INTRODUCTION
The Java platform is highly regarded in part because of its suitability for writing
programs that use and interact with the resources on the Internet and the World Wide
Web. In fact, Java-compatible browsers use this ability of the Java platform to the
extreme to transport and run applets over the Internet. Java provides java.net package,
which provides support for networking.
What makes Java a good language for networking are the classes defined in the
java.net package. These networking classes encapsulate the socket paradigm pioneered at
the Berkeley Software Distribution from the university of California at Berkeley.
The applets that you have run are referenced by a special tag in an HTML file, the
<APPLET> tag. Applets can be located anywhere, whether on your local machine or
somewhere out on the Internet. The location of the applet is completely invisible to you,
the user. However, the location of the applet is encoded within the <APPLET> tag. The
browser decodes this information, locates the applet, and runs it. If the applet is on some
machine other than your own, the browser must download the applet before it can be run.
This is the highest level of access that you have to the Internet from the Java
development environment. It is the browser that does all of the work of connecting to the
network and getting data from it, thereby enabling you to run applets from anywhere in
the world.
One particular class in the java.net package called URL represents a Uniform
Resource Locator and is the address of some resource on the network. Your applets and
applications can use a URL to reference and even connect to resources out on the
network. For example, to load an image from the network, your Java program must first
create a URL that contains the address to the image.
This is the next highest level of interaction you can have with the Internet--your
Java program gets an address of something it wants, creates a URL for it, and then uses
some existing function in the Java development environment that does the grunt work of
connecting to the network and retrieving the resource.
When you write Java programs that communicate over the network, you are
programming at the application layer. Typically, you don't need to concern yourself with
the TCP and UDP layers. Instead, you can use the classes in the java.net package.
107
6.2.1. TCP
When two applications want to communicate to each other reliably, they establish
a connection and send data back and forth over that connection. This is analogous to
making a telephone call. If you want to speak to Aishwarya Rai in Mumbai, a connection
is established when you dial her phone number and she answers. You send data back and
forth over the connection by speaking to one another over the phone lines. Like the phone
company, TCP guarantees that data sent from one end of the connection actually gets to
the other end and in the same order it was sent. Otherwise, an error is reported.
Example Of TCP/IP
import java.net.*;
class InetAddressTest
{
public static void main(String s[])
{
try
{
InetAddress Address = InetAddress.getLocalHost();
System.out.println(Address);
Address = InetAddress.getByName("yahoo.com");
System.out.println(Address);
InetAddress SW[] =
InetAddress.getAllByName("www.indya.com");
for(int i =0;i < SW.length;i++)
{
System.out.println(SW[i]);
}
}
catch(Exception e)
{
System.out.println("You Are Not Connected To The
Net");
}
108
}
}
/* Output:
pc1/202.202.202.1
www.yahoo.com/216.115.108.243
www.indya.com/64.41.181.230
*/
6.2.2. UDP
Definition: UDP (User Datagram Protocol) is a protocol that sends independent packets
of data, called datagrams, from one computer to another with no guarantees about arrival.
UDP is not connection-based like TCP.
The UDP protocol provides for communication that is not guaranteed between
two applications on the network. UDP is not connection-based like TCP. Rather, it sends
independent packets of data, called datagrams, from one application to another. Sending
datagrams is much like sending a letter through the postal service: The order of delivery
is not important and is not guaranteed, and each message is independent of any other.
For many applications, the guarantee of reliability is critical to the success of the
transfer of information from one end of the connection to the other. However, other forms
of communication don't require such strict standards. In fact, they may be slowed down
by the extra overhead or the reliable connection may invalidate the service altogether.
Consider, for example, a clock server that sends the current time to its client when
requested to do so. If the client misses a packet, it doesn't really make sense to resend it
because the time will be correct when the client receives it on the second try. If the client
makes two requests and receives packets from the server out of order, it doesn't really
matter because the client can figure out that the packets are out of order and make another
request. The reliability of TCP is unnecessary in this instance because it causes
performance degradation and may hinder the usefulness of the service.
Another example of a service that doesn't need the guarantee of a reliable channel
is the ping command. The purpose of the ping command is to test the communication
between two programs over the network. In fact, ping needs to know about dropped or
out-of-order packets to determine how good or bad the connection is. A reliable channel
would invalidate this service altogether.
The UDP protocol provides for communication that is not guaranteed between
two applications on the network. UDP is not connection-based like TCP. Rather, it sends
independent packets of data from one application to another. Sending datagrams is much
like sending a letter through the mail service: The order of delivery is not important and
is not guaranteed, and each message is independent of any others.
109
import java.net.*;
class MainServer
{
public static int serverport = 666;
public static int clientport = 999;
public static int buffer_size = 1024;
public static DatagramSocket ds;
public static byte buffer[] = new byte[buffer_size];
}
}
}
TheServer();
}
else
{
ds = new DatagramSocket(clientport);
TheClient();
}
}
}
/*
The above example implements a simple networked communications client and server.
message are typed into the window at the server and written across to the client window
where they are displayed
to use this program first compile it then type
java MainSever
java MainServer 1
This is the server.Anything that is typed at the server will be written to the client window
*/
The Output is is similar to this
111
Definition: The TCP and UDP protocols use ports to map incoming data to a particular
process running on a computer.
Port numbers range from 0 to 65,535 because ports are represented by 16-bit
numbers. The port numbers ranging from 0 - 1023 are restricted; they are reserved for use
by well-known services such as HTTP and FTP and other system services. These ports
are called well-known ports. Your applications should not attempt to bind to them.
Through the classes in java.net, Java programs can use TCP or UDP to
communicate over the Internet. The URL, URLConnection, Socket, and
ServerSocket classes all use TCP to communicate over the network. The
DatagramPacket, DatagramSocket, and MulticastSocket classes are for use
with UDP.
URL is the acronym for Uniform Resource Locator. It is a reference (an address)
to a resource on the Internet. You provide URLs to your favorite Web browser so that it
can locate files on the Internet in the same way that you provide addresses on letters so
that the post office can locate your correspondents.
Java programs that interact with the Internet also may use URLs to find the
resources on the Internet they wish to access. Java programs can use a class called URL in
the java.net package to represent a URL address.
The term URL can be ambiguous. It can refer to an Internet address or a URL
object in a Java program. Where the meaning of URL needs to be specific, we use "URL
113
address" to mean an Internet address and "URL object" to refer to an instance of the URL
class in a program.
What Is a URL?
A URL takes the form of a string that describes how to find a resource on the
Internet. URLs have two main components: the protocol needed to access the resource
and the location of the resource.
If you've been surfing the Web, you have undoubtedly heard the term URL and
have used URLs to access HTML pages from the Web.
It's often easiest, although not entirely accurate, to think of a URL as the name of a file
on the World Wide Web because most URLs refer to a file on some machine on the
network. However, remember that URLs also can point to other resources on the
network, such as database queries and command output.
The following is an example of a URL which accesses the msn India homepage
http://www.msn.co.in/
Note that the protocol identifier and the resource name are separated by a colon
and two forward slashes. The protocol identifier indicates the name of the protocol to be
used to fetch the resource. The example uses the Hypertext Transfer Protocol (HTTP),
which is typically used to serve up hypertext documents. HTTP is just one of many
different protocols used to access different types of resources on the net. Other protocols
include File Transfer Protocol (FTP), Gopher, File, and News.
The resource name is the complete address to the resource. The format of the
resource name depends entirely on the protocol used, but for many protocols, including
HTTP, the resource name contains one or more of the components listed in the following
list:
host name
the name of the machine the resource lives on
filename
the pathname to the file on the machine
port number
the port number to connect to (this is typically optional)
reference
a reference to a named anchor within a resource; usually identifies a specific
location within a file (this is typically optional)
114
For many protocols, the host name and the filename are required, while the port
number and reference are optional. For example, the resource name for an HTTP URL
must specify a server on the network (Host Name) and the path to the document on that
machine (Filename); it also can specify a port number and a reference. In the URL for
theMSN Web site www.msn.co.in is the host name and the trailing slash is shorthand for
the file named /default.asp.
Creating a URL
The easiest way to create a URL object is from a String that represents the
human-readable form of the URL address. This is typically the form that another person
will use for a URL. For example, the URL for the yahoo site takes the form:
http://www.yahoo.com/
In your Java program, you can use a String containing this text to create a URL object:
The URL object created above represents an absolute URL. An absolute URL
contains all of the information necessary to reach the resource in question. You can also
create URL objects from a relative URL address.
The URL class provides several methods that let you query URL objects. You can get the
protocol, host name, port number, and filename from a URL using these accessor
methods:
getProtocol
Returns the protocol identifier component of the URL.
getHost
Returns the host name component of the URL.
getPort
Returns the port number component of the URL. The getPort method returns
an integer that is the port number. If the port is not set, getPort returns -1.
getFile
Returns the filename component of the URL.
getRef
Returns the reference component of the URL.
Not all URL addresses contain these components. The URL class provides these
methods because HTTP URLs do contain these components and are perhaps the most
commonly used URLs. The URL class is somewhat HTTP-centric.
You can use these getXXX methods to get information about the URL regardless
of the constructor that you used to create the URL object.
115
The URL class, along with these accessor methods, frees you from ever having to
parse URLs again! Given any string specification of a URL, just create a new URL object
and call any of the accessor methods for the information you need. This small example
program creates a URL from a string specification and then uses the URL object's
accessor methods to parse the URL:
import java.net.*;
import java.io.*;
protocol = http
host = java.sun.com
filename = /docs/books/tutorial/intro.html
port = 80
ref = DOWNLOADING
After the successful creation of a URL, you can call the URL's openStream()
method to get a stream from which you can read the contents of the URL. The
openStream() method returns a java.io.InputStream object, so reading from
a URL is as easy as reading from an input stream.
The following small Java program uses openStream() to get an input stream on
the URL http://www.hotmail.com/. It then opens a BufferedReader on the input
stream and reads from the BufferedReader thereby reading from the URL. Everything
read is copied to the standard output stream:
import java.net.*;
import java.io.*;
116
String inputLine;
in.close();
}
}
When you run the program, you should see, scrolling by in your command
window, the HTML commands and textual content from the HTML file located at
http://www.hotmail.com/.
Alternatively, the program might hang or you might see an exception stack trace.
If either of the latter two events occurs, you may have to set the proxy host so that the
program can find the Hotmail server.
After you've successfully created a URL object, you can call the URL object's
openConnection method to connect to it. When you connect to a URL, you are
initializing a communication link between your Java program and the URL over the
network. For example, you can open a connection to the Hotmail site with the following
code:
try
{
URL hotmail = new URL("http://www.hotmail.com/");
hotmail.openConnection();
} catch (MalformedURLException e)
{ // new URL() failed
. . .
}
catch (IOException e)
{ // openConnection() failed
. . .
}
Now that you've successfully connected to your URL, you can use the
URLConnection object to perform actions such as reading from or writing to the
connection. The next section shows you how.
The following program performs the same function as the URLReader program
shown in Reading Directly from a URL.
However, rather than getting an input stream directly from the URL, this program
explicitly opens a connection to a URL and gets an input stream from the connection.
Then, like URLReader, this program creates a BufferedReader on the input stream and
reads from it. The bold statements highlight the differences between this example and the
previous
import java.net.*;
import java.io.*;
The output from this program is identical to the output from the program that
opens a stream directly from the URL. You can use either way to read from a URL.
However, reading from a URLConnection instead of reading directly from a URL
might be more useful. This is because you can use the URLConnection object for
other tasks (like writing to the URL) at the same time.
118
Again, if the program hangs or you see an error message, you may have to set the
proxy host so that the program can find the Hotmail server.
Many HTML pages contain forms-- text fields and other GUI objects that let you
enter data to send to the server. After you type in the required information and initiate the
query by clicking a button, your Web browser writes the data to the URL over the
network. At the other end, a cgi-bin script (usually) on the server receives the data,
processes it, and then sends you a response, usually in the form of a new HTML page.
Many cgi-bin scripts use the POST METHOD for reading the data from the
client. Thus writing to a URL is often called posting to a URL. Server-side scripts use the
POST METHOD to read from their standard input.
A Java program can interact with cgi-bin scripts also on the server side. It
simply must be able to write to a URL, thus providing data to the server. It can do this by
following these steps:
1. Create a URL.
2. Open a connection to the URL.
3. Set output capability on the URLConnection.
4. Get an output stream from the connection. This output stream is connected to the
standard input stream of the cgi-bin script on the server.
5. Write to the output stream.
6. Close the output stream.
Hassan Schroeder, a member of the Java development team, wrote a small cgi-
bin script named backwards and made it available at the Java Web site,
http://java.sun.com/cgi-bin/backwards. You can use this script to test the
following example program. You can also put the script on your network, name it
backwards, and test the program locally.
The script at our Web site reads a string from its standard input, reverses the
string, and writes the result to its standard output. The script requires input of the form
string=string_to_reverse, where string_to_reverse is the string whose characters
you want displayed in reverse order.
Here's an example program that runs the backwards script over the network
through a URLConnection:
import java.io.*;
import java.net.*;
if (args.length != 1) {
System.err.println("Usage: java Reverse
string_to_reverse");
System.exit(1);
}
in.close();
}
}
Let's examine the program and see how it works. First, the program processes its
command-line arguments:
if (args.length != 1) {
System.err.println("Usage: java Reverse " +
"string_to_reverse");
System.exit(-1);
}
String stringToReverse = URLEncoder.encode(args[0]);
These statements ensure that the user provides one and only one command-line
argument to the program, and then encodes it. The command-line argument is the string
that will be reversed by the cgi-bin script backwards. It may contain spaces or other
non-alphanumeric characters. These characters must be encoded because the string is
processed on its way to the server. The URLEncoder class methods encode the
characters.
Next, the program creates the URL object--the URL for the backwards script on
java.sun.com--opens a URLConnection, and sets the connection so that it can write to it:
c.setDoOutput(true);
The program then creates an output stream on the connection and opens a
PrintWriter on it:
Next, the program writes the required information to the output stream and closes the
stream:
out.println("string=" + stringToReverse);
out.close();
This code writes to the output stream using the println method. So you can see
that writing data to a URL is as easy as writing data to a stream. The data written to the
output stream on the client side is the input for the backwards script on the server side.
The Reverse program constructs the input in the form required by the script by
concatenating string= to the encoded string to be reversed.
Often, when you are writing to a URL, you are passing information to a cgi-bin
script, as in this example. This script reads the information you write, performs some
action, and then sends information back to you via the same URL. So it's likely that you
will want to read from the URL after you've written to it. The Reverse program does
this:
When you run the Reverse program using "Reverse Me" as an argument, you should
see this output:
Reverse Me
reversed is:
eM esreveR
121
6.4. SOCKETS
Description of a Socket
Normally, a server runs on a specific computer and has a socket that is bound to a
specific port number. The server just waits, listening to the socket for a client to make a
connection request.
On the client-side: The client knows the hostname of the machine on which the
server is running and the port number to which the server is connected. To make a
connection request, the client tries to rendezvous with the server on the server's machine
and port.
If everything goes well, the server accepts the connection. Upon acceptance, the
server gets a new socket bound to a different port. It needs a new socket (and
consequently a different port number) so that it can continue to listen to the original
socket for connection requests while tending to the needs of the connected client.
The client and server can now communicate by writing to or reading from their
sockets.
122
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.
Given below is 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.
import java.io.*;
import java.net.*;
try {
echoSocket = new Socket("campione", 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: vanavil.");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to:
vanavil.");
System.exit(1);
}
123
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.
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:
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
vanavil. 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. PrintWriter on it.
Similarly, the third statement gets the socket's input stream and opens a
BufferedReader on it. The example uses readers and writers so that it can write
Unicode characters over the socket.
To send data through the socket to the server, EchoClient simply needs to write
to the PrintWriter. To get the server's response, EchoClient reads from the
BufferedReader. The rest of the program achieves this.
124
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();
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.
125
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:
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.
This section walks through the code that implements the Knock Knock server program.
The complete source for the KnockKnockServer class is given below:
import java.net.*;
import java.io.*;
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
outputLine = kkp.processInput(null);
out.println(outputLine);
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. Let the
KnockKnockServer listen on port 3333.
try {
serverSocket = new ServerSocket(3333);
} catch (IOException e) {
System.out.println("Could not listen on port: 3333");
System.exit(-1);
}
If the server successfully connects 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):
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.out.println("Accept failed: 3333");
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 a hypothetical machine
on port 3333). When a connection is requested and successfully established, the accept
method returns a new Socket object which is bound to a new port. The server can
communicate with the client over this new Socket and continue to listen for client
connection requests on the ServerSocket bound to the original, predetermined port.
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:
1. It gets the socket's input and output stream and opens readers and writers on them.
2. It Initiates communication with the client by writing to the socket (shown in bold).
3. It 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.
128
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 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 response to the server's statements. It wouldn't do to have the
client say "Turnip 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.
129
import java.net.*;
import java.io.*;
if (state == WAITING) {
theOutput = "Knock! Knock!";
state = SENTKNOCKKNOCK;
} else if (state == SENTKNOCKKNOCK) {
if (theInput.equalsIgnoreCase("Who's there?")) {
theOutput = clues[currentJoke];
state = SENTCLUE;
} else {
theOutput = "You're supposed to say \"Who's there?\"! "
+
"Try again. Knock! Knock!";
}
} else if (state == SENTCLUE) {
if (theInput.equalsIgnoreCase(clues[currentJoke] + "
who?")) {
theOutput = answers[currentJoke] + " Want another?
(y/n)";
state = ANOTHER;
} else {
theOutput = "You're supposed to say \"" +
clues[currentJoke] +
" who?\"" +
"! Try again. Knock! Knock!";
state = SENTKNOCKKNOCK;
}
} else if (state == ANOTHER) {
if (theInput.equalsIgnoreCase("y")) {
theOutput = "Knock! Knock!";
if (currentJoke == (NUMJOKES - 1))
130
currentJoke = 0;
else
currentJoke++;
state = SENTKNOCKKNOCK;
} else {
theOutput = "Bye.";
state = WAITING;
}
}
return theOutput;
}
}
The KnockKnockClient class implements the client program that speaks to the
KnockKnockServer. KnockKnockClient is based on the EchoClient program
in the previous section. We'll go over the program 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:
When creating its socket, KnockKnockClient uses the host name vanavil, 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 3333 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 a local port number (not port 3333) 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
131
the user types a carriage return, the client sends the text to the server through the output
stream attached to the socket.
The communication ends when the server asks if the client wishes to hear another joke,
the client says no, and the server says "Bye."
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();
import java.io.*;
import java.net.*;
try {
kkSocket = new Socket("campione", 4444);
out = new PrintWriter(kkSocket.getOutputStream(), true);
in = new BufferedReader(new
InputStreamReader(kkSocket.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:
taranis.");
System.exit(1);
}
String fromServer;
String fromUser;
fromUser = stdIn.readLine();
if (fromUser != null) {
System.out.println("Client: " + fromUser);
out.println(fromUser);
}
}
out.close();
in.close();
stdIn.close();
kkSocket.close();
}
}
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:
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 on 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:
133
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):
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:
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:
while (true) {
accept a connection ;
create a thread to deal with the client ;
end while
The thread reads from and writes to the client connection as necessary.
Java provides several useful classes for simplifying internet and socket
programming. These include InetAddress for obtaining IP addresses from domain names,
URL and URLConnection classes for communicating with web servers, and Socket and
ServerSocket classes for creating general client server programs.
6.9. REFERENCES
7.1. INTRODUCTION
RMI makes heavy use of interfaces. When you want to create a remote object,
you mask the underlying implementation by passing around an interface. Thus, when the
client gets a handle to a remote object, what they really get is an interface handle, which
happens to connect to some local stub code that talks across the network. But you don’t
think about this, you just send messages via your interface handle.
When you create a remote interface, you must follow these guidelines:
1. The remote interface must be public (it cannot have “package access,” that is, it
cannot be “friendly”). Otherwise, a client will get an error when attempting to
load a remote object that implements the remote interface.
2. The remote interface must extend the interface java.rmi.Remote.
137
You must explicitly define the constructor for the remote object even if you’re
only defining a default constructor that calls the base-class constructor. You must write it
out since it must throw RemoteException.
//: PerfectTime.java
// The implementation of the PerfectTime
// remote object
package c15.ptime;
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
import java.net.*;
Here, main( ) handles all the details of setting up the server. When you’re serving RMI
objects, at some point in your program you must:
1. Create and install a security manager that supports RMI. The only one available
for RMI as part of the Java distribution is RMISecurityManager.
2. Create one or more instances of a remote object. Here, you can see the creation of
the PerfectTime object.
3. Register at least one of the remote objects with the RMI remote object registry for
bootstrapping purposes. One remote object can have methods that produce
handles to other remote objects. This allows you to set it up so the client must go
to the registry only once, to
4. get the first remote object.
Here, you see a call to the static method Naming.bind( ). However, this call
requires that the registry be running as a separate process on the computer. The name of
the registry server is rmiregistry, and under 32-bit Windows you say:
start rmiregistry
rmiregistry &
or for Unix:
The information about the port must also be given to the bind( ) command, as
well as the IP address of the machine where the registry is located. But this brings up
what can be a frustrating problem if you’re expecting to test RMI programs locally the
way the network programs have been tested so far in this chapter.
The name for the service is arbitrary; it happens to be PerfectTime here, just like
the name of the class, but you could call it anything you want. The important thing is that
it’s a unique name in the registry that the client knows to look for to procure the remote
object. If the name is already in the registry, you’ll get an AlreadyBoundException. To
prevent this, you can always use rebind( ) instead of bind( ), since rebind( ) either adds
a new entry or replaces the one that’s already there.
Even though main( ) exits, your object has been created and registered so it’s kept
alive by the registry, waiting for a client to come along and request it. As long as the
rmiregistry is running and you don’t call Naming.unbind( ) on your name, the object
will be there. For this reason, when you’re developing your code you need to shut down
the rmiregistry and restart it when you compile a new version of your remote object.
You aren’t forced to start up rmiregistry as an external process. If you know that
your application is the only one that’s going to use the registry, you can start it up inside
your program with the line:
LocateRegistry.createRegistry(1785);
1785 is the port number we happen to be using in this example. This is the
equivalent of running rmiregistry 1785 from a command line, but it can often be more
convenient when you’re developing RMI code since it eliminates the extra steps of
starting and stopping the registry. Once you’ve executed this code, you can bind( ) using
Naming as before.
If you compile and run PerfectTime.java, it won’t work even if you have the
rmiregistry running correctly. That’s because the framework for RMI isn’t all there yet.
You must first create the stubs and skeletons that provide the network connection
operations and allow you to pretend that the remote object is just another local object on
your machine.
What’s going on behind the scenes is complex. Any objects that you pass into or
return from a remote object must implement Serializable (if you want to pass remote
140
references instead of the entire objects, the object arguments can implement Remote ),
so you can imagine that the stubs and skeletons are automatically performing serialization
and deserialization as they “marshal” all of the arguments across the network and return
the result. Fortunately, you don’t have to know any of this, but you do have to create the
stubs and skeletons. This is a simple process: you invoke the rmic tool on your compiled
code, and it creates the necessary files. So the only requirement is that another step be
added to your compilation process.
rmic c15.PTime.PerfectTime
When rmic runs successfully, you’ll have two new classes in the directory:
PerfectTime_Stub.class
PerfectTime_Skel.class
corresponding to the stub and skeleton. Now you’re ready to get the server and client to
talk to each other.
//: DisplayPerfectTime.java
// Uses remote object PerfectTime
package c15.ptime;
import java.rmi.*;
import java.rmi.registry.*;
t.getPerfectTime());
} catch(Exception e) {
e.printStackTrace();
}
}
} ///:~
The ID string is the same as the one used to register the object with Naming, and
the first part represents the URL and port number. Since you’re using a URL, you can
also specify a machine on the Internet.
What comes back from Naming.lookup( ) must be cast to the remote interface, not to the
class. If you use the class instead, you’ll get an exception.
t.getPerfectTime( )
that once you have a handle to the remote object, programming with it is
indistinguishable from programming with a local object (with one difference: remote
methods throw RemoteException).
There are a number of special concerns when running RMI with applets. Applets
have their own security manager since they run inside a browser. Thus, they do not use
the RMISecurityManager on the client side.
We must take care where to place the stub and server files. Consider a browser
that opens a web page with an APPLET tag. The browser loads the class file referenced in
the tag and all other class files as they are needed during execution. The classes are
loaded from the same hostthat contains the web page. Because of applet security
restrictions, the applet can make network connections only to its originating host.
Therefore, the server objects must reside on the same host as the web page. That is the
same server must store
Web pages
Applet code
Stub classes
Server objects
The RMI registry
Example 1
import java.rmi.*;
import java.awt.*;
public interface Product
extends Remote
{ String getDescription()
throws RemoteException;
Example 2
import java.rmi.*;
import java.util.*;
Example 3
import java.rmi.*;
import java.rmi.server.*;
import java.awt.*;
throws RemoteException
{ return "I am a " + name + ". Buy me!";
}
Example 4
import java.io.*;
return false;
}
Example 5
Import java.rmi.*;
import java.util.*;
public interface Warehouse
extends Remote
{ public Vector find(Customer c)
throws RemoteException;
}
Example 6
import java.rmi.*;
import java.util.*;
import java.rmi.server.*;
Example 7
import java.rmi.*;
import java.rmi.server.*;
145
System.out.println
("Binding server implementations to registry...");
Naming.rebind("central_warehouse", w);
System.out.println
("Waiting for invocations from clients...");
}
catch(Exception e)
{ System.out.println("Error: " + e);
}
}
Example 8
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
import javax.swing.*;
System.setSecurityManager(new RMISecurityManager());
try
{ Properties props = new Properties();
String fileName = "WarehouseClient.properties";
FileInputStream in = new FileInputStream(fileName);
props.load(in);
String url = props.getProperty("warehouse.url");
if (url == null)
url = "rmi://localhost/central_warehouse";
centralWarehouse = (Warehouse)Naming.lookup(url);
}
catch(Exception e)
{ System.out.println("Error: Can't connect to warehouse.
" + e);
}
}
getContentPane().setLayout(new GridBagLayout());
gbc.weighty = 100;
add(new JLabel("Hobbies"), gbc, 0, 2, 1, 1);
String[] choices = { "Gardening", "Beauty",
"Computers", "Household", "Sports" };
gbc.fill = GridBagConstraints.BOTH;
hobbies = new JList(choices);
add(new JScrollPane(hobbies), gbc, 1, 2, 1, 1);
gbc.weighty = 0;
gbc.fill = GridBagConstraints.NONE;
JButton submitButton = new JButton("Submit");
add(submitButton, gbc, 0, 3, 2, 1);
submitButton.addActionListener(this);
gbc.weighty = 100;
gbc.fill = GridBagConstraints.BOTH;
result = new JTextArea(4, 40);
148
result.setEditable(false);
add(result, gbc, 0, 4, 2, 1);
}
// RemoteInterface
import java.rmi.*;
import java.sql.*;
// Server Implementation
/*Note that the following program assumes that you have already
created a data source name called ContactsDB with user name as
‘user’ and passowrd as ‘user’. Also the DSN has a table called
CONT which has the following 4 fields:
NAME
ADDRESS
EMAIL
AGE
The name of the database used here was contacts.mdb (MS Access
was used)
*/
149
import java.rmi.*;
import java.rmi.server.*;
import java.io.*;
import java.sql.*;
ResultSet rs = smt.executeQuery(query);
while(rs.next()){
s[0] = rs.getString("NAME");
s[1] = rs.getString("ADDRESS");
s[2] = rs.getString("EMAIL");
s[3] = new
Integer(rs.getInt("AGE")).toString();
}
return s;
}
catch(Exception e)
{
e.printStackTrace();
System.out.println("Client request could not be
processed");
return null;
}
}
Naming.rebind("rmi://202.202.202.11/rmiindb",ms);
System.out.println("I am registered with RMI!
Please do not disturb me");
}
catch(Exception e){System.out.println(e);}
}//end of main
}
import java.sql.*;
import java.rmi.*;
}catch(Exception e){e.printStackTrace();}
}
/*
The output is
Name :Contact3
Address :Prince Pettai
email :itoodontknowmyname@yahoo.com
age :16
*/
151
Example 3 shows the implementation for the product service. Products store a
description, an age range, the gender targeted (male, female or both), and the matching
hobby. Note that this class implements the get Description method advertised in the
Product interface. The match method is an example of local method, a method that can
be called only from the program, not remotely. Since the match method is local, it need
not be prepared to throw a Remote Exception.
Example 4 contains the code for the Customer class-none of its methods can be
executed remotely. However the class is serializable. Therefore, objects of this class can
be transported from one machine to another.
Example 5 shows the implementation for the warehouse service. This class has
local and remote methods. The add; it is used by the server to add products to the
warehouse. The find method is remote; it is used to find items in the warehouse. The find
method is remote; it is used to find items in the warehouse.
To illustrate that the Costumer object is actually copied, the find method of the
warehouseImpl class clears the costumer object it receives. When the remote method
returns, the WarehouseClient displays the costumer object that it sent to the server. As
you will see, that object has not changed. The server cleared only its copy. In this case,
the clear operation serves no useful purpose except to demonstrate that local objects are
copied when they are passed as parameters.
Example 6 shows the server program that creates a warehouse object and
registers it with the bootstrap registry service.
Example 7 shows the code for the client. When the user clicks on the “Submit”
button, a new costumer object is generated and passed to the remote find method. Then,
the costumer record is displayed in the text area ( to prove that the clear call in the server
did not effect it ). Finally , the product descriptions of the return products in the vector
are added to the text area. Note that each getDescription is again a remote method
invocation.
152
In the above Lesson we discussed the need of distributed applications using RMI.
Usage of remote objects and object serialization has been discussed in detail
1) Write a remote method that computes weather a given year is leap year or not and
return just a boolean value. Write both client side and the server side programs as
well as the interfaces required.
2) Write two interfaces (Remote) and give one abstract methods each, and try to access
these methods. (e.g one interface could be taken from the previous example. The
other could be a method that returns a string say “hello world”?)
3) Write a RMI program that connects to the database server and retrievs some
information from the data base. (Please note the java.sql.ResultSet is not Serializable)
Execute those Examples given in this lesson and try to make some changes and
record the output
7.8. REFERENCES
8.1. INTRODUCTION
The characteristics alone do not describe an object completely. An object also has a
set of behaviors. At design-time, the behaviors of a visual component are partially
155
represented by events, meaning “Here’s something that can happen to the component.”
Ordinarily, you decide what you want to happen when an event occurs by tying code to
that event.
This is not all. The application builder tool is able to dynamically interrogate (using
reflection) the component to find out which properties and events the component
supports. Once it knows what they are, it can display the properties and allow you to
change those (saving the state when you build the program), and also display the events.
In general, you do something like double clicking on an event and the application builder
tool creates a code body and ties it to that particular event. All you have to do at that
point is write the code that executes when the event occurs.
All this adds up to a lot of work that’s done for you by the application builder tool.
As a result you can focus on what the program looks like and what it is supposed to do,
and rely on the application builder tool to manage the connection details for you. The
reason that visual programming tools have been so successful is that they dramatically
speed up the process of building an application – certainly the user interface, but often
other portions of the application as well.
Viewed subjectively, a component is after all really just a block of code, typically
embodied in a class. The key issue is the ability for the application builder tool to
discover the properties and events for that component. To create a VB component, the
programmer had to write a fairly complicated piece of code following certain conventions
to expose the properties and events. Delphi was a second-generation visual programming
tool and the language was actively designed around visual programming so it is much
easier to create a visual component. However, Java has brought the creation of visual
components to its most advanced state with Java Beans, because a Bean is just a class.
You don’t have to write any extra code or use special language extensions in order to
make something a Bean. The only thing you need to do, in fact, is slightly modify the
way that you name your methods. It is the method name that tells the application builder
tool whether this is a property, an event, or just an ordinary method.
The BeanBox
Making beans
Making beans requires just a naming convention and it’s fairly simple:
1. For a property named xxx, you typically create two methods: getXxx( ) and
setXxx( ). Note that the first letter after get or set is automatically lowercased to
produce the property name. The type produced by the “get” method is the same as the
type of the argument to the “set” method. The name of the property and the type for
the “get” and “set” are not related.
2. For a boolean property, you can use the “get” and “set” approach above, but you
can also use “is” instead of “get.”
3. Ordinary methods of the Bean don’t conform to the above naming convention, but
they’re public.
4. For events, you use the “listener” approach. It’s exactly the same as you’ve been
seeing: addFooBarListener(FooBarListener) and
removeFooBarListener(FooBarListener) to handle a FooBarEvent. Most of the
159
time the built-in events and listeners will satisfy your needs, but you can also create
your own events and listener interfaces.
Now you can see that most of those changes had to do with adapting to the “get”
and “set” naming conventions in order to make that particular component into a Bean.
We can use these guidelines to create a simple Bean:
Example1
import java.awt.*;
import java.io.*;
import javax.swing.*;
When you look at this code, notice that it really doesn’t look any different from
any other JAVA class. For example, all accessor methods begin with get; all mutator
programs begin with set. As we have seen earlier, builder tools use this standard
naming convention to discover properties. For example, fileName is a property of this
160
bean because it has get and set methods. In this particular example, the filename
property is stored in an instance variable that is also called filename. However, a
property doesn’t have to be stored in an instance variable- the get method can compute
it some other way.
Getting the Bean Information using the Introspector
One of the most critical parts of the Bean scheme occurs when you drag a
Bean off a palette and plop it down on a form. The application builder tool must be
able to create the Bean (which it can do if there’s a default constructor) and then,
without access to the Bean’s source code, extract all the necessary information to
create the property sheet and event handlers.
One good way to do this would be reflection, which allows all the methods of an
anonymous class to be discovered. This is perfect for solving the Bean problem
without requiring you to use any extra language keywords like those required in other
visual programming languages. In fact, one of the prime reasons that reflection was
added to Java 1.1 was to support Beans (although reflection also supports object
serialization and remote method invocation). So you might expect that the creator of
the application builder tool would have to reflect each Bean and hunt through its
methods to find the properties and events for that Bean.
This is certainly possible, but the Java designers wanted to provide a standard
interface for everyone to use, not only to make Beans simpler to use but also to
provide a standard gateway to the creation of more complex Beans. This interface is
the Introspector class, and the most important method in this class is the static
getBeanInfo( ). You pass a Class handle to this method and it fully interrogates that
class and returns a BeanInfo object that you can then dissect to find properties,
methods, and events.
The example given below shows how we can get a bean’s properties using bean
descriptor.
import java.beans.*;
import java.lang.reflect.*;
PropertyDescriptor[] properties =
bi.getPropertyDescriptors();
for(int i = 0; i < properties.length; i++)
{
Class p = properties[i].getPropertyType();
System.out.println("Property type:\n " +
p.getName());
System.out.println("Property name:\n " +
Method readMethod =
properties[i].getReadMethod();
if(readMethod != null)
System.out.println("Read method:\n " +
readMethod.toString());
Method writeMethod =
properties[i].getWriteMethod();
if(writeMethod != null)
System.out.println("Write method:\n " +
writeMethod.toString());
System.out.println("====================");
}
System.out.println("Public methods:");
MethodDescriptor[] methods =bi.getMethodDescriptors();
for(int i = 0; i < methods.length; i++)
System.out.println(methods[i].getMethod().toString());
System.out.println("======================");
System.out.println("Event support:");
EventSetDescriptor[] events =
bi.getEventSetDescriptors();
for(int i = 0; i < events.length; i++) {
System.out.println("Listener type: " +
events[i].getListenerType().getName());
Method[] lm = events[i].getListenerMethods();
for(int j = 0; j < lm.length; j++)
System.out.println("Listener method:\n "
+lm[j].getName());
MethodDescriptor[] lmd =
events[i].getListenerMethodDescriptors();
for(int j = 0; j < lmd.length; j++)
System.out.println("Method descriptor:\n " +
lmd[j].getMethod().toString());
Method addListener = events[i].getAddListenerMethod();
System.out.println("Add Listener Method:\n " +
addListener.toString());
Method removeListener =
events[i].getRemoveListenerMethod();
System.out.println("Remove Listener Method:\n "
+removeListener.toString());
System.out.println("====================");
}
BeanDumper.dump( ) is the method that does all the work. First it tries to create
a BeanInfo object, and if successful calls the methods of BeanInfo that produce
information about properties, methods, and events. In Introspector.getBeanInfo( ),
you’ll see there is a second argument. This tells the Introspector where to stop in the
inheritance hierarchy. Here, it stops before it parses all the methods from Object,
since we’re not interested in seeing those.
This next example is slightly more sophisticated, albeit frivolous. It’s a canvas
that draws a little circle around the mouse whenever the mouse is moved. When you
press the mouse, the word “Bang!” appears in the middle of the screen, and an action
listener is fired.
163
The properties you can change are the size of the circle as well as the color, size,
and text of the word that is displayed when you press the mouse. A BangBean also
has its own addActionListener( ) and removeActionListener( ) so you can attach
your own listener that will be fired when the user clicks on the BangBean. You should
be able to recognize the property and event support:
Example 2
package bangbean;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
}
public void removeActionListener(
ActionListener l) {
actionListener = null;
}
class ML extends MouseAdapter {
public void mousePressed(MouseEvent e) {
Graphics g = getGraphics();
g.setColor(tColor);
g.setFont(
new Font(
"TimesRoman", Font.BOLD, fontSize));
int width =
g.getFontMetrics().stringWidth(text);
g.drawString(text,
(getSize().width - width) /2,
getSize().height/2);
g.dispose();
// Call the listener's method:
if(actionListener != null)
actionListener.actionPerformed(
new ActionEvent(BangBean.this,
ActionEvent.ACTION_PERFORMED, null));
}
}
class MML extends MouseMotionAdapter {
public void mouseMoved(MouseEvent e) {
xm = e.getX();
ym = e.getY();
repaint();
}
}
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
// Testing the BangBean:
public static void main(String[] args) {
BangBean bb = new BangBean();
try {
bb.addActionListener(new BBL());
} catch(TooManyListenersException e) {}
Frame aFrame = new Frame("BangBean Test");
aFrame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
aFrame.add(bb, BorderLayout.CENTER);
aFrame.setSize(300,300);
aFrame.setVisible(true);
}
// During testing, send action information
// to the console:
static class BBL implements ActionListener {
public void actionPerformed(ActionEvent e) {
165
System.out.println("BangBean action");
}
}
}
The first thing you’ll notice is that BangBean implements the Serializable interface.
This means that the application builder tool can “pickle” all the information for the
BangBean using serialization after the program designer has adjusted the values of the
properties. When the Bean is created as part of the running application, these
“pickled” properties are restored so that you get exactly what you designed.
You can see that all the fields are private, which is what you’ll usually do with a
Bean – allow access only through methods, usually using the “property” scheme.
When you press the mouse, the text is put in the middle of the BangBean, and if
the actionListener field is not null, its actionPerformed( ) is called, creating a new
ActionEvent object in the process. Whenever the mouse is moved, its new
coordinates are captured and the canvas is repainted (erasing any text that’s on the
canvas, as you’ll see).
The main( ) is added to allow you to test the program from the command line.
When a Bean is in a development environment, main( ) will not be used, but it’s
helpful to have a main( ) in each of your Beans because it provides for rapid testing.
main( ) creates a Frame and places a BangBean within it, attaching a simple
ActionListener to the BangBean to print to the console whenever an ActionEvent
occurs. Usually, of course, the application builder tool would create most of the code
that uses the Bean.
When you run the BangBean through BeanDumper or put the BangBean inside a
Bean-enabled development environment, you’ll notice that there are many more
properties and actions than are evident from the above code. That’s because
BangBean is inherited from Canvas, and Canvas is a Bean, so you’re seeing its
properties and events as well.
Manifest-Version: 1.0
Name: bangbean/BangBean.class
Java-Bean: True
166
The first line indicates the version of the manifest scheme, which until further notice
from Sun is 1.0. The second line (empty lines are ignored) names the BangBean.class
file, and the third says, “It’s a Bean.” Without the third line, the program builder tool will
not recognize the class as a Bean.
The only tricky part is that you must make sure that you get the proper path in the
“Name:” field. If you look back at BangBean.java, you’ll see it’s in package bangbean
(and thus in a subdirectory called “bangbean” that’s off of the classpath), and the name in
the manifest file must include this package information. In addition, you must place the
manifest file in the directory above the root of your package path, which in this case
means placing the file in the directory above the “bangbean” subdirectory. Then you must
invoke jar from the same directory as the manifest file, as follows:
jar cfm BangBean.jar BangBean.mf bangbean
This assumes that you want the resulting JAR file to be named BangBean.jar and
that you’ve put the manifest in a file called BangBean.mf.
You might wonder “What about all the other classes that were generated when I compiled
BangBean.java?” Well, they all ended up inside the bangbean subdirectory, and you’ll
see that the last argument for the above jar command line is the bangbean subdirectory.
When you give jar the name of a subdirectory, it packages that entire subdirectory into
the jar file (including, in this case, the original BangBean.java source-code file – you
might not choose to include the source with your own Beans). In addition, if you turn
around and unpack the JAR file you’ve just created, you’ll discover that your manifest
file isn’t inside, but that jar has created its own manifest file (based partly on yours)
called MANIFEST.MF and placed it inside the subdirectory META-INF (for “meta-
information”). If you open this manifest file you’ll also notice that digital signature
information has been added by jar for each file, of the form:
In general, you don’t need to worry about any of this, and if you make changes you
can just modify your original manifest file and re-invoke jar to create a new JAR file for
your Bean. You can also add other Beans to the JAR file simply by adding their
information to your manifest.
One thing to notice is that you’ll probably want to put each Bean in its own
subdirectory, since when you create a JAR file you hand the jar utility the name of a
subdirectory and it puts everything in that subdirectory into the JAR file. Once you have
your Bean properly inside a JAR file you can bring it into a Beans-enabled program-
builder environment. The way you do this varies from one tool to the next, but Sun
provides a freely-available test bed for Java Beans in their “Beans Development Kit”
(BDK) called the “beanbox.”. To place your Bean in the beanbox, copy the JAR file into
167
So it would be instructive to see where a bean can get complicated. One place where
you can add sophistication is with properties. The examples above have shown only
single properties, but it’s also possible to represent multiple properties in an array. This is
called an indexed property . You simply provide the appropriate methods (again
following a naming convention for the method names) and the Introspector recognizes
an indexed property so your application builder tool can respond appropriately.
Properties can be bound, which means that they will notify other objects via a
PropertyChangeEvent. The other objects can then choose to change themselves based
on the change to the Bean.
Properties can be constrained, which means that other objects can veto a change to
that property if it is unacceptable. The other objects are notified using a
PropertyChangeEvent, and they can throw a ProptertyVetoException to prevent the
change from happening and to restore the old values.
You can also change the way your Bean is represented at design time:
1. You can provide a custom property sheet for your particular Bean. The ordinary
property sheet will be used for all other Beans, but yours is automatically invoked when
your Bean is selected.
2. You can create a custom editor for a particular property, so the ordinary property
sheet is used, but when your special property is being edited, your editor will
automatically be invoked.
3. You can provide a custom BeanInfo class for your Bean that produces information
that’s different from the default created by the Introspector.
4. It’s also possible to turn “expert” mode on and off in all FeatureDescriptors to
distinguish between basic features and more complicated ones.
persistence that enables the state of components to be stored in a non-volatile place for
later retrieval.
8.4.1. Object serialization
Serialization is a process of reading or writing an object. It is a process of saving an
object’s state to a sequence of bytes, as well as a process of rebuilding those bytes back
into a live object at some future time. An object is marked serializable by implementing
the java.io.Serializable interface, which is only a marker interface—it simply allows the
serialization mechanism to verify that the class can be persisted.
Serialization has a number of advantages. It provides:
}
Serialization has the disadvantage that because the encoding of the data is serial, merely
extracting one part of the data structure that is serialized means that the entire object must
be reconstructed or read before this can be done.
8.4.2. Serialization
The mechanism that makes persistence possible is called serialization. Object
serialization means converting an object into a data stream and writing it to storage. Any
169
applet, application, or tool that uses that bean can then "reconstitute" it by deserialization.
The object is then restored to its original state.
For example, a Java application can serialize a Frame window on a Microsoft Windows
machine, the serialized file can be sent with e-mail to a Solaris machine, and then a Java
application can restore the Frame window to the exact state which existed on the
Microsoft Windows machine.
Any applet, application, or tool that uses that bean can then "reconstitute" it by
deserialization.
All beans must persist. To persist, your beans must support serialization by implementing
either the java.io.Serializable(in the API reference documentation) interface, or the
java.io.Externalizable(in the API reference documentation) interface. These
interfaces offer you the choices of automatic serialization and customized serialization. If
any class in a class's inheritance hierarchy implements Serializable or
Externalizable, then that class is serializable.
8.4.3. Classes that are Serializable
Any class is serializable as long as that class or a parent class implements the
java.io.Serializable interface. Examples of serializable classes include
Component, String, Date, Vector, and Hashtable. Thus, any subclass of the
Component class, including Applet, can be serialized. Notable classes not supporting
serialization include Image, Thread, Socket, and InputStream. Attempting to
serialize objects of these types will result in an NotSerializableException.
The Java Object Serialization API automatically serializes most fields of a Serializable
object to the storage stream. This includes primitive types, arrays,and strings. The API
does not serialize or deserialize fields that are marked transient or static.
8.4.4. Controlling Serialization
You can control the level of serialization that your beans undergo. Three ways
to control serilization are:
made sure your class will work with default serialization. Here are some important points
about working with the Serializable interface:
encoder.writeObject( object );
encoder.close();
The XMLDecoder class reads an XML document that was created with XMLEncoder:
XMLDecoder decoder = new XMLDecoder(
new BufferedInputStream(
new FileInputStream( "Beanarchive.xml" )
) );
<object class="javax.swing.JButton"
method="new">
<string>Ok</string>
</object>
or statements
<object class="javax.swing.JButton">
<void method="setText">
<string>Cancel</string>
</void>
</object>
The following code represents an XML archive that will be generated for the
SimpleBean component:
<?xml version="1.0" encoding="UTF-8" ?>
<java>
<object class="javax.swing.JFrame">
<void method="add">
<object class="java.awt.BorderLayout" field="CENTER"/>
<object class="SimpleBean"/>
</void>
<void property="defaultCloseOperation">
<object class="javax.swing.WindowConstants"
field="DISPOSE_ON_CLOSE"/>
</void>
<void method="pack"/>
<void property="visible">
<boolean>true</boolean>
</void>
173
</object>
</java>
2. Write a bean to implement a password field. The letters typed must not be
displayed. Instead * must be displayed.
3. Write a bean to implement a clock component. The component can inherit from
either a tect field or a label. It must display the time at every instant [ Hint : Make
use of threading concept for keeping time.
5. Convert the graphical user interface for calculator, created in the chapter on
Swing into a bean.
BeanInfo
Bean
Properties
Methods
174
Event Sources
Solution:
Java code should be made that implements object methods to actual SQL statements
however there is several already usable Persistence libraries. One is WebApp Framework
created by Peter Roßbach and Hendrik Schreiber. This library is has very high
performance and features but with high cost. Another is included in Oracle distribution
named Business Object for Java. This library is huge with lot of features, but
unfortunately this library has little performance and errors. But it is easy and not requires
mach of effort to implement such library, what is done with help of people in my
previous projects. Persistence library named INetForms originally meant to be for
MySQL database, but later expanded with support for Oracle and functionality not
related to persistence.
8.10. REFERENCES
Jane Jawroski, “Java Unleashed”, SAMS Techmedia Publications, 1999
Campione, Walrath and Huml, “The Java Tutorial”, Addison Wesley 1999
http://java.sun.com/docs/books/tutorial/javabeans/whatis/index.html
175
Understand JDBC
Architecture of JDBC
SQL commands in JDBC
9.1. INTRODUCTION
In the summer of 1996,Sun released the first version of the JDBC (Java database
connectivity) kit. This package lets the user connect to a database, query it, or update it,
using SQL (Structured query language). This is one of the most important developments
in programming for JAVA platform. It is not just that databases are among the most
common use of hardware and software today. The more important reason that Java and
JDBC have an essential advantage over other database programming environments is
this:
Programs developed with the JAVA programming language and JDBC are
platform independent and vendor independent.
In the two-tier model, a Java applet or application talks directly to the data source. This
requires a JDBC driver that can communicate with the particular data source being
accessed. A user's 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 user's 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 three-tier 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.
177
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
that translate Java bytecode into efficient machine-specific code and technologies such as
Enterprise JavaBeans™, the Java platform is fast becoming the standard platform for
middle-tier development. This is a big plus, making it possible to take advantage of Java's
robustness, multithreading, and security features.
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-tier
architecture. Some of the features 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.
What all the database vendors and tool vendors did agree on was that it would be
useful if Sun provided a pure Java API for SQL access along with a driver manager to
allow third-party drivers to connect to specific database. database vendors could provide
their own drivers to plug into the driver manager. There would then be a simple
mechanism for registering third-party drivers with the driver manager-the point being that
all the drivers needed to do was follow the requirements laid out in the driver manager
API.
178
After a fairly long period of public discussion, the API or database access became
the JDBC API, and the rules for writing drivers were encapsulated in the JDBC driver
API. (the JDBC driver API is of interest only to database vendors and database tool
providers; we don’t cover it here.)
This protocol follows the very successful model of Microsoft’s ODBC, which
provided a C programming language interface for database access. Both JDBC and
ODBC are based on the same idea: Programs written according to the JDBC API would
talk to the JDBC driver manager, which, in turn, would use the drivers that were plugged
into it at that moment to talk to the actual database.
ODBC Vendor-
driver Supplied Database
Database
JDBC driver
More precisely, the JDBC consists of three layers. The top layer is the JDBC
API. This API communicates with the JDBC manager driver API, sending it the various
SQL statements. The manager should (transparently to the programmer) communicate
with the various third-party drivers that actually connect to the database and return the
information from the query or perform the action specified by the query.
All this means the Java/JDBC layer is all that most programmers will ever have to deal
with.
Most database vendors supply either a type 3 or a type 4 driver with their
database. Furthermore, a number of third party companies specialize in producing drivers
with better standards conformance, support for more platforms, or in some cases, simply
better reliability than the drivers that are provided by database vendors.
One of the most important steps in the design of a database program, is that of
establishing connectivity between the front end and the back end. Here the front end is
JAVA. The back end can be SQL Server, Oracle, Access, FoxPro or any other such
database manipulation language. This consists of a set of routine steps that are same for
all programs. Nevertheless, it will be worth wile to study, in detail, the steps involved and
the significance of each step, in order to get a better insight about how JDBC actually
works.
a physical directory where the database tables are located. For your database
identifier to have any meaning, you must register the name using your database
administration software. (The process of registration varies from platform to
platform.)
All this information is combined into one string, the “database URL.” For
example, to connect through the ODBC subprotocol to a database identified as “people,”
the database URL could be:
If you’re connecting across a network, the database URL will also contain the
information identifying the remote machine.
When you’re ready to connect to the database, you call the static method
DriverManager.getConnection( ), passing it the database URL, the user name, and a
password to get into the database. You get back a Connection object that you can then
use to query and manipulate the database.
The following example opens a database of contact information and looks for a
person’s last name as given on the command line. It selects only the names of people that
have email addresses, then prints out all the ones that match the given last name:
//: Lookup.java
// Looks up email addresses in a
// local database using JDBC
import java.sql.*;
while(r.next())
{
181
You can see the creation of the database URL as previously described. In this
example, there is no password protection on the database so the user name and password
are empty strings.
The executeQuery( ) method returns a ResultSet object, which is quite a bit like
an iterator: the next( ) method moves the iterator to the next record in the statement, or
returns null if the end of the result set has been reached. You’ll always get a ResultSet
object back from executeQuery( ) even if a query results in an empty set (that is, an
exception is not thrown). Note that you must call next( ) once before trying to read any
record data. If the result set is empty, this first call to next( ) will return false. For each
record in the result set, you can select the fields using (among other approaches) the field
name as a string. Also note that the capitalization of the field name is ignored – it doesn’t
matter with an SQL database. You determine the type you’ll get back by calling getInt( ),
getString( ), getFloat( ), etc. At this point, you’ve got your database data in Java native
format and can do whatever you want with it using ordinary Java code.
With JDBC, understanding the code is relatively simple. The confusing part is
making it work on your particular system. The reason this is confusing is that it requires
you to figure out how to get your JDBC driver to load properly, and how to set up a
database using your database administration software.
Of course, this process can vary radically from machine to machine, but the
process I used to make it work under 32-bit Windows might give you clues to help you
attack your own situation.
182
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
If the load statement is wrong, you’ll get an exception at this point. To test
whether your driver load statement is working correctly, comment out the code after the
statement and up to the catch clause; if the program throws no exceptions it means that
the driver is loading properly.
Again, this is specific to 32-bit Windows; you might need to do some research to
figure it out for your own platform.
First, open the control panel. You might find two icons that say “ODBC.” You
must use the one that says “32bit ODBC,” since the other one is for backwards
compatibility with 16-bit ODBC software and will produce no results for JDBC. When
you open the “32bit ODBC” icon, you’ll see a tabbed dialog with a number of tabs,
including “User DSN,” “System DSN,” “File DSN,” etc., in which “DSN” means “Data
Source Name.” It turns out that for the JDBC-ODBC bridge, the only place where it’s
important to set up your database is “System DSN,” but you’ll also want to test your
configuration and create queries, and for that you’ll also need to set up your database in
“File DSN.” This will allow the Microsoft Query tool (that comes with Microsoft Office)
to find the database. Note that other query tools are also available from other vendors.
The most interesting database is one that you’re already using. Standard ODBC
supports a number of different file formats including such venerable workhorses as
DBase. However, it also includes the simple “comma-separated ASCII” format, which
virtually every data tool has the ability to write. In my case, I just took my “people”
database that I’ve been maintaining for years using various contact-management tools
and exported it as a comma-separated ASCII file (these typically have an extension of
.csv). In the “File DSN” section I chose “Add,” chose the text driver to handle my
183
comma-separated ASCII file, and then un-checked “use current directory” to allow me to
specify the directory where I exported the data file.
You’ll notice when you do this that you don’t actually specify a file, only a
directory. That’s because a database is typically represented as a collection of files under
a single directory (although it could be represented in other forms as well). Each file
usually contains a single table, and the SQL statements can produce results that are culled
from multiple tables in the database (this is called a join). A database that contains only a
single table (like this one) is usually called a flat-file database . Most problems that go
beyond the simple storage and retrieval of data generally require multiple tables that must
be related by joins to produce the desired results, and these are called relational
databases.
To test the configuration you’ll need a way to discover whether the database is
visible from a program that queries it. Of course, you can simply run the JDBC program
example above up to and including the statement:
Once we’ve done this, we will see that your database is available when you create
a new query using your query tool.
We’ll write a query that would search for records that had the last name that was
typed on the command line when starting the Java program. So as a starting point, we’ll
search for a specific last name, ‘Shankar’. We’ll also try to display only those names that
had email addresses associated with them. The steps to create this query are:
1. Start a new query and use the Query Wizard. Select the “people” database. (This
is the equivalent of opening the database connection using the appropriate
database URL.)
2. Select the “people” table within the database. From within the table, choose the
columns FIRST, LAST, and EMAIL.
184
3. Under “Filter Data,” choose LAST and select “equals” with an argument of
Shankar. Click the “And” radio button.
4. Choose EMAIL and select “Is not Null.”
5. Under “Sort By,” choose FIRST.
The result of this query will show you whether you’re getting what you want. Now you
can press the SQL button and without any research on your part, up will pop the correct
SQL code, ready for you to cut and paste. For this query, it would look like this:
SELECT people.FIRST, people.LAST, people.EMAIL
FROM people.csv people
WHERE (people.LAST='Shankar') AND
(people.EMAIL Is Not Null)
ORDER BY people.FIRST
With more complicated queries it’s easy to get things wrong, but with a query tool
you can interactively test your queries and automatically generate the correct code. It’s
hard to argue the case for doing this by hand.
You’ll notice that the code above looks different from what’s used in the program.
That’s because the query tool uses full qualification for all of the names, even when
there’s only one table involved. (When more than one table is involved, the qualification
prevents collisions between columns from different tables that have the same names.)
Since this query involves only one table, you can optionally remove the “people”
qualifier from most of the names, like this:
In addition, you don’t want this program to be hard coded to look for only one
name. Instead, it should hunt for the name given as the command-line argument. Making
these changes and turning the SQL statement into a dynamically-created String
produces:
SQL has another way to insert names into a query called stored procedures , which is
used for speed. But for much of your database experimentation and for your first cut,
building your own query strings in Java is fine.
You can see from this example that by using the tools currently available – in particular
the query-building tool – database programming with SQL and JDBC can be quite
straightforward.
The SQL statements can be classified broadly into three types, namely :-
Data retrieval
Data manipulation language
Data definition language
We shall deal with the most commonly used statements, belonging to each one of these
three types.
Data retrieval:
These statements are generally known as queries. They start with the word select. The
syntax is as follows
‘column_name’ refers to the columns of the table, whose data we desire to see
‘table_name’ is the table from which we want data
‘condition(s)’ refers to the conditions we may set to restrict the records retrieved
The result of this query will be obtained by assigning it to a ResultSet, about which we
dealt in the previous section. From the ResultSet, we can recover the required data in
appropriate form.
186
Data manipulation:
Insertion, updating and deletion are the operations carried out by data manipulation
language. The syntax of each of them is given below.
UPDATE table_name
SET column_name = VALUE [, column = value]
[WHERE condition]
Here also the notations are almost similar to the last case. The notation value refers to the
value will be setting to the fields in the record we are inserting or updating.
Data definition:
These statements help in creating, deleting or renaming a table during runtime. They also
help in modifying a table. The syntaxes of some of these statements are given below.
Here also ‘column’ and ‘datatype’ mean the same as in earlier cases. ‘datatype’ refers to
the datatype of the column in the table. ‘expr’ refers to the expression that will be used to
compute default values for a column, in case values are not set for that particular field.
Application of JDBC:
Usually JDBC is useful in creating user friendly applications with a graphical user interface. To do this, it is used along with Swing
features to make some applications that require access to a database. Here we shall see a few simple examples, in which the JDBC
concepts are made use of.
Populating a database:
187
The first thing we must have, in order to write a JDBC program is a database. So
we shall first write a program for creating a database. Then we shall write other programs
that run using this database that we create. Here data is provided to the program as text
files. It is very easy to create these text files. The format in which the data must exist in
the text file will be given. So one can use his own set of data and make these text files.
Four text files have to be made. The first file is “authors” . The fields in it are Author_Id
char(4), Name char(25), URL char(80).Let this be the first line in the text file. The
program turns the first line into a CREATE TABLE statement such as CREATE
TABLE Authors(Author_Id char(4), Name char(25), URL char(80)).The data starts from
the next line onwards. Here is a sample data
“ 'ARON', 'Aronson, Larry', 'www.interport.net/~laronson/Homepage.html' “
Data, in similar form should be given, one set of data on each line.
Similarly, we have “Books” with fields “Title char(60), ISBN char(13), Publisher_Id
char(5), URL char(80), Price double ”, ”BooksAuthors” with fields “ISBN char(13),
Author_Id char(4), Seq_No int”, “Publishers” with fields Publisher_Id char(5), Name
char(30), URL char(80).
The program will turn all the lines of the text files, excepting the first line into statements,
such as Insert into Publishers values('01262', 'Academic Press', 'www.apnet.com/'). We
have to run the program as follows to create tables from each of the above mentioned text
files.
There is one more thing to be done for making the program run. There has to be a file
MakeDb.properties that looks like this jdbc.drivers=com.pointbase.jdbc.jdbcDriver
jdbc.url=jdbc:pointbase:corejava
jdbc.username=PUBLIC
jdbc.password=PUBLIC
These values work for PointBase database. They must be changed if some other database
is being used.
driver. The getConnection method uses the jdbc.url, jdbc.username, and the
jdbc.password properties to open the database connection.
2. Obtain the filename from the table name by appending the extension .dat
3. Read in the column names and types and construct a CREATE TABLE
command. Then execute that command:
String line = in.readLine();
String command = "CREATE TABLE " + tableName
+ "(" + line + ")";
stmt.executeUpdate(command);
Here we use executeUpdate, not execute query, because this statement has no
result.
4. For each line in the input file, execute an INSERT statement:
command = "INSERT INTO " + tableName
+ " VALUES (" + line + ")";
stmt.executeUpdate(command);
5. After all these elements have been inserted, run a SELECT * FROM table
name query, using the show table method to show the result. This method shows
that the data has been successfully inserted. To find the number of columns in the
result set, we need the get column count method of the result set metadata class.
import java.net.*;
import java.sql.*;
import java.io.*;
import java.util.*;
in.close();
stmt.close();
con.close();
}catch (SQLException ex)
{
System.out.println ("SQLException:");
while (ex != null)
{
System.out.println ("SQLState: "+
ex.getSQLState());
System.out.println ("Message: "+
ex.getMessage());
System.out.println ("Vendor: "+
ex.getErrorCode());
ex = ex.getNextException();
System.out.println ("");
}
}
catch (IOException ex)
{
System.out.println("Exception: " + ex);
ex.printStackTrace ();
}
} //end of main
{
String line = in.readLine();
String command = "CREATE TABLE " + tableName
+ "(" + line + ")";
stmt.executeUpdate(command);
190
while (rs.next())
{
for (int i = 1; i <= columnCount; i++)
{
if (i > 1) System.out.print(", ");
System.out.print(rs.getString(i));
}
System.out.println();
}
rs.close();
}
We shall now have a look at a program that executes queries against the database we
created in the preceding section. A graphical user interface has been implemented using
Swing. The application consists of two combo boxes, two buttons, a text field and a text
box. One combo box contains the names of the authors and another one contains the
name of the books. The two buttons are ‘Query’ and ‘Change Price’. The user can choose
an author from the combo box and choose any in publisher. Then if he presses the query
button, the names of all books published by the author are displayed in the text box. On
the converse, if he chooses a publisher and choose any for author, all books published by
him will be displayed. There is one more thing, which the user can do. He can type the
name of a book in the text box and the change in its price in the text field. Then, if he
presses the ‘Change Price’ button, the price of the book gets changed by the amount
191
entered, in the database. Thus, in this program, we perform both data retrieval and data
updation.
1. Arrange the components in the frame, using a grid bag lay out.
2. Populate the author and publisher textboxes by running two queries that
return all author and publisher name in the database.
3. When the user selects “query”, find which of the four query types need to be
executed. If this is the first time this query type is executed, then the prepared
statement is null, and the prepared statement is constructed. Then, the values
are bound to the query and the query is executed.
4. The results of the query are displayed in the result textbox.
5. When the user selects “change price”, then the update query is constructed
and executed. The query is quite complex because the where clause of the
update statement needs the publisher code and we need know only the
publisher name. This problem is solved with a nested subquery:
UPDATE Books " +
"SET Price = Price + " + priceChange.getText() +
" WHERE Books.Publisher_Id = " +
"(SELECT Publisher_Id FROM Publishers WHERE Name = '" +
publisher + "')
6. We initialize the connection and statement objects in the constructer. We
hang on to them for the life of the program. Just before the program exits, we
call the dispose method and these objects are closed.
getContentPane().setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
authors.addItem("Any");
publishers = new JComboBox();
publishers.setEditable(false);
publishers.addItem("Any");
result = new JTextArea(4, 50);
result.setEditable(false);
try
{
con = getConnection();
stmt = con.createStatement();
catch(Exception e)
{
result.setText("Error " + e);
}
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 100;
gbc.weighty = 100;
add(authors, gbc, 0, 0, 2, 1);
gbc.fill = GridBagConstraints.NONE;
JButton queryButton = new JButton("Query");
queryButton.addActionListener(this);
add(queryButton, gbc, 0, 1, 1, 1);
gbc.fill = GridBagConstraints.HORIZONTAL;
add(priceChange, gbc, 3, 1, 1, 1);
gbc.fill = GridBagConstraints.BOTH;
add(result, gbc, 0, 2, 4, 1);
}
returnDriverManager.getConnection(url, username,
password);
}
private void add(Component c, GridBagConstraints gbc,int x, int
y, int w, int h)
{
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = w;
gbc.gridheight = h;
getContentPane().add(c, gbc);
}
public void actionPerformed(ActionEvent evt)
{
String arg = evt.getActionCommand();
if (arg.equals("Query"))
{
ResultSet rs = null;
try
{
String author=
(String)authors.getSelectedItem();
194
String publisher=
(String)publishers.getSelectedItem();
if (!author.equals("Any")&&
!publisher.equals("Any"))
{
if (authorPublisherQueryStmt == null)
{
String authorPublisherQuery =
"SELECT Books.Price, Books.Title "
+
"FROM Books, BooksAuthors,
Authors, Publishers " +
"WHERE Authors.Author_Id =
BooksAuthors.Author_Id AND " +
"BooksAuthors.ISBN = Books.ISBN
AND " +
"Books.Publisher_Id =
Publishers.Publisher_Id AND " +
"Authors.Name = ? AND " +
"Publishers.Name = ?";
authorPublisherQueryStmt
=
con.prepareStatement(authorPublisherQuery);
}
authorPublisherQueryStmt.setString(1,
author);
authorPublisherQueryStmt.setString(2,publisher);
rs =
authorPublisherQueryStmt.executeQuery();
}
else if (!author.equals("Any")&&
publisher.equals("Any"))
{
if (authorQueryStmt == null)
{
String authorQuery =
"SELECT Books.Price, Books.Title "
+
"FROM Books, BooksAuthors, Authors
" +
"WHERE Authors.Author_Id =
BooksAuthors.Author_Id AND " +
"BooksAuthors.ISBN = Books.ISBN
AND " +
"Authors.Name = ?";
authorQueryStmt=
con.prepareStatement(authorQuery);
}
authorQueryStmt.setString(1, author);
rs = authorQueryStmt.executeQuery();
195
else if (author.equals("Any")&&
!publisher.equals("Any"))
{
if (publisherQueryStmt == null)
{
String publisherQuery =
"SELECT Books.Price, Books.Title "
+
"FROM Books, Publishers " +
"WHERE Books.Publisher_Id =
Publishers.Publisher_Id AND " +
"Publishers.Name = ?";
publisherQueryStmt=
con.prepareStatement(publisherQuery);
publisherQueryStmt.setString(1,
publisher);
rs = publisherQueryStmt.executeQuery();
}
else
{
if (allQueryStmt == null)
{
String allQuery ="SELECT
Books.Price, Books.Title FROM Books";
allQueryStmt=
con.prepareStatement(allQuery);
}
rs = allQueryStmt.executeQuery();
}
result.setText("");
while (rs.next())
result.append(rs.getString(1)
+ " | " + rs.getString(2) + "\n");
rs.close();
catch(Exception e)
{
result.setText("Error " + e);
}
}
else if (arg.equals("Change prices"))
{
String publisher=
(String)publishers.getSelectedItem();
if (publisher.equals("Any"))
196
}
public void dispose()
{
try
{
stmt.close();
con.close();
}
catch(SQLException e) {}
}
}
The above examples would be sufficient to give one a decent exposure to JDBC. If one is
interested in knowing more, lot of books are available, dealing entirely with SQL only.
There are also a number of good books dealing with the RDBMS (Relational database
management systems) concepts. It would be highly enriching to read them. But for day
today database application programming using JAVA, the concepts covered in the above
section would suffice.
In this section will discuss about various elements found in applet code that are not
present in standalone application code. Some of these elements involve advanced aspects
of the Java programming language. This section will give some rationale and some basic
explanation, but explaining them fully is beyond the scope of this Lesson. For purposes
of this sample applet, you only need to grasp the general idea, so don't worry if you don't
197
understand everything. You can use the applet code as a template, substituting your own
queries for the one in the applet.
To begin with, applets will import classes not used by standalone applications. Our applet
imports two classes that are special to applets: the class Applet , which is part of the
java.applet package, and the class Graphics , which is part of the java.awt package.
This applet also imports the general-purpose class java.util.Vector so that we have
access to an array-like container whose size can be modified. This code uses Vector
objects to store query results so that they can be displayed later.
All applets extend the Applet class; that is, they are subclasses of Applet. Therefore,
every applet definition must contain the words extends Applet, as shown here:
In our applet example, OutputApplet, this line also includes the words implements
Runnable, so it looks like this:
Runnable is an interface that makes it possible to run more than one thread at a time. A
thread is a sequential flow of control, and it is possible for a program to be multithreaded,
that is, to have many threads doing different things concurrently. The class
OutputApplet implements the interface Runnable by defining the method run, the only
method in Runnable. In our example the run method contains the JDBC code for
opening a connection, executing a query, and getting the results from the result set. Since
database connections can be slow, and can sometimes take several seconds, it is generally
a good idea to structure an applet so that it can handle the database work in a separate
thread.
Similar to a standalone application, which must have a main method, an applet must
implement at least one init, start, or paint method. Our example applet defines a
start method and a paint method. Every time start is invoked, it creates a new thread
(named worker) to re-evaluate the database query. Every time paint is invoked, it
displays either the query results or a string describing the current status of the applet.
As stated previously, the run method defined in OutputApplet contains the JDBC code.
When the thread worker invokes the method start, the run method is called
automatically, and it executes the JDBC code in the thread worker. The code in run is
very similar to the code you have seen in our other sample code with three exceptions.
First, it uses the class Vector to store the results of the query. Second, it does not print
198
out the results but rather adds them to the Vector results for display later. Third, it
likewise does not print out exceptions and instead records error messages for later
display.
Applets have various ways of drawing, or displaying, their content. This applet, a very
simple one that has only text, uses the method drawString (part of the Graphics class)
to display its text. The method drawString takes three arguments:
The method paint is what actually displays something on the screen, and in
OutputApplet.java , it is defined to contain calls to the method drawString . The main
thing drawString displays is the contents of the Vector results (the stored query
results). When there are no query results to display, drawString will display the current
contents of the String message . This string will be "Initializing" to begin with. It gets
set to "Connecting to database" when the method start is called, and the method
setError sets it to an error message when an exception is caught. Thus, if the database
connection takes much time, the person viewing this applet will see the message
"Connecting to database" because that will be the contents of message at that time. (The
method paint is called by AWT when it wants the applet to display its current state on
the screen.)
The last two methods defined in the class OutputApplet, setError and setResults are
private, which means that they can be used only by OutputApplet. These methods both
invoke the method repaint , which clears the screen and calls paint . So if setResults
calls repaint , the query results will be displayed, and if setError calls repaint, an
error message will be displayed.
A final point to be made is that all the methods defined in OutputApplet except run are
synchronized . The keyword synchronized indicates that while a method is accessing
an object, other synchronized methods are blocked from accessing that object. The
method run is not declared synchronized so that the applet can still paint itself on the
screen while the database connection is in progress. If the database access methods were
synchronized , they would prevent the applet from being repainted while they are
executing, and that could result in delays with no accompanying status message.
(3) Display error messages on the screen instead of printing them to System.out or
System.err .
Running an Applet
Before running our sample applet, you need to compile the file OutputApplet.java .
This creates the file OutputApplet.class , which is referenced by the file
OutputApplet.html.
The easiest way to run an applet is to use the appletviewer, which is included as part of
the JDK. Simply follow the instructions below for your platform to compile and run
OutputApplet.java :
UNIX
javac OutputApplet.java
appletviewer OutputApplet.html
Windows 95/NT
javac OutputApplet.java
appletviewer OutputApplet.html
Applets loaded over the network are subject to various security restrictions. Although this
can seem bothersome at times, it is absolutely necessary for network security, and
security is one of the major advantages of using the Java programming language. An
applet cannot make network connections except to the host it came from unless the
browser allows it. Whether one is able to treat locally installed applets as "trusted" also
depends on the security restrictions imposed by the browser. An applet cannot ordinarily
read or write files on the host that is executing it, and it cannot load libraries or define
native methods.
Applets can usually make network connections to the host they came from, so they can
work very well on intranets.
The JDBC-ODBC Bridge driver is a somewhat special case. It can be used quite
successfully for intranet access, but it requires that ODBC, the bridge, the bridge native
library, and JDBC be installed on every client. With this configuration, intranet access
works from Java applications and from trusted applets. However, since the bridge
requires special client configuration, it is not practical to run applets on the Internet with
the JDBC-ODBC Bridge driver. Note that this is a limitation of the JDBC-ODBC Bridge,
not of JDBC. With a pure Java JDBC driver, you do not need any special configuration to
run applets on the Internet.
JDBC helps you to write java applications that manage these three programming
activities:
1. Create a table, containing the fields Name, Id and salary. Populate it and create the
jdbc-odbc connection. Do it either manually or through a program, as shown in the
example program.
2. Create a graphical user interface consisting of three Text fields and three Labels ,
corresponding to the three fields of the table, created in the previous exercise. There
must be a button ‘SHOW’. The user must type the Id and press ‘SHOW’ to display
the rest of the information. Write a program, utilizing JDBC to implement this, for the
table.
3. To the above GUI, add two more buttons ‘ADD’ and ‘DELETE’. If the user enter
data into the three fields and presses ‘ADD’, the new data must be added to the table.
On the other hand, if the user enters data in one of the fields and presses ‘DELETE’,
all the records having that value for that field must be deleted from the table.
4. Now add two more buttons ‘NEXT’ and ‘PREVIOUS’. By pressing these buttons the
user must be able to scroll through the records in the table, one after the other.
5. Add one more button ‘UPDATE’. When the user is scrolling through the records,
using ‘NEXT” and ‘PREVIOUS’, if the user changes the value in a particular field
and presses ‘UPDATE’, the value must get changed in the table.
Note: The programs must take care of all conditions of wrong entry of data and must display message
boxes, displaying the appropriate error messages
Compare 2 Tier and 3 Tier Architecture and Discuss the limitations of 2-tier
architecture
201
9.9. REFERENCES
Jane Jawroski, “Java Unleashed”, SAMS Techmedia Publications, 1999
Campione, Walrath and Huml, “The Java Tutorial”, Addison Wesley 1999
202
Servlets
Applications of Servlets
Database support in web applications
Servlets are the programs that execute on the server side. Servlets are modules that extend
request/response-oriented servers, such as Java-enabled web servers. For example, a servlet might be
responsible for taking data in an HTML order-entry form and applying the business logic used to
update a company's order database.
203
Servlets are to servers what applets are to browsers. Unlike applets, however, servlets
have no graphical user interface.
Servlets can be embedded in many different servers because the servlet API, which
you use to write servlets, assumes nothing about the server's environment or protocol.
Servlets have become most widely used within HTTP servers.
So use servlets to handle HTTP client requests. For example, have servlets
process data POSTed via HTTPS using an HTML form, including purchase order or
204
credit card data. A servlet like this could be part of an order-entry and processing system,
working with product and inventory databases, and perhaps an on-line payment system.
Servlets run until the servers are destroys them, for example, at the request of a
system administrator. When a server destroys a servlet, the server runs the servlet's
destroy method. The method is run once; the server will not run that servlet again until
after the server reloads and reinitializes the servlet.
206
When the destroy method runs, another thread might be running a service
request.
Once you have written your servlet, you can test it in the servletrunner utility.
The servletrunner is a small, multithreaded process that handles requests for
servlets. Because servletrunner is multi-threaded, it can be used to run multiple
servlets simultaneously, or to test one servlet that calls other servlets to satisfy client
requests.
Unlike some web servers, servletrunner does not automatically reload updated
servlets. However you can stop and restart servletrunner with very little overhead to
run a new version of a servlet.
You might have to specify certain pieces of data to run a servlet. For example, if a
servlet requires initialization parameters, you must set up this data before starting
servletrunner.
After the property file is set up, you can run the servletrunner utility.
The javax.servlet package provides interfaces and classes for writing servlets.
The architecture of the package is described in the next section.
207
The central abstraction in the Servlet API is the Servlet interface. All servlets
implement this interface, either directly or, more commonly, by extending a class that
implements it such as HttpServlet
The Servlet interface declares, but does not implement, methods that manage
the servlet and its communications with clients. Servlet writers provide some or all of
these methods when developing a servlet.
Client Interaction
The ServletResponse interface gives the servlet methods for replying to the client.
It:
Allows the servlet to set the content length and MIME type of the reply.
Provides an output stream, ServletOutputStream API, and a Writer through
which the servlet can send the reply data.
Interfaces that extend the ServletResponse interface give the servlet more
protocol-specific capabilities. For example, the HttpServletResponse API interface
contains methods that allow the servlet to manipulate HTTP-specific header information.
The classes and interfaces described above make up a basic Servlet. HTTP
servlets have some additional objects that provide session-tracking capabilities. The
servlet writer can use these APIs to maintain state between the servlet and the client that
persists across multiple connections during some time period. HTTP servlets also have
objects that provide cookies. The servlet writer uses the cookie API to save data with the
client and to retrieve this data.
Description of Example
SimpleServlet extends the HttpServlet class, which implements the
Servlet interface.
SimpleServlet overrides the doGet method in the HttpServlet class.
The doGet method is called when a client makes a GET request (the
default HTTP request method), and results in the simple HTML page
being returned to the client.
Within the doGet method,
The user's request is represented by an HttpServletRequest
object.
The response to the user is represented by an
HttpServletResponse object.
Because text data is returned to the client, the reply is sent using
the Writer object obtained from the HttpServletResponse
object.
Protocol Support
An HTTP Servlet handles client requests through its service method. The
service method supports standard HTTP client requests by dispatching each request to
a method designed to handle that request.
javax.servlet package
Classes: ServletException, ServletInputStream, ServletOutputStream,
GenericServlet, UnavailableException.
javax.servlet.http package
Classes: Cookie, HttpUtils, HttpServlet, HttpSessionBindingEvent
Interfaces: HttpServletRequest, HttpServletResponse, HttpSession,
HttpSessionBindingListener, HttpSessionContext,
HttpServletRequest Objects
HttpServletResponse Objects
Closing the Writer or ServletOutputStream after you send the response allows
the server to know when the response is complete.
You must set HTTP header data before you access the Writer or OutputStream.
The HttpServletResponse class provides methods to access the header data. For
example, the setContentType method sets the content type. (This header is often the
only one manually set.)
The methods to which the service method delegates HTTP requests include,
Handling GET requests involves overriding the doGet method. The following example
shows the BookDetailServlet doing this.
The servlet extends the HttpServlet class and overrides the doGet method.
Within the doGet method, the getParameter method gets the servlet's expected
argument.
To respond to the client, the example doGet method uses a Writer from the
HttpServletResponse object to return text data to the client. Before accessing the
writer, the example sets the content-type header. At the end of the doGet method, after
the response has been sent, the Writer is closed.
Handling POST requests involves overriding the doPost method. The following
example shows the ReceiptServlet doing this.
The servlet extends the HttpServlet class and overrides the doPost method.
Within the doPost method, the getParameter method gets the servlet's
expected argument.
To respond to the client, the example doPost method uses a Writer from the
HttpServletResponse object to return text data to the client. Before accessing the
writer the example sets the content-type header. At the end of the doPost method, after
the response has been set, the Writer is closed
Some applications, such as the Java Web Server Administration Tool, get
descriptive information from the servlet and display it. The servlet description is a string
that can describe the purpose of the servlet, its author, its version number, or whatever the
servlet author deems important.
The method that returns this information is getServletInfo, which returns null
by default. You are not required to override this method, but applications are unable to
supply a description of your servlet unless you do.
Generic Servlet:
So far we discuses about HTTP Servlet. Now we will get into the Generic servlet.
The Generic Servlet provides functionality that makes it easy to handle request &
response.
Description
Here Myservlet defined as s subclass of genericServlet. This provides
functionality to handle the request and reponse to the Myservlet.Inside the Myservlet ,the
service() method is overridden the GenericServlet method.This method handles request
from client.
The argument ServletRequest is used to get request from the client and
ServletResponseused to formulate a response to the client.The setContentType ()calling
establishes the MIME type of the HTTP response. In this program, MIME type is text or
html type. The getWriter () obtains a PrintWriter. Anything written in this stream is sent
the client. Then, println() is used to write HTML source code as the HTTP response.
What is a session?
HTTP is a stateless protocol which means that eash request is independent of the
previous one. How ever it is necessary to save state information so that information can
be collected from several interactions between a browser and a server. Sessions provide
such a mechanism.
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
Cookies
Cookies are a mechanism that a servlet uses to have clients hold a small amount
of state-information associated with the user. Servlets can use the information in a cookie
as the user enters a site (as a low-security user sign-on, for example), as the user
navigates around a site (as a repository of user preferences for example), or both.
The Cookie class encapsulates a cookie. a cookie is stored on the client and
contains state information. cookies are valuable for tracking user activities.
A servlet can write a cookie to a users machine via a addCookie() method of the
HttpServletResponce interface. the data for thta cookie is then included in the header of
the HTTP responce that is sent to the browser.
A cookie contains the following
name
value
expiry date
domain and path
The expiry date determines whrn the cookie is deleted from the users machine.If
no expiry date is assigned then it is deleted when the current session ends
The domain and path of the cookie determines whne it is included in the header of
an HTTP request. if the user enters a URL whose domainb and path match these values
then the cookie is supplied to the web server
216
//AddCookieServlet.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
//create cookie
Cookie cookie = new Cookie("MyCookie",data);
res.addCookie(cookie);
res.setContentType("text/html");
PrintWriter pw = res.getWriter();
pw.println("<b>MyCookie has been set to ");
pw.println(data);
pw.close();
}
}
//GetCookieServlet.java
217
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
In this lesson we discussed about Database search on WEB, database support in web
applications using servlet.
10.9. REFERENCES
Jane Jawroski, “Java Unleashed”, SAMS Techmedia Publications, 1999
Campione, Walrath and Huml, “The Java Tutorial”, Addison Wesley 1999
219
11.1. INTRODUCTION
The Java Archive (JAR) file format enables you to bundle multiple files into a single
archive file. Typically a JAR file will contain the class files and auxiliary resources
associated with applets and applications.
11.2. ADVANTAGES OF JAR
The JAR file format provides many benefits:
Security: You can digitally sign the contents of a JAR file. Users who recognize your signature
can then optionally grant your software security privileges it wouldn't otherwise have.
Decreased download time: If your applet is bundled in a JAR file, the applet's class files and
associated resources can be downloaded to a browser in a single HTTP transaction without the
need for opening a new connection for each file.
Compression: The JAR format allows you to compress your files for efficient storage.
Packaging for extensions (version 1.2): The extensions framework provides a means by which
you can add functionality to the Java core platform, and the JAR file format defines the
packaging for extensions. Java 3D and JavaMail are examples of extensions developed by Sun.
By using the JAR file format, you can turn your software into extensions as well.
Package Sealing (version 1.2): Packages stored in JAR files can be optionally sealed so that the
package can enforce version consistency. Sealing a package within a JAR file means that all
classes defined in that package must be found in the same JAR file.
Package Versioning (version 1.2): A JAR file can hold data about the files it contains, such as
vendor and version information.
Portability: The mechanism for handling JAR files is a standard part of the Java platform's core
API.
The JAR file format is an important part of the Java platform's extension mechanism.
220
You can use the Jar tool to unpack a JAR file. When extracting files, the Jar tool makes
copies of the desired files and writes them to the current directory, reproducing the
directory structure that the files have in the archive.
Option Description
222
Produces verbose output on stderr (in version 1.1) or stdout (in version 1.2) while the JAR file is
v
being built. The verbose output tells you the name of each file as it's added to the JAR file.
0
Indicates that you don't want the JAR file to be compressed.
(zero)
M Indicates that the default manifest file should not be produced.
Used to include manifest information from an existing manifest file. The format for using this
option is:
m
jar cmf existing-manifest jar-file input-file(s)
See Modifying a Manifest for more information about his option.
To change directories during execution of the command. Version 1.2 only. See below for an
-C
example.
In version 1.1, the JAR-file format supports only ASCII filenames. Version 1.2 adds
support for UTF8-encoded names.
An Example
Let's look at an example. The JDK demos include a simple TicTacToe applet. This demo contains a
bytecode class file, audio files, and images all housed in a directory called TicTacToe having this structure:
The audio and images subdirectories contain sound files and GIF images used by the applet.
To package this demo into a single JAR file named TicTacToe.jar, you would run this command from
inside the TicTacToe directory:
The audio and images arguments represent directories, so the Jar tool will recursively place them and their
contents in the JAR file. The generated JAR file TicTacToe.jar will be placed in the current directory.
Because the command used the v option for verbose output, you'd see something similar to this output
when you run the command:
adding: TicTacToe.class
(in=3825) (out=2222) (deflated 41%)
adding: audio/ (in=0) (out=0) (stored 0%)
adding: audio/beep.au
(in=4032) (out=3572) (deflated 11%)
adding: audio/ding.au
(in=2566) (out=2055) (deflated 19%)
adding: audio/return.au
(in=6558) (out=4401) (deflated 32%)
adding: audio/yahoo1.au
(in=7834) (out=6985) (deflated 10%)
adding: audio/yahoo2.au
(in=7463) (out=4607) (deflated 38%)
223
You can see from this output that the JAR file TicTacToe.jar is compressed. The Jar tool compresses files
by default. You can turn off the compression feature by using the 0 (zero) option, so that the command
would look like:
jar cvf0 TicTacToe.jar TicTacToe.class audio images
You might want to avoid compression, for example, to increase the speed with which a JAR file could be
loaded by a browser. Uncompressed JAR files can generally be loaded more quickly than compressed files
because the need to decompress the files during loading is eliminated. However, there's a tradeoff in that
download time over a network may be longer for larger, uncompressed files.
The Jar tool will accept arguments that use the wildcard * symbol. As long as there weren't any unwanted
files in the TicTacToe directory, you could have used this alternative command to construct the JAR file:
Though the verbose output doesn't indicate it, the Jar tool automatically adds a manifest file to the JAR
archive with pathname META-INF/MANIFEST.MF.
In the above example, the files in the archive retained their relative pathnames and directory structure. The
Jar tool in version 1.2 of the Java Development Kit provides the -C option that you can use to create a JAR
file in which the relative paths of the archived files are not preserved. It's modeled after GZIP's -C option.
As an example, suppose you wanted put audio files and gif images used by the TicTacToe demo into a JAR
file, and that you wanted all the files to be on the top level, with no directory hierarchy. You could
accomplish that by issuing this command from the parent directory of the images and audio directories:
The -C images part of this command directs the Jar tool to go to the images directory, and the * following -
C images directs the Jar tool to archive all the contents of that directory. The -C audio * part of the
command then does the same with the audio directory. The resulting JAR file would have this table of
contents:
META-INF/MANIFEST.MF
cross.gif
not.gif
beep.au
ding.au
return.au
yahoo1.au
yahoo2.au
By contrast, suppose that you used a command that didn't employ the -C option:
jar cf ImageAudio.jar images audio
The resulting JAR file would have this table of contents:
META-INF/MANIFEST.MF
images/cross.gif
224
images/not.gif
audio/beep.au
audio/ding.au
audio/return.au
audio/yahoo1.au
audio/yahoo2.au
11.9. REFERENCES
Jar tool reference for Windows platform
http://java.sun.com/products/jdk/1.2/docs/tooldocs/win32/jar.html
http://java.sun.com/products/jdk/1.2/docs/tooldocs/solaris/jar.html
Java Internationalization
http://java.sun.com/javase/technologies/core/basic/intl/#mobile
226
12.1. INTRODUCTION
JFC is short for Java Foundation Classes, which encompass a group of features for
building graphical user interfaces (GUIs) and adding rich graphics functionality
and interactivity to Java applications. It is defined as containing the features shown
in the table below.
Features of the Java Foundation Classes
Feature Description
Includes everything from buttons to split panes to tables. Many
Swing GUI
components are capable of sorting, printing, and drag and drop, to
Components
name a few of the supported features.
The look and feel of Swing applications is pluggable, allowing a
choice of look and feel. For example, the same program can use
Pluggable Look- either the Java or the Windows look and feel. Additionally, the Java
and-Feel Support platform supports the GTK+ look and feel, which makes hundreds
of existing look and feels available to Swing programs. Many more
look-and-feel packages are available from various sources.
Enables assistive technologies, such as screen readers and Braille
Accessibility API
displays, to get information from the user interface.
Enables developers to easily incorporate high-quality 2D graphics,
Java 2D API text, and images in applications and applets. Java 2D includes
extensive APIs for generating and sending high-quality output to
227
printing devices.
This trail concentrates on the Swing components. We help you choose the appropriate
components for your GUI, tell you how to use them, and give you the background information
you need to use them effectively. We also discuss other JFC features as they apply to Swing
components.
Fortunately, most programs use only a small subset of the API. This trail sorts out the
API for you, giving you examples of common code and pointing you to methods and
classes you're likely to need. Most of the code in this trail uses only one or two Swing
packages:
javax.swing
javax.swing.event (not always required)
Install the latest release of the Java SE platform, if you haven't already done so.
Create a program that uses Swing components.
Compile the program.
Run the program.
228
javac HelloWorldSwing.java
If you can't compile, make sure you're using the compiler in a recent release of the Java platform. Once
you've updated your JDK, you should be able to use the programs in this trail without changes. Another
common mistake is installing the Java Runtime Environment (JRE) and not the full Java Development Kit
(JDK) needed to compile these programs
java HelloWorldSwing
the GUI development process, letting you focus on the application logic instead
of the underlying infrastructure.
Because this lesson is a step-by-step checklist of specific actions to take, we
recommend that you run the NetBeans IDE and perform each step as you read
along. This will be the quickest and easiest way to begin programming with
Swing. If you are unable to do so, simply reading along should still be useful,
since each step is illustrated with screenshots.
If you prefer the traditional approach of programming each component
manually (without the assistance of an IDE), think of this lesson as an entry
point into the lower-level discussions already provided elsewhere in the tutorial.
Hyperlinks in each discussion will take you to related lessons, should you wish
to learn such lower-level details.
Keyboard shortcuts for each command appear on the far right of each menu item. The look and
feel of the NetBeans IDE may vary across platforms, but the functionality will remain the same.
You may notice mention of "J2SE" in the description pane; that is the old name
for what is now known as the "Java SE" platform. Press the button labeled
"Next" to proceed.
Step 3: Set a Project Name
Now enter "CelsiusConverterProject" as the project name. You can leave the
Project Location and Project Folder fields set to their default values, or click the
Browse button to choose an alternate location on your system.
Make sure to deselect the "Create Main Class" checkbox; leaving this option
selected generates a new class as the main entry point for the application, but
our main GUI window (created in the next step) will serve that purpose, so
checking this box is not necessary. Click the "Finish" button when you are
done.
232
When the IDE finishes loading, you will see a screen similar to the above. All
panes will be empty except for the Projects pane in the upper left hand corner,
which shows the newly created project.
Step 4: Add a JFrame Form
Now right-click the CelsiusConverterProject name and choose New -> JFrame
Form (JFrame is the Swing class responsible for the main frame for your
233
application.) You will learn how to designate this class as the application's entry
point later in this lesson.
Step 5: Name the GUI Class
Next, type CelsiusConverterGUI as the class name, and learn as the package name.
You can actually name this package anything you want, but here we are following the tutorial
convention of naming the package after the lesson in which is resides.
The remainder of the fields should automatically be filled in, as shown above.
Click the Finish button when you are done.
234
When the IDE finishes loading, the right pane will display a design-time,
graphical view of the CelsiusConverterGUI. It is on this screen that you will
visually drag, drop, and manipulate the various Swing components.
12.5. NETBEANS IDE BASICS
It is not necessary to learn every feature of the NetBeans IDE before exploring its GUI creation
capabilities. In fact, the only features that you really need to understand are the Palette, the
Design Area, the Property Editor, and the Inspector. We will discuss these features below.
The Palette
The Palette contains all of the components offered by the Swing API. You can probably already
guess what many of these components are for, even if this is your first time using them
(JLabel is a text label, JList is a drop-down list, etc.)
From this list, our application will use only JLabel (a basic text label),
JTextField (for the user to enter the temperature), and JButton (to convert the
temperature from Celsius to Fahrenheit.)
The Design Area
The Design Area is where you will visually construct your GUI. It has two views: source view,
and design view. Design view is the default, as shown below. You can toggle between views at
any time by clicking their respective tabs.
The figure above shows a single JFrame object, as represented by the large
shaded rectangle with blue border. Commonly expected behavior (such as
quitting when the user clicks the "close" button) is auto-generated by the IDE
and appears in the source view between uneditable blue sections of code known
as guarded blocks.
236
A quick look at the source view reveals that the IDE has created a private
method named initComponents, which initializes the various components of
the GUI. It also tells the application to "exit on close", performs some layout-
specific tasks, then packs the (soon to be added) components together on screen.
The Property Editor
The Property Editor does what its name implies: it allows you to edit the properties of each
component. The Property Editor is intuitive to use; in it you will see a series of rows — one row
per property — that you can click and edit without entering the source code directly. The
following figure shows the Property Editor for the newly added JFrame object:
237
The screenshot above shows the various properties of this object, such as background color,
foreground color, font, and cursor.
The Inspector
The last component of the NetBeans IDE that we will use in this lesson is the Inspector:
The Inspector
The Inspector provides a graphical representation of your application's components. We will use
the Inspector only once, to change a few variable names to something other than their defaults.
You can set the title by either double-clicking the title property and entering the new text
directly, or by clicking the button and entering the title in the provided field. Or, as a
shortcut, you could single-click the JFrame of the inspector and enter its new text directly
without using the property editor.
239
Adding a JTextField
You may be tempted to erase the default text "JTextField1", but just leave it in place for now.
We will replace it later in this lesson as we make the final adjustments to each component.
Adding a JLabel
Adding a JButton
You may be tempted to manually adjust the width of the JButton and
JTextField, but just leave them as they are for now. You will learn how to
correctly adjust these components later in this lesson. For more information
about this component.
242
Finally, add a second JLabel, repeating the process in step 2. Place this second
label to the right of the JButton, as shown above.
12.6.1. Adjusting the CelsiusConverter GUI
With the GUI components now in place, it is time to make the final adjustments. There are a
few different ways to do this; the order suggested here is just one possible approach.
The GUI portion of this application is now complete! If the NetBeans IDE has done its job, you
should feel that creating this GUI was a simple, if not trivial, task. But take a minute to click on
the source tab; you might be surprised at the amount of code that has been generated.
245
To see the code in its entirety, scroll up and down within the IDE as necessary.
You can expand or collapse certain blocks of code (such as method bodies) by
clicking the + or - symbol on the left-hand side of the source editor.
The default names are not very relevant in the context of this application, so it makes sense to
change them from their defaults to something that is more meaningful. Right-click each variable
name and choose "Change variable name." When you are finished, the variable names should
appear as follows:
In the Design Area, click on the Convert button to select it. Make sure that only
the Convert button is selected (if the JFrame itself is also selected, this step will
not work.) Right-click the Convert button and choose Events -> Action ->
ActionPerformed. This will generate the required event-handling code, leaving
you with empty method bodies in which to add your own functionality:
There are many different event types representing the various kinds of actions
that an end-user can take (clicking the mouse triggers one type of event, typing
at the keyboard triggers another, moving the mouse yet another, and so on.) Our
application is only concerned with the ActionEvent;
Step 3: Add the Temperature Conversion Code
The final step is to simply paste the temperature conversion code into the empty method body.
The following code is all that is necessary to convert a temperature from Celsius to Fahrenheit:
Simply copy this code and paste it into the convertButtonActionPerformed method as shown
below:
2. Add a menu bar to the calculator, you created in the previous example. The menu bar must contain
menus ‘File’, ‘Edit’, ’View’. ‘File’ must contain ‘Open’ and ‘Close’ buttons. ‘Edit’ must contain
‘Cut’, ‘Copy’ and ‘Paste’. View must contain ‘Ordinary’ and ’Scientific’. The two must be
separated by a separator. Also provide short cuts for using the menus, through the keyboard.
3. Create an interface that looks similar to the windows explorer. Populate it fictional filenames and
directory names. Few of them will do, but see to it that there is at least one folder that contains two
levels of sub folders and one with one sub folders. All others may be folders with a few files in
them
.
[Hint: Make use of tree, scroll pane and split pane]
4. Create a GUI, having a tabbed pane that has images in each of the panes and the title of each tab is
the name of the image. The GUI must also have four buttons ‘TOP’, ‘BOTTOM’, ‘RIGHT’,
‘LEFT’. If the user presses the button ‘BOTTOM’, the tabs must be displayed at the bottom.
Similarly if he presses ‘LEFT’, the tabs must be displayed to the left and so on.
5. Create a table having columns ‘Name’, ‘Roll Number’ and ‘Total Marks’. Populate the table with
at least ten rows. As a further exercise, make this table editable. If time permits, create a database
table, consisting of these fields, and develop the application such that changes to the table will be
reflected in the database.
You are required to achieve the following tasks with these components:
(1) If you click “File”-> “Open”, you should be able to open a file window as below.
You can open a file by either double clicking the file name or typing in the file
name and hitting the “open” button, just as you normally do. The content of the
file you selected should be shown in the text area. Only the content of a plain text
file is required to be shown correctly. If the file doesn’t exist (double clicking the
file name won’t has this problem, but if you type into the file name, it is possible),
show a message box to indicate such an error. If you click “Cancel”, this window
will be closed and nothing happens.
251
HINT: Design of this “open” window is NOT your job; it’s already done in the
JFileChoose class. Go to http://java.sun.com/j2se/1.4.2/docs/api/ to check
what functions and fields this class provides. What you need to do is figuring out which
file has been selected and how to read its context into the text area. As to the message
box, refer to the JOptionPane class.
(2) If you click “File”-> “Save As”, you should be able to open a file window as
below. After you double click a file name or type in a file name and click “Save”,
the text currently shown in the text area should be saved in that file. You are NOT
required to handle a double confirmation if the file has existed, so be careful that
you may override some useful files (just be careful by yourself, this lab doesn’t
require you to do anything about it). If you click “Cancel”, this window will be
closed and nothing happens.
HINT: Same as task (1), this window is also manipulated by the JFileChoose class.
(3) If you click “File”-> “Exit”, your text editor window will be closed and the
program stops.
(4) You should be able to change the font style, the foreground color and the
background color of the text area.
12.10. REFERENCES
Jane Jawroski, “Java Unleashed”, SAMS Techmedia Publications, 1999
Campione, Walrath and Huml, “The Java Tutorial”, Addison Wesley 1999
252
Understand JSP
Architecture of CORBA
Applications of EJB
Applications of JINI
What Is JSP?
JavaServer Pages are all about data-- how to move it, handle it and display it. JSP lets the
programmer build dynamic web sites. For example, when you log on to your favorite on-line book store,
the web site may greet you by name and suggest new titles of specific interest to you based on your past
purchases. The web site content changes dynamically, in this example, based on who the user is. With JSP,
web site design is not only a function of how the data is presented but also what data is used (and how it is
used) based on current conditions.
As we go ahead we will see that JSP looks a lot like HTML with embedded Java. The HTML
paints the page, and the Java gets the work done, but that means the page designers and the programmers
are constantly working on the same JSP script
If you let the page designers translate their vision into the JSP's HTML and let the programmers
write their part in Java Beans that are executed from the JSP part of the script, then nobody steps on
anybody. It's a powerful division of labor, allowing each group to concentrate on doing what it does best.
Another advantage of this approach is that Java Beans are reusable, so it just makes good sense to separate
them out into database calls, business rules, and other common routines.
Java Beans aren't all that big a deal either. If you can write an applet or a Java application, you can
write a Bean. It's just got a bit more structure. We're not going to get there for quite a while, but Bean
basics will be covered when we do.
First we need to define a few terms that will keep popping up.
A Web Server is software that accepts a request for a web file (HTML). When it gets that file, it
sends the information back to the client machine's browser for display.
A Container is software that stores JSP files and servlets, converts JSP files into servlets,
compiles servlets, and runs servlets, creating HTML. All this stuff happens when the web server gets a
request for a file with a .jsp extension.
We'll also be talking about some software to accommodate connection pooling, but that can wait
until a subsequent lesson when we're going after real data.
The user does something to cause a request for a JSP file to be sent to the web browser. A real-
world example is a HTML form that allows the user to enter something and then take an action (like
clicking a button) that fires off a request to the web server for a JSP file to be loaded into the web browser
and displayed.
The web server receives the request for a .jsp file, but it has no idea what to do with the .jsp
extension. Remember, this web server isn't all that bright. It serves up HTML, and nothing else, so it
forwards the request to the container.
The container looks for a servlet class with the requested file name in the appropriate package. If it
finds the servlet, it runs the servlet, creating HTML that is immediately sent to the web browser (so,
servlets create HTML).
Important point: a JavaServer Page is converted to a Java servlet for compiling and processing.
If the container doesn't find the servlet class, it looks for the same file name, but with a .jsp
extension. If it finds a match, the JSP is converted to a servlet by the container's JSP engine, and the servlet
is compiled. Then the container runs the servlet, creating HTML that is immediately sent to the web
browser, just like before.
The web server gets the newly-created HTML from the container and forwards it to the client's
browser for processing. The browser does its thing and the user sees the data he/she requested in the
beginning.
Server Components
Server components are application components that run in an application server. EJB technology is part of
Sun's Enterprise Java platform, a robust Java technology environment that can support the rigorous
254
A Java application server provides an optimized execution environment for server-side Java application
components. By combining traditional OLTP technologies with new distributed object technologies, a Java
application server delivers a high-performance, highly scalable, robust execution environment specifically
suited to support Internet-enabled application systems.
WORA
The Enterprise JavaBeans architecture defines a standard model for Java application servers to support
"Write Once, Run AnywhereTM" (WORA) portability. WORA is one of the primary tenets of Java
technology. The Java virtual machine (JVM) allows a Java application to run on any operating system. But
server components require additional services that are not supplied directly by the JVM. These services are
supplied either by an application server or by a distributed object infrastructure, such as CORBA or
DCOM. Traditionally, each application server supplied a set of proprietary programming interfaces to
access these services, and server components have not been not portable from one application server to
another. For example, a server component designed to run in BEA Tuxedo could not execute in IBM
TXSeries without significant modification. The EJB server component model defines a set of standard
vendor-independent interfaces for all Java application servers.
Component Portability
Enterprise JavaBeans technology takes the WORA concept to a new level. Not only can these components
run on any platform, but they are also completely portable across any vendor's EJB-compliant application
server. The EJB environment automatically maps the component to the underlying vendor-specific
infrastructure services.
The Enterprise JavaBeans specification defines a standard model for a Java application server that supports
complete portability. Any vendor can use the model to implement support for Enterprise JavaBeans
components. Systems, such as TP monitors, CORBA runtime systems, COM runtime systems, database
systems, Web server systems, or other server-based runtime systems can be adapted to support portable
Enterprise JavaBeans components.
Overview of Components
Components
A component is a reusable software building block: a pre-built piece of encapsulated application code that
can be combined with other components and with handwritten code to rapidly produce a custom
application.
Containers
Components execute within a construct called a container. A container provides an application context for
one or more components and provides management and control services for the components. In practical
terms, a container provides an operating system process or thread in which to execute the component.
Client components normally execute within some type of visual container, such as a form, a compound
document, or a Web page. Server components are non-visual and execute within a container that is
provided by an application server, such as a TP monitor, a Web server, or a database system.
255
Component Model
A component model defines the basic architecture of a component, specifying the structure of its interfaces
and the mechanisms by which it interacts with its container and with other components. The component
model provides guidelines to create and implement components that can work together to form a larger
application. Application builders can combine components from different developers or different vendors
to construct an application.
Granularity
Components come in a variety of shapes and sizes. A component can be very small, such as a simple GUI
widget (e.g., a button), or it can implement a complex application service, such as an account management
function.
Standard Interface
In order to qualify as a component, the application code must provide a standard interface that enables
other parts of the application to invoke its functions and to access and manipulate the data within the
component. The structure of the interface is defined by the component model.
An application developer should be able to make full use of the component without requiring access to its
source code. Components can be customized to suit the specific requirements of an application through a
set of external property values. For example, the button component has a property that specifies the name
that should appear on the button. The account management component has a property that specifies the
location of the account database. Properties can be used to support powerful customization services. For
example, the account management component might allow a user to add a special approval process for
withdrawals over a certain dollar amount. One property would be used to indicate that special approval
functions are enabled, a second property would identify the conditions that require special approvals, and a
third property would indicate the name of the approval process component that should be called when the
condition exists.
Component Marketplace
One of the promises of component technology is a world in which customized business solutions can be
assembled from a set of off-the-shelf business objects. Software vendors could produce numerous
specialized business components, and organizations could select the appropriate components to match their
business needs. Thus far, there is a fairly rich supply of off-the-shelf, third-party, client-side development
components. For the moment, the market for server-side components is still very young. As more and more
organizations adopt the server component architecture, the market is likely to mature rapidly. Application
software companies are already beginning to implement applications using server components. Some e-
commerce vendors are beginning to supply individual application functions, such as a shopping cart and a
credit validation service, as customizable components.
Server Components
Shared Servers
In order to achieve the most benefit from the multitier architecture, server components should be
implemented as shared servers. But building a shared server is harder than building a single-user
application function. Highly scalable shared servers need to support concurrent users, and they need to
efficiently share scarce system resources, such as threads, processes, memory, database connections, and
network connections. For business operations, shared servers must participate in transactions. In many
cases, a shared server needs to enforce security policies.
256
Plug-and-Play Assembly
A component builder doesn't especially want to implement multithreading, concurrency control, resource-
pooling, security, and transaction management in every component. If these services were implemented in
each component, achieving true plug-and-play application assembly would be very difficult. A component
model standardizes and automates the use of these services, thereby enabling easy application development.
Container
An application server provides a container to manage the execution of a component. When a client invokes
a server component, the container automatically allocates a process thread and initiates the component. The
container manages all resources on behalf of the component and manages all interactions between the
component and the external systems.
There are many different types of application servers in common use today, and each provides a container
for some type of server-based request. For example:
A TP monitor contains transactions and manages shared resources on behalf of a transaction.
Multiple transactions can work together and rely on the TP monitor to coordinate the extended
transaction.
A database management system (DBMS) contains database requests. Multiple database clients can
submit requests to the database concurrently and rely on the DBMS to coordinate locks and
transactions.
A Web server contains Web page requests. Multiple Web clients can submit concurrent page
requests to the Web server. The Web server serves up HTML pages or invokes server extensions
or servlets in response to requests.
The operations and behaviors of a container are defined by its component model. Unfortunately, each
container implements its own set of services with its own service interfaces. As a result, components
developed for one type of environment are usually not portable to any other type of environment. The
Enterprise JavaBeans component model, however, is designed to deliver a portability layer for these
container systems.
EJB Servers
The first EJB-compliant application servers began to appear in August 1998. Products that are shipping or
in beta as of this writing include:
BEA WebLogic Tengah
Bluestone Sapphire/Web
GemStone GemStone/J
IBM WebSphere Advanced Edition
Novera jBusiness
Oracle8i
Oracle Application Server
OrchidSoft Vanda
Persistence PowerTier
Progress Apptivity
Secant Extreme
Valto Ejipt
Additional EJB-compliant application servers should be available in early 1999 from vendors, such as
Forte, Fujitsu, Haht, Inprise, Informix, Netscape, Sun, Sybase, and Vision.
257
Benefits
Component Portability
The Enterprise JavaBeans architecture provides a simple and elegant server component container model.
The model ensures that Java platform server components can be developed once and deployed anywhere, in
any vendor's container system. Even though the container systems implement their runtime services
differently, the Enterprise JavaBeans interfaces ensure that an enterprise bean can rely on the underlying
system to provide consistent lifecycle, persistence, transaction, distribution, and security services.
Architecture Independence
The Enterprise JavaBeans architecture is completely independent from any specific platform, protocol, or
middleware infrastructure. Applications that are developed for one platform can be picked up, moved, and
redeployed to another platform. EJB applications can scale from a small single-processor, Intel-based
Novell environment to a large multiprocessor, UltraSPARCTM environment to a massive Sysplex IBM
mainframe environment-all without modification.
Developer Productivity
The Enterprise JavaBeans architecture improves the productivity of application developers. The Enterprise
JavaBeans environment automates the use of complex infrastructure services, such as transactions, thread
management, and security checking. Component developers and application builders do not need to
implement complex service functions within the application programming logic.
Highly Customizable
Enterprise JavaBeans applications are highly customizable. The underlying component model supports
customization without requiring access to source code. Application behaviors and runtime settings are
defined through a set of attributes that can be changed at deployment time.
The Enterprise JavaBeans model is based on an extremely versatile and powerful multitier, distributed
object architecture that relies on industry-standard protocols. The model is appropriate for small-scale
applications or large-scale business transactions. As application requirements grow, applications can
migrate to progressively more powerful operating environments. The environment inherently supports
Web-based applications and a variety of other Internet-enabled client devices. Additional client systems
can be added at any time without modification of the core application systems. Enterprise JavaBeans
technology provides an environment that is designed to grow with the industry to support new technologies
as they emerge.
hardware devices, software programs, or a combination of the two. The focus of the system is to make the
network a more dynamic entity that better reflects the dynamic nature of the workgroup by enabling the
ability to add and delete services flexibly.
A Jini system consists of the following parts:
A set of components that provides an infrastructure for federating services in a distributed system
A programming model that supports and encourages the production of reliable distributed services
Services that can be made part of a federated Jini system and which offer functionality to any
other member of the federation
While these pieces are separable and distinct, they are interrelated, which can blur the distinction in
practice. The components that make up the Jini technology infrastructure make use of the Jini programming
model; services that reside within the infrastructure also use that model; and the programming model is
well supported by components in the infrastructure.
The end goals of the system span a number of different audiences; these goals include the following:
Enabling users to share services and resources over a network
Providing us
t-in security that allows the confidence to run code downloaded from another machine. Strong typing in the
Java application environment enables identifying the class of an object to be run on a virtual machine even
when the object did not originate on that machine. The result is a system in which the network supports a
fluid configuration of objects which can move from place to place as needed and can call any part of the
network to perform operations.
The Jini architecture exploits these characteristics of the Java application environment to simplify the
construction of a distributed system. The Jini architecture adds mechanisms that allow fluidity of all
components in a distributed system, extending the easy movement of objects to the entire networked
system.
The Jini technology infrastructure provides mechanisms for devices, services, and users to join and detach
from a network. Joining into and leaving a Jini system is an easy and natural, often automatic, occurrence.
Jini systems are far more dynamic than is currently possible in networked groups where configuring a
network is a centralized function done by hand.
Devices and applications use a process known as discovery to register with the network. Once registered,
the device or application places itself in the lookup service, equivalent to a bulletin board for all services on
the network. The lookup can store not only pointers to the services on the network, but also the code for
these services.
For example, when a printer registers with the lookup, it loads its printer driver or an interface to the driver
into the lookup. When a client wants to use the printer, the driver and driver interface get downloaded from
the lookup to the client. This code mobility means that clients can take advantage of services from the
network without pre-installing or loading drivers or other software.
The printer might also load other value-added services into the lookup. For instance, the printer might store
attributes about itself, such as whether it supports the Postscript language or color printing. The printer
might also store help wizards that will run on the client to make it easier for people on the network to use
the printer's services.
To preserve the network's flexibility and resilience, Jini technology employs the concept of leasing. When a
device joins the network, it registers for a certain leased time. As the time expires, the device can
renegotiate the lease. But if the device is removed from the network before the lease expires, the device's
entry in the lookup is removed.
260
The following figure illustrates the primary components in the OMG Reference Model
architecture..
Object Services -- These are domain-independent interfaces that are used by many distributed object
programs. For example, a service providing for the discovery of otheravailable services is almost always
necessary regardless of the application domain.
Two examples of Object Services that fulfill this role are:
The Naming Service -- which allows clients to find objects based on names;
The Trading Service -- which allows clients to find objects based on their properties.
Common Facilities -- Like Object Service interfaces, these interfaces are also horizontally-oriented,
but unlike Object Services they are oriented towards end-user applications. An example of such a facility
is the Distributed Document Component Facility (DDCF), a compound document Common Facility
based on OpenDoc. DDCF allows for the presentation and interchange of objects based on a document
model, for example, facilitating the linking of a spreadsheet object into a report document.
Domain Interfaces -- These interfaces fill roles similar to Object Services and Common Facilities
but are oriented towards specific application domains. For example, one of the first OMG RFPs issued
for Domain Interfaces is for Product Data Management (PDM) Enablers for the manufacturing domain.
Other OMG RFPs will soon be issued in the telecommunications, medical, and financial domains.
261
Application Interfaces - These are interfaces developed specifically for a given application.
Because they are application-specific, and because the OMG does not develop applications (only
specifications), these interfaces are not standardized. However, if over time it appears that certain broadly
useful services emerge out of a particular application domain, they might become candidates for future
OMG standardization.
CORBA ORB Architecture
The following figure illustrates the primary components in the CORBA ORB architecture.
Descriptions of these components are available below the figure.
Object -- This is a CORBA programming entity that consists of an identity, an interface, and an
implementation, which is known as a Servant.
Servant -- This is an implementation programming language entity that defines the operations that
support a CORBA IDL interface. Servants can be written in a variety of languages, including C,
C++, Java, Smalltalk, and Ada.
Client -- This is the program entity that invokes an operation on an object implementation.
Accessing the services of a remote object should be transparent to the caller. Ideally, it should be
as simple as calling a method on an object, i.e., obj->op(args). The remaining
components in Figure 2 help to support this level of transparency.
Object Request Broker (ORB) -- The ORB provides a mechanism for transparently
communicating client requests to target object implementations. The ORB simplifies distributed
programming by decoupling the client from the details of the method invocations. This makes
client requests appear to be local procedure calls. When a client invokes an operation, the ORB is
responsible for finding the object implementation, transparently activating it if necessary,
delivering the request to the object, and returning any response to the caller.
262
ORB Interface -- An ORB is a logical entity that may be implemented in various ways (such as
one or more processes or a set of libraries). To decouple applications from implementation details,
the CORBA specification defines an abstract interface for an ORB. This interface provides various
helper functions such as converting object references to strings and vice versa, and creating
argument lists for requests made through the dynamic invocation interface described below.
CORBA IDL stubs and skeletons -- CORBA IDL stubs and skeletons serve as the ``glue''
between the client and server applications, respectively, and the ORB. The transformation between
CORBA IDL definitions and the target programming language is automated by a CORBA IDL
compiler. The use of a compiler reduces the potential for inconsistencies between client stubs and
server skeletons and increases opportunities for automated compiler optimizations.
Dynamic Invocation Interface (DII) -- This interface allows a client to directly access the
underlying request mechanisms provided by an ORB. Applications use the DII to dynamically
issue requests to objects without requiring IDL interface-specific stubs to be linked in. Unlike IDL
stubs (which only allow RPC-style requests), the DII also allows clients to make non-blocking
deferred synchronous (separate send and receive operations) and oneway (send-only) calls.
Dynamic Skeleton Interface (DSI) -- This is the server side's analogue to the client side's DII.
The DSI allows an ORB to deliver requests to an object implementation that does not have
compile-time knowledge of the type of the object it is implementing. The client making the
request has no idea whether the implementation is using the type-specific IDL skeletons or is
using the dynamic skeletons.
Object Adapter -- This assists the ORB with delivering requests to the object and with activating
the object. More importantly, an object adapter associates object implementations with the ORB.
Object adapters can be specialized to provide support for certain object implementation styles
(such as OODB object adapters for persistence and library object adapters for non-remote objects).
263
CORBAservices
CORBAservices add functionality to a CORBA application at the server level. They provide services to
objects that are necessary for various tasks, including event management, object lifecycle, and object
persistence. New CORBAservices are constantly being produced, but at the time of this writing, only the
following 15 services are in existence (a full list of available CORBAservices can be found on the OMG
Web site at http://www.omg.org):
Concurrency Control Service: This service enables multiple clients to coordinate access to shared
resources. For example if two clients are attempting to withdraw funds from the same back
account, this service could be used to ensure that the two transactions do not happen at the same
time.
Event Service: This service enables event's to be delivered from multiple event sources to multiple
event listeners.
Externalization Service: This service enables an object (or objects) or a graph to be written out as
a stream of bytes. This is similar to object serialization in JDK 1.1.
Licensing Service: This service enables control over intellectual property. It allows content
authors to ensure that their efforts are not being used by others for profit.
Life Cycle Service: This service defines conventions for creating, deleting, copying, and moving
objects.
Naming Service: This service allows objects to be tagged with a unique logical name. The service
can be told of the existence of objects and can also be queried for registered objects.
Persistent Object Service: This service enables objects to be stored in some medium. This medium
will usually be a relational or object database, but it could be virtually anything.
Property Service: This service enables name/value pairs to be associated with an object. For
example, some image file could be tagged with name/value pairs describing its content.
Query Service: This service enables queries to be performed against collections of objects.
Relationship Service: This service enables the relationship between entities to be logically
represented.
Security Service: This service enables access to objects to be restricted by user or by role.
Time Service: This service is used to obtain the current time along with the margin of error
associated with that time. In general, it's not possible to get the exact time from a service due to
various factors, including the time delta that occurs when messages are sent between server and
client.
Trader Object Service: This service allows objects to locate certain services by functionality. The
object will first discuss with the trader service whether a particular service is available; then it
negotiates access to those resources.
Transaction Service: This service manages multiple, simultaneous transactions across a variety of
264
environments.
CORBA services are always being developed by the OMG; chances are that by the time you read this list,
there will be a few more services. Already steps are being taken to finalize firewall and fault tolerance
services.
CORBA facilities
As stated earlier, CORBAfacilities add additional functionality to an application
level closer to the user. Facilities are similar to services in that they both aid a
CORBA application however CORBA facilities need not be simply targeted at a
broad audience.
CORBAfacilities are categorized into horizontal and vertical services.
Vertical CORBAfacilities
A vertical CORBAfacility has specific applications in a unique industry or domain.
Obvious parallels exist between a vertical CORBAfacility and a CORBAdomain; however,
CORBAdomains usually have much broader applications within the domain. The following list describes
the eight existing vertical CORBAfacilities:
Distributed Simulation: This facility enables communication between objects used to create
simulations.
Imagery: This facility enables interoperability between imaging devices, images and image data.
Mapping: This facility enables communication between objects used for mapping.
Oil and Gas Industry Exploitation and Production: This facility enables communication between
objects used in the petroleum market.
Horizontal CORBAfacilities
Horizontal CORBAfacilities are broad in their function and should be of use to virtually any application.
Due to their broad scope, there are four categories of horizontal CORBAfadilities. This list of categories is
not at all static and can be added to at some point in the future:
User Interface: All facilities in this category apply to the user interface of an application.
Information. Management: All facilities in this category deal with the modeling, definition,
storage, retrieval, and interchange of information.
265
System Management: All facilities in this category deal with management of information systems.
Facilities should be neutral in vendor support, because any system should be supported.
Task Management: All facilities in this category deal with automation of various user- or system-
level tasks.
The User Interface common facilities apply to an application's, interface at many levels.
As shown in the following list, this includes everything from physically rendering object to the aggregation
of objects into compound documents:
Desktop Management: This facility supports the variety of, functions needed by the user at the desktop.
The Information Management common facilities enable the myriad functions required in a data ownership
situation. These facilities, defined in the following list, range in function from information management to
information storage:
Information Modeling: This facility supports the physical modeling of data storage systems.
Information Storage and Retrieval: This facility enables the storage and retrieval of information.
Compound Interchange: This facility enables the interchange of data contained in compound
documents.
Information Exchange: This facility enables the interchange of information as an entire logical
unit.
Data Encoding and Representation: This facility enables document encoding discovery and
translation.
Time Operations: This facility supports manipulation and understanding of time operations.
The System Management common facilities aid in the difficult task of managing a heterogeneous collection
of information systems. These facilities, defined in the following list, range in function from managing
resources to actually controlling their actions:
Management Tools: This facility enables the interoperation of management tools and collection
management tools.
The Task Management common facilities assist with the automation of user- and system-
level tasks:
Workflow: This facility enables tasks that are directly part of a work process.
Agent: This facility supports manipulation and creation of software agents.
Rule Management: This facility enables objects to both acquire knowledge and to also take action based on
that knowledge.
Automation: This facility allows one object to access the key functionality of another object.
JSP
EJB
JINI
CORBA
List out various Advanced Java Techniques with their specific applications
13.8. REFERENCES
Jane Jawroski, “Java Unleashed”, SAMS Techmedia Publications, 1999
Campione, Walrath and Huml, “The Java Tutorial”, Addison Wesley 1999