This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.


MIND


java911@microsoft.com         Download the code (10KB)
Jonathan Locke

CGI Joe to the Rescue!

I've been trying to make a Java CGI program that processes an HTML form. I'm using Internet Information Server (IIS) 4.0, running on Windows NT® Server 4.0. So far, I've had no luck. Can you explain how to do this?

Although one certainly can create a CGI program in Java, it's a much easier task to write an Active Server Page (ASP) that accesses a Java object through COM (especially since you're already running IIS). By taking the ASP/COM route, you can avoid writing a Java native method to access server environment variables and reading and parsing form parameters posted through standard input. With ASP/COM, a few simple method calls take care of it all.
      The JavaASPTest.asp HTML file defines a form with a text input field called InputValue:


 <html>
 <body>
 <h1>Java ASP Test</h1>
 
 <form method="post" action="Handler.asp">
     Enter a value to pass to Java:<p>
     <input name="InputValue" value="2" type="text" size="37">
     <input type="submit" value="submit">
 <form>
 
 <hr>
 </body>
 </html>
The initial value of the InputValue field is 2. The HTML form's method is set to post, and the action that is executed when the user hits Return (or pushes the form's submit button) is to invoke the Handler.asp page.
      The Handler.asp page creates a COM object by asking the page's Server object to create a COM object corresponding to the progid Java911.JavaASPHandler:

 <html>
 <body>
 <h1>Handler!</h1>
 
     <%
     'Create a Handler object
     Set obj = Server.CreateObject("Java911.JavaASPHandler")
     obj.handleRequest Request, Response
     %>
 
 <hr>
 </body>
 </html>
This invokes the Java Virtual Machine (VM), which loads the JavaASPHandler class and returns a new instance of it as a COM object. The reference returned by Server.CreateObject is then saved in the VBScript variable named obj. This object reference is then used to call obj's handleRequest method, passing it the Request and Response objects for the current scripting context. These Request and Response objects are—you guessed it!—COM objects. These particular COM objects can be conveniently accessed through a set of Java interfaces defined in com.ms.asp. The interfaces in this package enable Java code to read information from an HTML form (in this case, the form that was defined in JavaASPTest.asp) and to compose a response.
      The source code for the JavaASPHandler class (the class registered under the progid Java911.JavaASPHandler) is shown in Figure 1. The handleRequest method, called from Handler.asp, takes an IRequest and an IResponse interface (both defined in com.ms.asp.* and shown in Figure 2) as arguments. In order to retrieve the form value from the originating page, I call IRequest.getForm to retrieve an IRequestDictionary interface to form data. Then I create a com.ms.com.Variant object representing the InputValue key string and pass that to the dictionary interface's getItem method. This retrieves the corresponding data from the form and returns it as a Variant, v.

Java Tip of the Month
      For easy access to the Windows® registry, go with the Microsoft® SDK for Java 2.0. Just import com.ms.lang.* and check out the sources in your %windir%\java\classes\com\ms\lang directory

      Now that I've got the form data, I can compose an HTML response. I do this by first converting the Variant information held in v to a String (by calling v.toString) to produce the original value. I then convert the same Variant to an integer (by calling v.toInt), multiply the result by two, and concatenate the doubled value onto the end of the response string. Finally, I convert the whole response string to a Variant and pass that value to IResponse.Write, which appends the value to the page's HTML response buffer. When the flow of control returns to the browser, the Java-composed HTML response created by handleRequest will appear as part of the Handler.asp page.
       After building the JavaASPHandler class with jvc or javac, it needs to be registered as a COM object and copied into %windir%\java\trustlib so that the VM can find it. You can do this from the command line like this:

 C:\MIND\911> copy JavaASPHandler.class %windir%\java\trustlib 
 C:\MIND\911> javareg /register /class:JavaASPHandler /progid:Java911.JavaASPHandler
A batch file called reg.bat supplied with the online source code performs these two commands. Once you have registered the JavaASPHandler class, you must copy JavaASPTest.asp and Handler.asp into an appropriate directory so that IIS can publish the files. In the default installation of IIS, a good place would be C:\Inetpub\wwwroot. You can then invoke the example page by starting up Microsoft Internet Explorer and surfing to http://localhost/JavaASPTest.asp. Figures 3 and 4 show the pages you should see.
Figure 3: JavaASPTest.asp Figure 4: Handler.asp
Figure 3: JavaASPTest.asp Figure 4: Handler.asp

Java Resource of the Month
      Want to test drive that new Java book before you buy it? Developer.com has a very cool online reference library that includes the full text of many popular Java books—

http://www.developer.com/reference/r_java.html


Is it possible for two applets to communicate with each other?

Yes. If the applets are on the same Web page, there are two easy ways to accomplish this. The easiest approach, illustrated in Figure 5, is to simply use static variables and methods to communicate between applets. This works because, at present, applets running on the same page are loaded into the same Java VM. Even though the classes are referenced by separate HTML statements in the page, the classes loaded by the VM are visible to each other.
Figure 6: Communicating Applets
Figure 6: Communicating Applets
       Figure 6 shows both applets in action in the Applet12.html page. As keystrokes are entered into Applet 1, the TextListener's textValueChanged method (which requires full JDK 1.1 support) simply calls Applet 2's static setText method which updates Applet 2's label directly.
       The other way for two applets on the same page to communicate with one another is to look each other up through the AppletContext class, shown in Figure 7. Applet 3, shown in Figure 8, first calls the getAppletContext method to obtain an AppletContext interface. By calling the getApplet method of the AppletContext interface, Applet 3 can look up the Applet4 object (shown in Figure 9) by name. The name for an applet can be specified in the HTML <applet> tag, as shown in Figure 10. Once Applet 3 has a reference to Applet 4, it can cast that object to the SetText interface (which Applet 4 implements) and call Applet 4's setText method.
       Unfortunately, communication between two applets that are not on the same page in the same browser is not quite as easy. The best and most general approach would be to have the applets communicate through the server using socket connections.

I have a class that holds a reference to a native resource in a static variable (it's a Win32® mutex handle). How can I ensure that variable gets finalized?

Unfortunately, you can't simply make your finalize method static. The only way to accomplish this is to create an instance finalizer and keep track of how many instances of the object there are. When the instance count drops to zero, you can clean up your static mutex handle. Figure 11 demonstrates how to do this. The output you get from running the code will look like this:


 J:\mind\911>java StaticFinalizer
 Creating object (1)
 Creating object (2)
 Creating object (3)
 Creating object (4)
 Creating object (5)
 Freeing object (5)
 Freeing object (4)
 Freeing object (3)
 Freeing object (2)
 Freeing object (1)
 Freeing native resource 123


From the May 1998 issue of Microsoft Interactive Developer.