Max DeLiso Max DeLiso - 8 days ago 4
Java Question

Correctly handling a Reload and Restart from the AppletViewer

When my applet starts up the first time from a clean environment, things work the way I expect them to. I spawn two threads, one for generic processing, and one for graphics. I do all GUI manipulation calls from the event dispatching thread. Start/Stop is handled correctly from the appletviewer, but Restart/Reload is not. I have a Canvas called

drawCanvas
as the only Component in my Applet's content pane, and I use double buffering to draw to it.

I observe the problem here:

public void start() {
/* ... some stuff */
executeOnEDTAndWait(
new Thread() {
@Override
public void run() {
/* ... more stuff ... */
setupDrawCanvas();

if( drawCanvas.isDisplayable() ) {
drawCanvas.createBufferStrategy(2);
/* ... some more stuff */
} else {
/* This is where it runs into difficulties */
}
/* ... */


Where
setupDrawCanvas
is defined like this:

private void setupDrawCanvas() {
setVisible(false);
setIgnoreRepaint(true);

getContentPane().removeAll();

drawCanvas = new Canvas();

drawCanvas.setName("drawCanvas");
drawCanvas.setSize(
newDrawCanvasDimension.width,
newDrawCanvasDimension.height);
drawCanvas.setIgnoreRepaint(true);

getContentPane().add(drawCanvas);

getContentPane().setVisible(true);
drawCanvas.setVisible(true);
setVisible(true);
}


Also, here's the relevant code in
destroy()


public void destroy() {
/* .. some stuff .. */

/* dispose of drawCanvas */
drawCanvas.setVisible(false);
if( drawCanvas.getBufferStrategy() != null ) {
drawCanvas.getBufferStrategy().dispose();
}

/* reset and disable the applet's GUI */
setVisible(false);
getContentPane().removeAll();
removeAll();

/* .. some more stuff */


The first time through, everything works fine. When I do a restart from the
appletviewer
, first
stop()
is called which causes all my threads to enter into wait states. Then
destroy()
is called which wakes all my threads up again and lets them exit, as well as do and
invokeAndWait()
on the EDT to clean up my widgets and do a setVisible(false). So after destroy completes the
appletviewer
calls init/start again and the process repeats exactly as before, except it fails in
start()
at the region I noted above.

Something that I noticed which made very little sense to me was that if I cloned the applet using the
appletviewer
and then reloaded the clone, everything would work as expected when I attempted to restart or reload the clone the first time, but would crash with an exception the second time.

Something else I noticed while trying to debug this problem is that the
appletviewer
and a browser act completely differently as hosts to my applet; they don't even call
init()
and
start()
under the same conditions. Also, restart and reload seem to be nothing more than a call to
stop()
->
destroy()
->
init()
->
start()
but with subtle modifications to the execution environment.

So my question is, what is the significance of the restart and reload operations (i.e. when are they used) and is it a problem that my applet fails in the appletviewer when they occur?

Answer

Nice Question. To answer this question we need understand the blocks of java code first. we have a anonymous, static blocks before construtor that will be executed.

package com.test;

import java.applet.Applet;
import java.awt.*;

public class AppletTest extends Applet {
    {
        System.out.println("I m Anonymous block");
    }

    static {
        System.out.println("I m static block");
    }

    public AppletTest()
    {
        System.out.println("I m constructor");
    }

    public void init()
    {
        System.out.println("init");
    }

    public void start()
    {
        System.out.println("start");
    }

    public void stop()
    {
        System.out.println("stop");   
    }

    public void destroy()
    {
        System.out.println("destory");   
    }

    public void paint(Graphics g)
    {
        g.drawString("test Applet",10,10);
    }
}

invocation:

 <applet code="AppletTest.class" height=300 width=300></applet>

when running this class using appletviewer you can note the difference. Applet running for the first time you will get

    I m static block
    I m Anonymous block
    I m constructor
    init
    start

while doing applet restart -

stop
destory
init
start

and on applet reload

stop
destory
I m Anonymous block
I m constructor
init
start

for your second question, applet does not guarantee the same output on different OS, network and hardware components.