December 19, 2014
Hot Topics:

Inter-applet Communication: Getting Them to Talk to Each Other

  • April 18, 2000
  • By Developer.com Staff
  • Send Email »
  • More Articles »

Getting two or more applets within a single Web page to talk to each other has some benefits. Although this applet capability has been around since the earliest version of Java, it's not often used, because there's more emphasis placed on getting applets to communicate with servers.

While this is understandable given the current fashion of client/server programming, it's still a valuable skill for developers to learn. Another reason the technique isn't used much is that complicated Web-borne applets are usually shown in a single window. If there's a lot of information to show, the designers simply make the applet larger.

However, in terms of Web page design, it's better in some cases to place small bits of Java-based functionality in different parts of the page, leaving the rest to be filled with text and images. To do this, you need multiple applet windows that are, in some sense, part of the same program.

In this article, we'll look into the basic techniques of inter-applet communication. We'll develop a nice API that takes care of the work for us. Then we'll show a sample application called DumChat, which uses the API.

Method

The secret of inter-applet communication (which we'll abbreviate to IAC) is the method AppletContext.getApplets(). This method provides us with an Enumeration of all the applets running on the same page as the calling applet. From this Enumeration, you can take actual Applet objects, allowing you to freely call methods on it.

Clearly, this is enough to get started. However, it doesn't provide an elegant metaphor for communication. So how should we describe it? Well, how about some kind of message passing? Sounds good.

What we'll do first is give names to the applets on the page and then allow them to send text strings to each other using the names as destinations.

Here's an API for this:


  public void send( String appletName, String message );  
  protected String rcv();

The send() method sends a string to another applet with a given name; the

rcv()
method returns the next string that has been sent to you.

This API will be implemented in a class called CommunicatingApplet. To use this, you'll derive all your applets from this instead of directly from Applet, and the methods in the API will be available to you.

Example

Our simple chat system is called DumChat because, although it allows chatting between two windows, both windows have to be in the same Web page, on the same screen. So it's not very useful, but it does demonstrate our technology.

The runtime structure of the DumChat applet is simple. It has a TextArea for displaying things that have been said, and above that it has a TextField for typing things in. Each time something is typed into the textfield, that message is sent to the other applet. And each applet has a background thread that is waiting for messages to come in and which prints them out when they do.

Here's an excerpt from the code that handles the user typing:


  // Extract the typed string
  String message = ae.getActionCommand();  

  // Send it to the other applet
  send( otherName, message );

  // Display it in our window
  ta.append( message+"\n" );
  tf.setText( "" );

The variable otherName contains the name of the other applet; here you can see that sending a message to the other applet is simple — a single call to send takes care of it.

Here's the code for the background thread that waits for incoming messages and displays them:


  while (true) {
	// Get the next message
	String message = rcv();

	// Print it
	ta.append( message+"\n" );  
  }

Again, very simple. It's worth the effort to put a nice, minimal API over a raw communication mechanism; a more complicated applet would be making lots of calls to send and rcv, and that's better than having lots of bits of code calling Applet.getApplets() and hunting around in that list for other Applet objects.

We name the applets in the HTML. Here's the HTML for our example setup:


  <applet code="DumChat.class" width=300 height=300>  
  <param name="communicationname" value="foo">
  <param name="other" value="bar">
  </applet>
  <applet code="DumChat.class" width=300 height=300>
  <param name="communicationname" value="bar">
  <param name="other" value="foo">
  </applet>

We've named the applets foo and bar. Very creative of us. Now, each applet needs to have a parameter that tells us what our name is and another one to tell us the name of our peer on the other side of our communication mechanism.

Implementation

Let's take a look inside our implementation of the send() and rcv() methods:


  // Send 'message' to applet named 'appletName'
  public void send( String appletName, String message )
      throws CommunicatingAppletException {

   // Have we managed to find our peer and send the message?
   boolean messageSent = false;

   // Zip through all the applets on the page
   Enumeration e = getAppletContext().getApplets();
   while (e.hasMoreElements()) {

    Applet applet = (Applet)e.nextElement();

    // Ignore applets that aren't part of our little game
    if (!(applet instanceof CommunicatingApplet))
     continue;

    // Grab the applet, if it might possibly be our peer
    CommunicatingApplet capplet = (CommunicatingApplet)applet;  

    // If this is the applet we're looking for,
    // give it the message
    if (capplet.getCommunicationName().equals( appletName )) {
     capplet.takeMessage( message );
     messageSent = true;

     // We're done!
     break;
    }
   }

   // The named applet isn't around; throw an Exception
   if (!messageSent)
    throw
      new CommunicatingAppletException(
           "Can't send message "+message );
  }

Here's how sending works: We sort through the list of applets on a page until we find the one with the target name. If we find it, we stuff the message directly into its queue by calling its takeMessage() method.

Note that we throw an exception if we don't find the target applet. This may or may not be overkill for some applications. Even though our chat example is bogus, it does show a case where we might ignore messages that don't arrive; after all, chat programs don't always warn you when your message doesn't get to everyone.

Here's the receiving routine:


  // Receive a waiting message, or block
  // until there is one
  protected String rcv() {
    synchronized( messages ) {

      // We have a lock on the 'messages' object;
      // wait() until there are messages to be had
      while (true) {
        if (messages.isEmpty())
          try { messages.wait(); }
          catch( InterruptedException ie ) {}
        else
          break;
      }

      // Good, there is one.  Remove it from the queue
      // and return it
      String message = (String)messages.elementAt( 0 );  
      messages.removeElementAt( 0 );
      return message;
    }
  }

The trick here is that if there aren't any messages, we have to block until there are some. Which means going into a class wait/condition loop. Once the loop is exited, we know that there is a message, so we take it from the queue and return it to the caller.

Note that we are using synchronization in this code. We are using a Java.util.Vector object to keep the messages in, and we can't have multiple threads messing with it at the same time; so we control access to it by sychronizing on the Vector itself. We don't want to synchronize on the applet — it would work fine, but you might have other code that's already synchronizing on the applet, and you don't want that interacting. It's best to have a separate object for each synchronization issue in your program, and in this case it was fine to just use the Vector itself.

Ideas for Further Work

The main thing to do is to use this technique for something useful. After all, DumChat is pretty silly, and it doesn't really suggest what one might use this for.

As mentioned above, you could have a page where you want to use Java to implement Web site navigational tools. There's a good chance you might want a collection of smaller applets — a collapsible menu on the left, a "What's Hot" ticker at the top, and so on. If these were entirely separate applets, they would likely be duplicating some of the site-layout information they both use, which increases download time. Instead, you can have a master applet telling other applets what to do and what to display.

Our implementation is also quite bare-bones. We are using String objects as our messages, and we might want to have something more sophisticated. We could allow the applets to send arbitrary Objects to each other (and we then send strings if we wanted, or anything else, depending on the application). We could even define a special CommunicatingAppletMessage class, which could contain the actual string or object, and also contain the name of the applet that sent it — like a return address. The receiving applet might need to know where to send a reply. This latter option is probably most elegant from an object-oriented design standpoint.

Another idea is to allow some kind of "discovery" of other applets. We hard-coded the name of the "other" applet into our HTML, but in some cases, our applets might be put on the page in different configurations. Our applet might want to sift through a list of other CommunicatingApplets on the page and see which ones it wants to send things to.

Finally, there might be a problem subclassing from CommunicatingApplet — after all, there might be some other useful abstract applet base class we want to derive from, and that would make it impossible to use CommunicatingApplet. If this were the case, we would want to create another class, say AppletPostOffice, and have the various methods be static methods of that class.

Conclusion

We've seen how applets on the same Web page can find each other, and we've created a more elegant API for using this mechanism. It's up to you to figure out how you can use this to improve your Java-enabled Web pages. Let me know if you make something interesting!

About the Author

Greg Travis is a freelance programmer living in New York City. His interest in computers can probably be traced back to the episode of "The Bionic Woman" where Jamie runs around trying to escape a building, whose lights and doors are controlled by an evil artificial intelligence. He's a devout believer in the idea that when a computer program works, it's a complete coincidence. He can be reached at mito@panix.com.






Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel