Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 470
Max DeLiso Avatar asked Sep 09 '11 22:09

Max DeLiso


1 Answers

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.

like image 148
undisputed Avatar answered Sep 20 '22 05:09

undisputed