Java Tip 101: An alternative way for applet-to-applet communication

Learn how to let your applets speak across frames and browser window boundaries

The AppletContext class in the java.applet package contains the two member functions getApplet and getApplets. By using those functions, an applet can find other applets and invoke methods on them. That can only be done if the following security requirements are met:

  • The applets originate from the same server and from the same directory on the server.
  • The applets are running on the same page and in the same browser window.

Those security restrictions may have been designed that way for good reason; however, the latter requirement limits the ways you can make interesting multiapplet interfaces featuring applet-to-applet (a2a) communication.

Imagine the following scenario:

You have just finished writing a nice stock-market-trade applet and decide to write an even nicer help system for it. You also want the help system to be an applet and to be placed in a different browser frame than the stock-market-trade applet. Your motive for that decision could be based on structural concerns of your Website or the need to always keep the help system on display. In addition, you want to make the help system change to the correct information/guides based on what the user is doing in the stock-trade applet (much like the paper clip in the Microsoft Office suite). You even plan to make wizards within the help system that can remotely point out things and perform tasks in the stock-market-trade applet.

The idea behind that scenario is good. However, since the applets are located on different pages, the Java API in AppletContext will not help you develop the idea completely — but this tip will.

Using the AppletContext API

Before I explain the alternative a2a-communication mechanism, I will briefly show how the getApplet and getApplets methods work. An applet can find another applet in the same HTML page by either using the getApplet method to look it up by name or using the getApplets method to find all the applets on the page. Both methods, if successful, return one or more Applet objects to the caller. Once the caller finds an Applet object, it can invoke the Applet‘s public methods.

Suppose that a snippet of the HTML page looks like this:

    <applet code="Applet1" width="400" height="100" name="app1">
    </applet>
    <br>
    <applet code="Applet2" width="400" height="100" name="app2">
    </applet>
    <br>

By using the name attribute in the applet tag, you can refer to a specific applet in the following way:

    Applet theOtherApplet = getApplet("app1");
    theOtherApplet.anyMethod(); //calling any public method

Or, you can use the following code to retrieve all applets on the page:

    Enumeration allAppletsOnSamePage = getApplets();
    while(allAppletsOnSamePage.hasMoreElements()) {
        Applet appl = (Applet) allAppletsOnSamePage.nextElement();
        appl.anyMethod();       //Calling any public method
    }

When the calling applet has retrieved one or several applets on the same HTML page, it can call those applets’ public methods.

Using a static data structure

Unfortunately with the standard approach, you are limited to communicating only with applets in the same HTML page. Luckily, you can circumvent that limitation very easily. The way you make a2a communication over page boundaries is based on the fact that two applets, even though loaded in different browser windows, will share the same runtime environment if their codebases are the same. Roughly speaking, the codebase is the directory from which the applet was loaded. See Resources below for a link to a tutorial on codebases.

The fact that the runtime environment is shared will make static fields and structures accessible for all applet instances, and therefore, those static fields and structures can be used to pass information between different applets.

Not only can you let simple data types like integers, chars, and strings be stored, but you can also let each applet store a reference to itself (to the instance) in a static field (possibly within its own class). Any other applet will be able to access that field, getting the reference to the instance.

Does that sound tricky? Well, it is not. I’ll start with an easy example. Suppose you have one applet (AppletA.class) in one frame and another applet (AppletB.class) in another frame, and both applets are loaded from the same codebase.

You now want to give AppletA access to AppletB’s public methods. You need to make AppletB save a reference to itself in a static and public field, like this:

    public class AppletB {
        public static AppletB selfRef = null; // Initially zero
        public void init() {
            //  Making reference to the instance
            selfRef = this;
        }
        ...
    }

From AppletA you can now access the instance of AppletB:

    public class AppletA {
        AppletB theOtherApplet = null;
        public void callAppletB() {
            // Getting the static field where the pointer
            // to the instance of AppletB is stored.
            theOtherApplet = AppletB.selfRef;
            // After this it is possible to call instance
            // methods, like this...
            theOtherApplet.repaint();
        }
        ...
    }

That is all there is to it. That method works even though the applets are not on the same page because the runtime environment is shared between different applets.

It is important to note that the code above does not deal with the case where the callAppletB method in AppletA is called before AppletB has started. If that happens, the selfRef will be null and no communication can take place.

A more generic approach

Of course, there is a more generic approach. You can create a class whose only purpose is to store references to applets in a static data structure. An example of such a class, called AppletList, can be seen below. Applet instances that want to give other applets access to their public methods register with the AppletList. By following the pattern in AppletContext.getApplet(string name), each registration has to be associated with a string. The string then serves as a key when another applet calls for a reference to a certain applet.

Typically, an applet registers like this:

    public class AppletA {
        public void start() {
            AppletList.register("Stock-trade-applet", this);
            ...
        }
    }

Then another applet gets access to it:

    public class AppletB {
        public void run() {
            AppletA tradeApplet =
                (AppletA) AppletList.getApplet("Stock-trade-applet");
            ...
        }
    }

You must also remember to unregister from the AppletList when the applet stops:

    public void stop() {
        AppletList.remove("Stock-trade-applet");
        ...
    }

The complete source for the AppletList class looks like this:

0: import java.util.*;
1: import java.applet.Applet;
2:
3: public class AppletList {
4:    private static Hashtable applets = new Hashtable();
5:
6:    public static void register(String name, Applet applet) {
7:          applets.put(name,applet);
8:    }
9:
10:   public static void remove(String name) {
11:         applets.remove(name);
12:   }
13:
14:   public static Applet getApplet(String name) {
15:         return (Applet) applets.get(name);
16:   }
17:
18:   public static Enumeration getApplets() {
19:         return applets.elements();
20:   }
21:
22:   public static int size() {
23:         return applets.size();
24:   }
25: }

Please download the exampleCode.zip file in Resources for examples of how to use this class.

Limitations

As I mentioned earlier, the applets have to be loaded from the same codebase. Moreover, if two different copies of the browser are running and applets are loaded into each copy, the applets might not be able to communicate (depending on browser version and settings) since they may no longer share the same runtime environment. However, that will not be a problem if the browser itself is spawning new browser windows.

That technique has been tested successfully on several platforms and browser versions, but configurations may exist in which each applet’s runtime environment is kept separate. It has been successfully tested on the following operating system and browser combinations:

Windows 2000: Internet Explorer 5.0, Internet Explorer 5.5, Netscape Navigator 4.72, Opera 4.01
Windows 98: Internet Explorer 4.72, Internet Explorer 5.0, Netscape Navigator 4.02
Mac OS 9: Internet Explorer 4.5, Netscape Navigator 4.5
Red Hat 6.2: Netscape Navigator 4.73

Conclusion

This tip has shown an alternative way to allow applet-to-applet communication. This approach works in a way that the Java API’s

getApplet()

method does not. Knowledge of this tip broadens your opportunities for developing applets as part of a Website or an intranet — use it as an alternative or complement to the

getApplets

methods.

Tobias Hill is one of the founders of
Sweden-based Citerus, a company
that focuses on the Java Platform for building Internet, intranet,
and extranet systems. Hill has programmed in Java since 1996 on
various projects ranging from programming an autonomic guide robot
to making an online firework
postcard maker.

Source: www.infoworld.com