Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


Tip of the Day
Language: Applets
Expertise: Beginner
Mar 21, 1997

Use Special Syntax to Find Applet Running in Another Frame?

Question:
I have two applets running on the same page, one in each of two frames. I want them to communicate, but when I do a getAppletContext.getApplet() call, the second applet can't find the first. I've gone through the enumeration returned by getApplets(), and only the applet that makes the call is found.

Is there a special syntax I have to use to find an applet running in another frame?

Answer:
First a little background for newcomers:

For security reasons, there are many restrictions on the ability of an applet to communicate with other processes. However, an applet can communicate with other applets running on the same Web page. How is this done?

One way is to give names to each applet on a Web page using a NAME specifier in the applet tag. Here's a sample HTML file containing two applets named "senderapplet" and "receiverapplet." Note that the names MUST be in lowercase letters:

**********************************





	

	

	

	
	

 Test 


    
    




    

This applet sends outputs to the applet below.

This browser can't run applets.

This applet receives inputs from the applet above.

This browser can't run applets. **********************************
Information about the Web page containing an applet is represented in an AppletContext object, which an applet can obtain using its getAppletContext method:
AppletContext context = getAppletContext();
Among other things, this context contains references to all other applets on the Web page. These references can be accessed from the applet's name (given by the NAME specifier above) using the getApplet method. For example, if an instance of Sender.class wants a reference to the instance of the Receiver.class residing on the same Web page, it can call:
Applet recApp = context.getApplet("receiverapplet");
Communication with the Receiver applet is possible if the Receiver applet provides a special public method that can process messages. Assume the Receiver object has a method called ProcessInput, which expects a String input. Then the Sender object can invoke this method through the reference obtained above (after the appropriate cast):
((Receiver)recApp).processInput("your message here");
Now the problem:

A frame is an HTML element that contains a Web page. Thus, using frames it is possible to nest Web pages. Although not yet a standard HTML feature, frames are supported by Netscape. Assume the Sender and Receiver applets above reside in separate HTML files called "send.html" and "rec.html," respectively. Using the frame feature, they can appear in separate frames on the same Web page:

**********************************



  

	

	

	

	
	

   Parent Frame 
  

    
    

   
  

    

    

  



********************************** 
Unfortunately, the AppletContext of the Sender applet represents send.html, the Web page within the Sender frame. Since the Receiver applet resides in rec.html, it will not be among the applets represented inside the Sender applet's AppletContext. Thus, the technique outlined above fails.

And now the solution:

I wish I could take all the credit for this idea, but alas, I stand on the shoulders of giants. My inspiration was a "Tip of the Week" submitted to JavaWorld by Greg Williams.

My strategy is this: Since Sender's AppletContext doesn't hold a reference to the Receiver applet, why not create our own class and call it a MetaContext, containing references to all registered applets? Receiver and Sender applets can register themselves with the MetaContext during initialization. The MetaContext can provide its own getApplet method to allow applets to access registered applets.

But how will applets running on different pages obtain references to a common MetaContext? This should be possible if everything in the MetaContext is static.

Here's my definition of MetaContext. Registered applets are held in a hash table, where they are indexed by their names:

**********************************

import java.applet.*;
import java.util.*;

public class MetaContext
       {
     // registered applets live here
     private static Hashtable applets = new Hashtable(10);

     // to access registered applets
     public static Applet getApplet(String s) {
        return (Applet)applets.get(s);
      }

     // to register applets
     public static void regApplet(String s, Applet a) {
        applets.put(s, a);
     }

   // etc.
}

********************************** 
As an example, my Sender and Receiver applets each contain two TextFields, one showing the applet's input, the other showing its output. The user enters a number x into the Sender's input field, x is sent to the Receiver, x appears in the Receiver's input field, the Receiver computes y = x * x, places y in its output field, then sends y back to the Sender. The Sender computes z = y + 1, then displays z in its output field. The example is silly, but it does show a non-trivial, two-way communication between Sender and Receiver.

To receive inputs, both Sender and Receiver provide a method:

public void processInput(String s) { ... }
To access the Receiver's processInput() method, the Sender first obtains a reference to the Receiver applet through the MetaContext:
Applet recApp = MetaContext.getApplet("receiverapplet");
Then invokes the Receiver's processInput method:
((Receiver)recApp).processInput(sendField.getText());
Here's the complete code for Sender and Receiver:
**********************************

// Sender.java

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

public class Sender extends Applet {

   private TextField sendField;    // input field
   private TextField receiveField; // output field

   public void init() {
      setLayout(new FlowLayout());
      sendField = new TextField("SEND", 7);
      add(sendField);
      receiveField = new TextField("RECEIVE", 7);
      add(receiveField);
      // register with MetaContext
      MetaContext.regApplet("senderapplet", this);
   }

   public boolean action (Event e, Object arg) {

      if (e.target instanceof TextField && e.target == sendField) {

         AppletContext context = getAppletContext();
         context.showStatus("***** " + sendField.getText() + " sent!");

         // get reference to receiver applet:
         // Applet recApp = context.getApplet("receiverapplet");
         Applet recApp = MetaContext.getApplet("receiverapplet");

         // send message to receiver applet:
         if (!recApp.isActive()) 
            receiveField.setText("Error!");
         else {          
            receiveField.setText("   ");
            ((Receiver)recApp).processInput(sendField.getText());
         }
      }
      else return false;  // event not handled
      return true; // event handled
   }

   // s = number sent by receiver applet
   public void processInput(String s) {
      double y = (Double.valueOf(s)).doubleValue();
      double z = doSomething(y);
      receiveField.setText(String.valueOf(z));
      repaint();
   }

   private double doSomething(double z) { return z + 1; }

}  // Sender

**********************************

// Receiver.java

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

public class Receiver extends Applet {

   private TextField sendField;    // input field
   private TextField receiveField; // output field

   public void init() {
      setLayout(new FlowLayout());
      sendField = new TextField("SEND", 7);
      add(sendField);
      receiveField = new TextField("RECEIVE", 7);
      add(receiveField);
      // register with MetaContext
      MetaContext.regApplet("receiverapplet", this);
   }

   // s = number sent by sender
   public void processInput(String s) {

      receiveField.setText(s);
      repaint();

      AppletContext context = getAppletContext();
      context.showStatus("***** " + s + " received!");

      // get reference to sender applet
      // Applet senderApp = context.getApplet("senderapplet");
      Applet senderApp = MetaContext.getApplet("senderapplet");

      double x = (Double.valueOf(s)).doubleValue();
      double y = doSomething(x);
      String t = String.valueOf(y);
      sendField.setText(t);
      repaint();

      // send message back to sender applet
      ((Sender)senderApp).processInput(sendField.getText());
      
   }

   private double doSomething(double z) { return z * z; }

}  // Receiver

********************************** 
To complete the picture, here are send.html and rec.html:
**********************************


   Sender 
  

    

The applet in this frame sends outputs to the applet in the other frame.

This browser can't run applets. ********************************** Receiver

The applet in this frame receives inputs from the applet in the Sender frame.

This browser can't run applets. **********************************
DevX Pro
 
Comment and Contribute

 

 

 

 

 


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

 

 

Sitemap
Thanks for your registration, follow us on our social networks to keep up-to-date