Received: from PACIFIC-CARRIER-ANNEX.MIT.EDU by po10 (5.61/4.7) id AA28738; Tue, 11 Jul 00 18:37:10 EDT
Received: from hermes.javasoft.com by MIT.EDU with SMTP
	id AA15665; Tue, 11 Jul 00 18:38:40 EDT
Received: (from nobody@localhost)
	by hermes.java.sun.com (8.9.3+Sun/8.9.1) id WAA04738;
	Tue, 11 Jul 2000 22:34:45 GMT
Date: Tue, 11 Jul 2000 22:34:45 GMT
Message-Id: <200007112234.WAA04738@hermes.java.sun.com>
X-Authentication-Warning: hermes.java.sun.com: Processed from queue /bulkmail/data/teri_71/mqueue5
X-Mailing: 227
From: JDCTechTips@sun.com
Subject: JDC Tech Tips - July 11, 2000
To: JDCMember@sun.com
Reply-To: JDCTechTips@sun.com
Errors-To: bounced_mail@hermes.java.sun.com
Precedence: junk
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
X-Mailer: Beyond Email 2.2


 J  D  C    T  E  C  H    T  I  P  S

                      TIPS, TECHNIQUES, AND SAMPLE CODE


WELCOME to the Java Developer Connection(sm) (JDC) Tech Tips, 
July 11, 2000. This issue covers:

         * Using Shutdown Hooks
         * Automating GUI Programs With java.awt.Robot
                  
These tips were developed using Java(tm) 2 SDK, Standard Edition, 
v 1.3.

You can view this issue of the Tech Tips on the Web at
http://developer.java.sun.com/developer/TechTips/2000/tt0711.html
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

USING SHUTDOWN HOOKS

Suppose that you're writing an application, and you'd like to
gain control when the application shuts down. You might want
to do this in order to close files that are open, for example,
close a log file that the application has written to.

One way to gain control is simply to have a shutdown method that 
you call before calling exit:

    callShutdown();
    System.exit(0);

This approach works if your application terminates only in one
place, that is, System.exit is called only one place, or if you 
specify callShutdown everywhere that you exit. This approach also 
requires that you catch all exceptions that are thrown, which
otherwise would terminate the program abnormally.

In JDK 1.3 there's another way to handle shutdown: using shutdown
hooks. A shutdown hook is an initialized thread that has not yet
been executed. In other words, a shutdown hook is an object of a
class derived from the Thread class, with a run method that is
called to perform whatever actions you want. You register this
object with the Java(tm) Virtual Machine (JVM)*.

Here's an example:

    import java.io.*;
    
    public class ShutdownDemo {
    
        private FileWriter fw_log;
        private BufferedWriter bw_log;
    
        // constructor that opens the log file
    
        public ShutdownDemo() throws IOException {
            fw_log = new FileWriter("log.txt");
            bw_log = new BufferedWriter(fw_log);
    
            // register the shutdown hook
    
            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    endApp();
                }
            });;
        }
    
        // do some application processing and write to the log file
    
        public void processApp1() throws IOException {
            bw_log.write("testing");
            bw_log.newLine();
        }
    
        // do some application processing resulting in an exception
    
        public void processApp2() {
            throw new RuntimeException();
        }
    
        // close the log file
    
        public void endApp() {
            try {
                bw_log.close();
            }
            catch (IOException e) {
                System.err.println(e);
            }
        }
    
        public static void main(String args[]) throws IOException {
    
            // create an application object
    
            ShutdownDemo demo = new ShutdownDemo();
    
            // do some processing
    
            demo.processApp1();
    
            // do some more processing that results in an exception
    
            demo.processApp2();
        }
    }

This application creates an instance of the ShutdownDemo class,
representing an application. The constructor for the class opens 
a log file, using FileWriter and BufferedWriter.

ShutdownDemo then calls processApp1. In its processing, processApp1 
writes an entry to the log file. Then processApp2 is called. It 
throws an exception that is not caught by the application. Normally,
this exception would terminate the application; the log file
entry previously written would be lost because the output is sitting
in a buffer which has not been flushed to disk.

But in this demo the output is not lost. This is because the 
application registers a shutdown hook by saying:

    Runtime.getRuntime().addShutdownHook(new Thread() {
        public void run() {
            endApp();
        }
    });;

Notice the use of an anonymous inner class. Here an instance of an
unnamed class derived from Thread is created, and a run method that
calls endApp is defined for the class.

All of this means that when the application is about to terminate,
the JVM starts the thread representing by the passed-in thread
object. When the thread starts, the run method is called. The run 
method calls endApp, which closes the log file. This flushes the 
output buffer. 

To underscore the effect of the shutdown hook, comment out the
addShutdownHook lines in ShutdownDemo. You'll see that the log
file is empty when the program terminates.

You can register multiple shutdown hooks. In this case, each thread 
that represents a hook is started in an unspecified order, and the 
various threads run simultaneously. You cannot register or 
unregister a shutdown hook after the shutdown sequence has started. 
Doing so results in an IllegalStateException.

Because shutdown hooks run as threads, you must use thread-safe 
programming techniques. Otherwise you risk having threads interfere
with each other. Also, it's wise to design your application for
simple and fast shutdown processing. For example, you might run
into trouble if your application uses services during shutdown that
are themselves in the processing of being shut down.

There are cases where shutdown processing does not happen even if
you have registered shutdown hooks. One example is corrupted native
methods, for example, when you dereference a null pointer in C code.

This feature is somewhat similar to the atexit library function in
C/C++.

For further information about shutdown hooks, see:
http://java.sun.com/j2se/1.3/docs/guide/lang/enhancements.html#hooks.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AUTOMATING GUI PROGRAMS WITH JAVA.AWT.ROBOT

Imagine that you have a Java GUI program written using the AWT and 
Swing libraries, and you'd like to automate the program. For 
example, you'd like to automatically supply GUI input events from 
the keyboard and mouse to the program. In this way, the program
could operate without user intervention. This type of automation 
might be useful for testing purposes, or to produce a self-running 
demo program.

java.awt.Robot is a new class in JDK 1.3, designed to handle this
type of automation. It's a way to automatically feed input events 
to a program. The events are generated in the native input queue 
of the platform, as if they had actually been generated by the 
user. For example, using java.awt.Robot, you can generate an event 
that is equivalent to a user moving the mouse to particular (X,Y) 
coordinates on the screen.

Here's an example of how you can use this class:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class RobotDemo {
        public static void main(String args[]) throws AWTException {
    
            // set up frames and panels
    
            JFrame frame = new JFrame("RobotDemo");
            JPanel panel = new JPanel();
            panel.setLayout(new GridLayout(3, 1));
    
            // set up fields, labels, and buttons
    
            final JTextField field = new JTextField(10);
            final JLabel lab = new JLabel();
            field.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    String s = "Length: " +
                        field.getText().length();
                    lab.setText(s);
                }
            });
            JButton button = new JButton("Exit");
            button.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    System.exit(0);
                }
            });
    
            // add components to panel and display
    
            panel.add(field);
            panel.add(lab);
            panel.add(button);
            frame.getContentPane().add(panel);
            frame.setSize(200, 150);
            frame.setLocation(200, 200);
            frame.setVisible(true);
    
            // create a robot to feed in GUI events
    
            Robot rob = new Robot();
    
            // enter some keystrokes
    
            int keyinput[] = {
                KeyEvent.VK_T,
                KeyEvent.VK_E,
                KeyEvent.VK_S,
                KeyEvent.VK_T,
                KeyEvent.VK_I,
                KeyEvent.VK_N,
                KeyEvent.VK_G
            };
            rob.delay(1000);
            rob.keyPress(KeyEvent.VK_SHIFT);
            field.requestFocus();
            for (int i = 0; i < keyinput.length; i++) {
                rob.keyPress(keyinput[i]);
                rob.delay(1000);
            }
            rob.keyRelease(KeyEvent.VK_SHIFT);
            rob.keyPress(KeyEvent.VK_ENTER);
    
            // move cursor to Exit button
    
            Point p = button.getLocationOnScreen();
            rob.mouseMove(p.x + 5, p.y + 5);
            rob.delay(2000);
    
            // press and release left mouse button
    
            rob.mousePress(InputEvent.BUTTON1_MASK);
            rob.delay(2000);
            rob.mouseRelease(InputEvent.BUTTON1_MASK);
        }
    }

The demo sets up a panel containing an input field, a label, and 
an Exit button. This part of the demo is typical of many Swing 
applications. Then the demo creates a Robot object, and feeds 
into it a series of keystrokes. These keystrokes mimic keys typed 
by a user, that is, the keys T, E, S, T, I, N, and G. There is 
a delay of 1000 milliseconds between keystrokes; this helps 
present the animation more clearly. The shift key is held down 
throughout, so that the letters are entered as capitals. At the 
end of the text input, Enter is specified. This causes the length 
of the input to be echoed in the label field. Then the mouse cursor 
is moved to the Exit button, and the left mouse button is pressed 
and released. This terminates the program.

Notice that virtual keycodes are used to enter keystrokes; keycodes 
are not the same as Java characters. KeyEvent.VK_A corresponds to 
pressing the unshifted 'A' key on a keyboard. If you specify 'A' or 
'a' instead of KeyEvent.VK_A, you get unexpected results.

Also note that the documentation for Robot says that some platforms 
require special privileges to access low-level input control. One 
specific case is X Windows, which requires the XTEST 2.2 standard 
extension.

For further information about java.awt.Robot, see
http://java.sun.com/j2se/1.3/docs/api/java/awt/Robot.html.
For further information about key events, see
http://java.sun.com/j2se/1.3/docs/api/java/awt/event/KeyEvent.html.
For further information about mouse events, see
http://java.sun.com/j2se/1.3/docs/api/java/awt/event/MouseEvent.html.

.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .

- NOTE
The names on the JDC mailing list are used for internal Sun
Microsystems(tm) purposes only. To remove your name from the list,
see Subscribe/Unsubscribe below.


- FEEDBACK
Comments? Send your feedback on the JDC Tech Tips to:

jdc-webmaster@sun.com


- SUBSCRIBE/UNSUBSCRIBE
The JDC Tech Tips are sent to you because you elected to subscribe
when you registered as a JDC member. To unsubscribe from JDC email,
go to the following address and enter the email address you wish to
remove from the mailing list:

http://developer.java.sun.com/unsubscribe.html


To become a JDC member and subscribe to this newsletter go to:

http://java.sun.com/jdc/


- ARCHIVES
You'll find the JDC Tech Tips archives at:

http://developer.java.sun.com/developer/TechTips/index.html


- COPYRIGHT
Copyright 2000 Sun Microsystems, Inc. All rights reserved.
901 San Antonio Road, Palo Alto, California 94303 USA.

This document is protected by copyright. For more information, see:

http://developer.java.sun.com/developer/copyright.html


This issue of the JDC Tech Tips is written by Glen McCluskey.

JDC Tech Tips 
July 11, 2000


* As used in this document, the terms "Java virtual machine" 
  or "JVM" mean a virtual machine for the Java platform. 












