You may have noticed that most of the examples in this book are provided in a form suitable for use as Java applications, not as applets. Rather than interspersing applet examples with applications throughout the book, we decided to concentrate on distributed system development issues without the additional complications of applet programming. In this appendix, we'll see how some of the examples could be modified for use in applets.
One of the examples that seems like an obvious candidate for use as an applet is our whiteboard example from Chapter 10, "Building Collaborative Applications". Currently, support for RMI within web browsers is scarce, so let's concentrate on a message-passing version of the whiteboard, instead of the RMI-based version shown in Example A-3. The message-passing version is very similar, but is based on the MessageCollaborator and MessageMediator classes from that chapter. This version, which we called the MsgWhiteboardUser, is shown in Example A-1. Since the differences between this and the RMI-based WhiteboardUser are minor, we won't go into details about the code here.
package dcj.examples.Collaborative; import dcj.util.Collaborative.*; import java.awt.event.*; import java.awt.*; import java.util.Hashtable; import java.util.Properties; import java.io.IOException; import java.util.Vector; class Msg { public Object data; public String tag; public Msg(Object o, String t) { data = o; tag = t; } } class CommHelper extends Thread { Collaborator collaborator; static Vector msgs = new Vector(); public CommHelper(Collaborator c) { collaborator = c; } public static void addMsg(Object o, String t) { synchronized (msgs) { msgs.addElement(new Msg(o, t)); } } public void run() { while (true) { try { Msg m = null; synchronized (msgs) { m = (Msg)msgs.elementAt(0); msgs.removeElementAt(0); } collaborator.broadcast(m.tag, m.data); } catch (Exception e) {} } } } public class MsgWhiteboardUser extends MessageCollaborator implements java.awt.event.MouseListener, java.awt.event.MouseMotionListener { protected Hashtable lastPts = new Hashtable(); protected Component whiteboard; protected Image buffer; public MsgWhiteboardUser(String name, Color color, String host, int port) { super(host, port, name); getIdentity().setProperty("color", color); System.out.println("color = " + color.getRed() + " " + color.getGreen() + " " + color.getBlue()); buildUI(); CommHelper helper = new CommHelper(this); helper.start(); } protected void buildUI() { Frame f = new Frame(); GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); f.setLayout(gridbag); f.addNotify(); c.fill = GridBagConstraints.BOTH; c.gridwidth = GridBagConstraints.REMAINDER; Canvas canvas1 = new java.awt.Canvas(); canvas1.setSize(240,180); canvas1.setBackground(Color.white); gridbag.setConstraints(canvas1, c); f.add(canvas1); String name = null; try { name = getIdentity().getName(); } catch (Exception e) { name = "unknown"; } Label label1 = new java.awt.Label("Your name: " + name); label1.setSize(100,30); gridbag.setConstraints(label1, c); f.add(label1); f.setSize(240,210); f.show(); whiteboard = canvas1; whiteboard.addMouseListener(this); whiteboard.addMouseMotionListener(this); buffer = whiteboard.createImage(f.getSize().width, f.getSize().height); } protected void nextLine(String agent, Point pt, Color c) { Graphics g = buffer.getGraphics(); g.setColor(c); Point lastPt = (Point)lastPts.get(agent); g.drawLine(lastPt.x, lastPt.y, pt.x, pt.y); whiteboard.getGraphics().drawImage(buffer, 0, 0, whiteboard); } public void mousePressed(MouseEvent ev) { Point evPt = ev.getPoint(); try { lastPts.put(getIdentity().getName(), evPt); CommHelper.addMsg(evPt, "start"); } catch (Exception e) {} } public void mouseReleased(MouseEvent ev) { Point evPt = ev.getPoint(); try { nextLine(getIdentity().getName(), evPt, (Color)getIdentity().getProperty("color")); lastPts.remove(getIdentity().getName()); CommHelper.addMsg(evPt, "end"); } catch (Exception e) {} } public void mouseDragged(MouseEvent ev) { Point evPt = ev.getPoint(); try { nextLine(getIdentity().getName(), evPt, (Color)getIdentity().getProperty("color")); lastPts.put(getIdentity().getName(), evPt); CommHelper.addMsg(evPt, "drag"); } catch (Exception e) { } } public void mouseExited(MouseEvent ev) {} public void mouseMoved(MouseEvent ev) {} public void mouseClicked(MouseEvent ev) {} public void mouseEntered(MouseEvent ev) {} public boolean notify(String tag, Object data, Identity src) throws IOException { if (src.getName().compareTo(getIdentity().getName()) == 0) { return true; } Color origColor = null; Color agentColor = null; Graphics gr = buffer.getGraphics(); try { agentColor = (Color)src.getProperty("color"); if (agentColor != null) { gr.setColor(agentColor); } else { System.out.println("No agent color available."); } } catch (Exception exc) { System.out.println("Exception while switching colors."); exc.printStackTrace(); } if (tag.compareTo("start") == 0) { lastPts.put(src.getName(), data); } else if (tag.compareTo("drag") == 0) { Point lastPt = (Point)lastPts.get(src.getName()); Point currPt = (Point)data; gr.drawLine(lastPt.x, lastPt.y, currPt.x, currPt.y); lastPts.put(src.getName(), data); } else if (tag.compareTo("end") == 0) { Point lastPt = (Point)lastPts.get(src.getName()); Point currPt = (Point)data; gr.drawLine(lastPt.x, lastPt.y, currPt.x, currPt.y); lastPts.remove(src.getName()); } whiteboard.getGraphics().drawImage(buffer, 0, 0, whiteboard); return true; } }
A quick and dirty way to use our message-passing whiteboard in an applet context is to just create a MsgWhiteboardUser from inside the init() method of an Applet:
public class WhiteboardApplet extends Applet { private MsgWhiteboardUser wbUser; public WhiteboardApplet() {} public void init() { wbUser = new MsgWhiteboardUser("Fred", new Color(255, 0, 0), "medhost", 5009); } }
When the MsgWhiteboardUser initializes itself, one of the things it does is try to connect to a MessageMediator at the host and port number given to the constructor. This will work just fine, assuming that the applet security policy for your browser allows you to make network connections to the host on which the mediator is running. Typically a browser will only allow an applet to open connections to the host it came from, so you may be forced to have the mediator running on the same host serving the HTML page with your applet.
Since the whiteboard constructs its own top-level Frame inside the buildUI() method, using the WhiteboardApplet in a web page will cause a separate window to pop up on the user's machine. It would be nice to have the whiteboard GUI appear embedded in the web page itself. To do this, we'll need a way to pass the Applet's top-level Container into the constructor for the MsgWhiteboardUser, so that it adds all of its user interface elements to the Container instead of a separate window. We just need to add an additional argument to the MsgWhiteboardUser constructor:
public MsgWhiteboardUser(String name, Color color, String host, int port, Container c) { . . .
Then we pass the external Container into the buildUI() method, which then uses it instead of a new Frame as the container for all of its AWT elements:
protected void buildUI(Container cont) { if (cont == null) cont = new Frame(); GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); cont.setLayout(gridbag); cont.addNotify(); c.fill = GridBagConstraints.BOTH; c.gridwidth = GridBagConstraints.REMAINDER; Canvas canvas1 = new java.awt.Canvas(); canvas1.setSize(240,180); canvas1.setBackground(Color.white); gridbag.setConstraints(canvas1, c); cont.add(canvas1); String name = null; try { name = getIdentity().getName(); } catch (Exception e) { name = "unknown"; } Label label1 = new java.awt.Label("Your name: " + name); label1.setSize(100,30); gridbag.setConstraints(label1, c); cont.add(label1); cont.setSize(240,210); cont.setVisible(true); whiteboard = canvas1; whiteboard.addMouseListener(this); whiteboard.addMouseMotionListener(this); buffer = whiteboard.createImage(cont.getSize().width, cont.getSize().height); }
Now our whiteboard will appear within the web page itself.
Many of the other examples in the book are even easier to apply in an applet context. They can be used within an applet you have developed, assuming that the browsers support the libraries used (e.g., RMI, CORBA, etc.). Of course, you must take applet security restrictions into account when you're deciding how to distribute your agents and how they'll talk to each other. (For example, if you put a server agent on machine X, will any browser running one of your client agents allow the agent to connect to the server machine? )
Copyright © 2001 O'Reilly & Associates. All rights reserved.