| |||||||
![]() |
|||||||
What's So Hot about Java? (Page 3 of 3)
|
|||||||
Inter-Applet Communications
To implement the whiteBoard applet, our wbControls object needed to communicate changes in ink color to the wbPanel object. This communication between panels was done simply by having wbControls call wbPanel's setForeground() method. Painless, right? The good news is that inter-applet communications is just as easy. Since we now have two applets, helloWorld and whiteBoard, we can demonstrate Inter-Applet communications.
Here's the plan. We'll display both the helloWorld and whiteBoard applets on a single Web page. We'll add a RESTART button to our helloWorld applet to restart the animation and clear the whiteBoard's drawings. In other words, when the RESTART button is pressed, the helloWorld applet will have to tell the whiteBoard applet to clear its wbPanel.
To make our plan work, we need something to represent our whiteBoard's contents. We need a few methods that both helloWorld and wbPanel can call to manipulate the whiteBoard's contents. The problem is, we don't want to try to force these two classes into the same superclass. We solved a similar problem earlier by using Interfaces. Interfaces are a set of abstract methods that act as a common shared repository. If we use an abstract class to represent our whiteBoard's contents, then both whiteBoard and helloWorld will have access. This means neither applet needs to change, except to invoke our new methods.
Figure 11 illustrates the new wb class. When whiteBoard
creates its wbPanel, it will call the setWb() method. Since wb represents the contents of the whiteBoard, we moved our vector of shapes into the abstract wb class. Notice the synchronized modifier used with each of the wb class's methods. The synchronized keyword prevents more than one thread from executing the enclosed block of code at the same time. Insert the wb class in Figure 11 into wb.java after the import statements.
You'll need to make a few other changes to utilize our new wb class. Refer to the original wb.java file in Figure 9. Notice the big green numbers "1" through "5." These numbers mark the lines that will be changed. Since we moved the shapes vector under the protection of wb, we need to remove its declaration from wbPanel, so in the wb.java file:
In the whiteBoard.java file (Figure 10), add the statement " wb.setWb(wp);" at the line indicated by the big "1." This will initialize the whiteBoard. In the helloWorld.java file, you can:
We're almost there. Since we need to combine the helloWorld and whiteBoard applets on a single page, we need a new HTML file. Create the both.html file as shown in Figure 13. Open this HTML file in your browser, draw a few lines on the whiteBoard, then test the new RESTART button.
The next segment will feature client-server network (socket) communications.
Because Java's security features restrict applets from making network connections (except to the host that served the applet), we need to implement a whiteBoard server program to forward messages to and from client whiteBoard applets. Unlike our helloWorld and whiteBoard applets, our server won't be invoked from a browser. Instead, the server should run as a daemon on the Web Server so it will always be available for connecting clients. Note that Java programs not invoked from a browser are called Java applications.
Java applications must have a main() method, which is called when the program is invoked. Any command line arguments supplied when the program is started are passed as input arguments to the main() method, just as in C and C++.
Just as an applet has a specific flow, a pair of programs using socket interfaces also has a specific flow. Figure 14 depicts a simple flow in which a server listens for and connects to incoming clients. A server associates itself with a particular logical port by binding itself to that port. The server waits to accept incoming clients. To communicate with a server, a client connects to the port to which the server is bound. For each incoming client, TCP/IP creates a new socket to represent the client. This new socket is passed to the server that is bound to the requested port to handle all communication to this particular client.
The process is repeated for each incoming client. Note that server processes block while waiting for incoming clients. And when reading messages from the socket, both the server and the client processes block.
Because the socket interface will cause our client and server to block at various
points, we'll need to implement multithreading in both the client and server. Figure 15 illustrates how the clients will interface to each other through the server.
You'll need to do the following:
Note the import statements in Figures 19 and 20 are in addition to those import statements already
included in whiteBoard.java and wb.java.
You may have noticed that the serverSockThread uses the DataInputStream to filter the socket input.
As described in the API documentation, if an error occurs on the socket or if the remote disconnects,
the readInt() method will throw a IOException or EOFException, respectively. However, note that
serverSockThread catches only Throwable. Throwable is the superclass for both IOException and
EOFException. By catching Throwable, we are telling Java to do the same thing, regardless of which
exception is thrown.
You may have also noticed the finally keyword in serverSockThread's cleanWb method. Finally
denotes statements to be executed regardless of whether an exception was generated.
When you complete the changes described, compile each of the modified Java source files. Start the
wbServer by entering the command java wbServer. From a separate C window, start two Netscape
browsers (netscape &) and set the Location field on both browsers to the both.html file created in the
inter-applet communications example. Test your work by drawing lines on either of the whiteBoards;
lines drawn on either browser should appear on both browsers.
We've seen that Java provides a very powerful set of class libraries for building Internet applets and
applications. However, it's possible that you may require a special capability provided by your
operating system but not implemented in the Java class libraries. Java allows native methods to be
implemented. Of course, there is a catch. The standard for configuring IP ports is to associate the port number with a service name in the /etc/services file. The server then calls the getservbyname() subroutine to convert the service name into a port number. Since the Java class libraries do not implement this feature, we'll need to create and link a native method. Using this requirement as a premise, Figure 21 illustrates the steps required to create and link the proposed native method on AIX. Start by creating a getService.java file containing the getService class. Note the static initializer in the getService class. Static denotes the code in the braces ({}) is be executed exactly once, when the class is loaded. The Java stub (getservice.java) class must include this static method to load the shared library containing the native method. Notice how loadLibrary loads getsvc, which matches the library name (libgetsvc.so) in our makefile (Figure 22.1). The getService.java file also contains the declaration for our native byName() method.In the second step, generate the getService class file by compiling the getService.java file. We use this class file in Steps 2 and 3 (see Figure 2) to generate the C header file and the C stub file. In Step 4, we modify our wbServer to create the getService object and call the byName() method we declared in Step 2. This code replaces the line denoted by the big green "1" in the main() method of our wbServer class. Now we've completed the steps that are generic to linking native methods in any Java implementation. The remaining steps are AIX-specific. We'll discuss those next.AIX-SPECIFIC STEPSIn Step 5, we create an export file, getService.exp. The export file is required by the AIX linker (ld) command to indicate external symbols to be made available for another executable (Java) to import. Note that we exported the two symbols defined in the C stub file generated by javah. Finally, in Step 6, we create the native method itself. Notice several key points about this function:
Now that we've written all our C and Java source code, our only remaining step is to compile and link the code. Figure 22.2 provides a contents of a makefile that simplifies this requirement. Note that we've set up several variables so that our makefile can be easily modified to compile and link other native methods. If you have not already done so, enter the text from Figure 22 into a file called makefile. Once this is complete, enter the command make, to build our new wbServer. Finally, insert the line "wbSvr 8888/tcp" into the /etc/services file. Test the wbServer and whiteBoard clients as described in the "Network Communications" posted earlier. This concludes our series on Java examples. So where do you go from here? Well, the final copy of whiteBoard provided with the download package shows images as they are being drawn and allows users to draw circles and text as well as lines, so incorporate these enhancements into your applets. Try dressing up the helloWorld message by using the Blink demo provided with the JDK. Be sure to visit the IBM Centre for Java Technology Development to see what's in store for JDK V1.1. And remember this is only the beginning!
|