Java to JavaScript Communication
CREDITS
- The ideas for the Demo Chat application included along with this article are my own. All chat applications I’ve seen are either entirely Java based or HTML based. My approach is a good balance between both of these.
- The technical information for communicating between Java and JavaScript has been gathered from reading numerous articles on the
Netscape Developer site. - I first came across the term ‘Faceless
applet ’ while reading an article by Danny Goodman (TheJavaScript Apostle on the Netscape site). Thus I give credit to Danny for coining this very apt term.
DISCLAIMERS
- The techniques discussed in this article were tested using
Internet Explorer 5.0 and Netscape Navigator 4.7 on a Windows 2000 Professional machine. To the best of my knowledge, these techniques should work using versions 4.0+ of either browser but cannot guarantee this since I did not have the time to test it out with all these versions. - Since JavaScript is the only language that is supported out-of-the-box with both the major browsers, all
scripting code fragments use this language. I have previously used a commercially available plug-in from http://www.ncompasslabs.com that enables VBScript support within Netscape Navigator but when I went to their site to verify the information, the product is no longer listed there.
INTRODUCTION
I have been living and breathing modern COM for over two years now as a technical lead on the toolkit team of my company’s eCommerce product. I have understood the significance of well-designed interfaces and of implementations that work well within various environments like Visual C++, Visual Basic as well as scripting. The power of interface-based programming is forever entrenched in my mind and I try to apply it to everything I am involved in as a software engineer.
Over the past one year, experience has taught our industry that all business logic should be encapsulated within COM objects while ASP + Scripting should be used only as glue for these objects. Designing and developing infrastructure and business objects typically requires a higher skillset as compared to what is required to actually use the same. The preferred environment for developing these objects (at least in my organization) is Visual C++ / ATL / STL. Microsoft is also promoting Visual Basic as an alternative development environment for these objects.
These objects are typically referred to as faceless because they implement a lot of logic but no user interface. The presentation tier is either a rich or thin client that has logic to present information to and gather information from the end user. Such a client then uses the faceless objects to do something meaningful with that information. The whole idea is that the presentation tier typically requires a lot of customization while the business objects do not change as frequently. The changes required for the presentation tier can also be implemented using less experienced programmers.
Applying these same principles to the browser environment, it seems logical to encapsulate sophisticated client side logic within faceless, binary modules while using a scripting language to handle the presentation aspects. The options for these modules on the Windows platform are Javaapplets and ActiveX controls / servers. The focus of this article is on using Java applets for achieving this goal because applets are browser, platform and processor independent (for the most part).
A BRIEF HISTORY OF APPLETS
SUN Microsystems introduced Java applets with much fanfare back in 1995. Applets immediately took the web world by storm because they added the ability to display dynamic web content within browsers in what was essentially a static HTML world.
During those initial days, it appeared that using Java applets was the best way to add dynamic content to web pages. Microsoft initially tried to counter SUN’s offering with their ActiveX Control technology but there are two primary issues with using controls within web pages:
- These are binary modules that are processor specific and hence not very suitable for running as part of a web page. One of the primary reasons that the World Wide Web is so successful is the fact that web pages written using W3C standard HTML are (for the most part) browser and processor agnostic. ActiveX Controls just do not fit within this paradigm.
- Security is a big problem because the control writer has full access to the resources on the client machine. Signed controls allow anyone viewing a web page to make intelligent decisions about whether a particular control should be downloaded on his / her machine but all it takes is an accidental (or blissfully ignorant) click of a button to leave the client machine vulnerable to the intentions of some malicious control writer.
When Dynamic HTML finally started taking shape, things changed drastically. The Document Object Model (DOM) exposes elements within a web page as programmable components with their own set of properties and methods. Even though the implementation of dynamic HTML within the Internet Explorer and Netscape Navigator browsers is vastly different, the underlying theme of programmatically changing content using scripting code within the displayed page itself was a BIG hit. Applets suddenly started to look old and primitive. The W3C’s endorsement of Dynamic HTML finally set the tone for the new breed of sophisticated, dynamic web pages.
There are several advantages to using Java applets within a browser as listed below
- Applets work (for the most part) on multiple browsers, platforms and processors.
- The Java language is a typed language with powerful constructs.
- The JDK comes with many useful classes that are typically found only in a high-level class library.
- Security is designed into the technology and applets run within a sandbox by default. Applets must be signed if they are to break the constraints of the sandbox.
- Applets can communicate back to the web server for sending customized messages, uploading / downloading files etc. Signed applets can communicate to any server, not just the one that hosts them.
- The applet code is not viewable using the browser’s ‘View Source’ option and thus protects intellectual property.
- The Java .class files are very compact in size, resulting in faster downloads.
The disadvantages to using applets are
- Within a browser session, applets are downloaded either the first time that a page using them is displayed or if the page is later refreshed. The applet code is not resident on the client machine between browser sessions. This can actually be considered as an advantage in most situations.
- Applets take a long time to initialize.
- Since the Java .class files are byte codes that are interpreted by the Java virtual machine (JVM), applets run slower than native code.
- An applet is just a piece of real estate on the web page and does not appear seamlessly integrated into the page contents. Cascading style sheets do not directly affect the rectangular area occupied by an applet.
- Netscape Navigator 4.x has a limitation of ten (10) active applets. I am not aware of any such limitation with Internet Explorer 4.0+.
A QUICK OVERVIEW OF USING JAVA APPLETS
Java applets are included in an HTML page with the applet tag. Section 13.4 of the HTML 4.01 Specification on the W3C site documents this tag in detail. It also mentions that this tag is deprecated in favor of the <object> tag.
A sample HTML page containing an applet is shown below:
Hide Copy Code
<html> <head> <title>Calculator</title> </head> <body> <applet id="Calculator" width="300" height="500" code ="Calculator.class" codebase="."> <param name="InitialMode" value="Normal"> </applet> </body> </html>
The attributes used in the above example are explained below.
Id | The identifier for the applet instance. Client side scripting code can refer to the applet using this id. |
Width | This attribute specifies the initial width of the applet’s display area (excluding any windows or dialogs that the applet creates). Even though I have successfully used a width of zero (0) with the browsers mentioned in the Disclaimers section, it is recommended to use a value of 1 as the smallest width possible. |
Height | This attribute specifies the initial height of the applet’s display area (excluding any windows or dialogs that the applet creates). Just like with the width attribute, a value of 1 is recommended as the smallest height possible. |
Code | This attribute specifies either the name of the class file that contains the applet’s compiled applet subclass or the path to get the class, including the class file itself. It is interpreted with respect to the applet’s codebase. |
Codebase | This attribute specifies the base URI for the applet. If this attribute is not specified, then it defaults the same base URI as for the current document. |
Only the code, width and height attributes are required.
The <param> tag contains name value pairs that allow the applet to be configured when it is first started up.
A sample JavaScript function that invokes a method on the above applet is shown below.
Hide Copy Code
<script language="Javascript"> function SetCalculatorMode(Mode) { document.Calculator.SetCalculatorMode (Mode); <FONT COLOR="GREEN">// Alternative way to reference the applet.</FONT> <FONT COLOR="GREEN"> // document.applets[0].SetCalculatorMode(Mode);</FONT> } </script
DIVISION OF LABOR
In the Introduction to this article, I suggested an approach wherein the sophisticated browser side processing is encapsulated within faceless Java applets while the presentation is managed byJavaScript code. This approach requires bi-directional communication between Java and JavaScript. The next few paragraphs investigate the available options.
Accessing public members and functions exposed by a Java applet from JavaScript code is straightforward as demonstrated in the
SetCalculatorMode()
function in the previous section. An applet within a document is referred to either using it’s Id / Name or using an index into the appletscollection.
For example,
Hide Copy Code
document.Calculator.SetCalculatorMode(Mode); <FONT COLOR="GREEN">// or</FONT> document.applets[0].SetCalculatorMode(Mode);
Communication in the other direction (Java to JavaScript) is achieved using the
netscape.javascript.JSObject
and netscape.javascript.JSException
classes. In order to find out where these .class files are located, I searched my hard-drive for all files that contained the text "JSObject". To my surprise, these files are widely used in many different applications, including the Scripting Library that is part of any Visual Interdev project.
If Netscape Navigator 4.0+ is installed on your machine, these .class files are available in the Java40.jar file which itself is located in the <Navigator Installation Directory>\communicator\program\java\classes directory.
I also found these .class files in four different .zip files located in the <Windows Installation Directory>\Java\Packages directory. These .zip files were obviously installed by Microsoft products because they contain many com.ms packages. The point is that these two classes are available with either browser and you can set your CLASSPATH environment variable to any of the above paths. An alternative approach is to extract these files from the .jar or .zip files into your applet’s directory using a utility like WinZip.
THE JSOBJECT CLASS
A brief description of the JSObject class’ member functions is included for better understanding the usefulness of this class.
public static JSObject getWindow (Applet applet )
This static method returns a JSObject for the window containing the given applet. For example,Hide Copy CodeJSObject MainWindow = JSObject.getWindow ( this );
public Object call ( String methodName, Object args[ ] )
This invokes a JavaScript method from within a Java applet. For example,Hide Copy CodeJSObject MainWindow = JSObject.getWindow ( this ); String Arguments[ ] = {"90", "2"}; <FONT COLOR="GREEN">// {"Percent complete", "Time remaining"}</FONT> MainWindow.call ( "UpdateProgressIndicator", Arguments );
public Object eval ( String s )
This method evaluates a JavaScript expression. The expression is a string of JavaScript source code, which will be evalauted in the context given bythis
. For example,Hide Copy CodeJSObject MainWindow = JSObject.getWindow ( this ); JSObject UserName = MainWin.eval ( "document.UserInfoForm.UserName" );
public Object getMember ( String name )
This method retrieves an indexed member of a JavaScript object. Equivalent tothis.name
in JavaScript. For example,Hide Copy CodeJSObject MainWindow = JSObject.getWindow ( this ); JSObject DocumentPage = (JSObject)MainWindow.getMember ( "document" ); JSObject UserInfoForm = (JSObject) DocumentPage.getMember ( "UserInfoForm" ); JSObject UserName = (JSObject) UserInfoForm.getMember ( "UserName" );
public Object getSlot ( int index)
This method retrieves an indexed member of a JavaScript object. Equivalent tothis [index]
in JavaScript. For example,Hide Copy CodeJSObject MainWindow = JSObject.getWindow ( this ); JSObject DocumentPage = (JSObject)MainWindow.getMember ( "document" ); JSObject Applets = (JSObject) DocumentPage.getMember ( "applets" ); Object theApplet = Applets.getSlot ( index );
public void removeMember ( String name )
This method removes a named member of a JavaScript object.
public void setMember ( String name, Object value )
This method sets a named member of a JavaScript object. It is equivalent tothis.name = value
in JavaScript. For example,Hide Copy CodeJSObject MainWin = JSObject.getWindow ( this ); JSObject DocumentPage = (JSObject) MainWin.getMember ( "document" ); JSObject UserInfoForm = (JSObject) DocumentPage.getMember ( "UserInfoForm" ); JSObject UserName = (JSObject) UserInfoForm.getMember ( "UserName" ); UserName.setMember ( "value", "Jeremiah S. Talkar" );
public void setSlot ( int index, Object value )
This method sets an indexed member of a JavaScript object. It is equivalent tothis[index] = value
in JavaScript.
public String toString ()
This method converts a JSObject to a string.
As is clear from the examples presented above, the public methods of the JSObject class are not restricted to invoking JavaScript functions from within a JavaApplet. They also enable an applet to directly manipulate the Document Object Model (DOM) elements.
Full documentation on these classes is available athttp://developer.netscape.com/docs/manuals/communicator/jsref/pkg.htm
The documentation also explains how data types are handled between Java and JavaScript.
SIGNIFICANCE OF THE MAYSCRIPT ATTRIBUTE
Even if an applet uses the JSObject to invoke JavaScript functions or to directly access the Document Object Model, the JSObject methods will fail if the <applet> tag does not include the MAYSCRIPT attribute. This enables the page designer to determine if an applet can call out to JavaScript.
COMMUNICATION BETWEEN FACELESS APPLETS
When using faceless, reusable Java applets within a web page, it is possible that one applet may need to directly communicate with another. Such a call could also be channeled through an intermediateJavaScript function but it is always better to know all the available options.
The AppletContext interface in the java.applet package gives an applet limited access to the applet’s context of execution like the browser that the applet is runing in, the web page the applet is on as well as other applets on the same page.
For example, here is an HTML page that contains two applets.
Hide Copy Code
<html> <head> <title>Communication between applets</title> </head> <body> <applet code="CircleArea.class" name="CircleArea" width=1 height=1> </applet> <applet code="PICalculator.class" name="PICalculator" width=1 height=1> </applet> ... </body> </html>
The following code shows usage of the AppletContext object.
Hide Copy Code
AppletContext context = getAppletContext(); PICalculator PIApplet = (PICalculator) context.getApplet ( "PICalculator" ); PIApplet.getValueOfPI();
Another option is to use the
AppletContext::getApplets()
method which returns an enumeration to access all the applets within the document. Even though communications between applets is part of the standard Java applet API, it is not supported in all Java enabled browsers. Hard-coding names of other applets is also inflexible. The best approach may well be to use an intermediateJavaScript function to handle such communication.IUNKNOWN::QUERYINTERFACE IN JAVA
Class Object is the root of the class hierarchy. Every class has Object as a superclass. All objects, including arrays, implement the methods of this class. The
Object::getClass()
method returns ‘Class’ which has many useful functions to discover the details of the Java class itself. While a detailed explanation is beyond the scope of this article, I would like to point out the getInterfaces()
method that enables dynamic discovery of the interfaces implemented by a Java class.
I have not tried invoking the
getClass()
method from within JavaScript and hence cannot comment on it’s feasibility. But using an infrastructure type applet, this functionality can be easily made available to scripting code.INSTALLING THE SAMPLE FILES
The sample code for this article is packaged in the Java2JavaScript.zip file. The sample files demonstrate a chat application that has been simplified to route messages on the client side itself. In real life, the users participating in a chat are on separate machines and a message is sent to a server that then broadcasts it to all the participants.
The files that comprise the sample are
ISession.java | Source file that defines the ISession interface. |
ISession.class | Java byte-codes for the ISession interface. |
ChatClient.java | Source file for the demo ChatClient applet. |
ChatClient.class | Java byte-codes for the ChatClient applet class. |
CompileChatClient.bat | A primitive makefile for the java source files. |
TestChatClient.htm | HTML file that hosts the ChatClient applet. |
JSObject.class | Byte-codes for the JSObject class. |
JSException.class | Byte-codes for the JSException class. |
The steps to install and run the sample program are
- Unzip the Java2JavaScript.zip file into a directory of your choice on a machine running an instance of either
Personal Web Server or Internet Information Server. - Ensure that the JSObject and JSException class files are available in the netscape\javascript subdirectory under the installation directory.
- Right-click on the installation directory and select ‘Properties’.
- Click on the ‘Web Sharing’ tab and select the ‘Share this folder’ radio button, accepting the default ‘Virtual Directory’ shown in the dialog that pops up.
- Finally, start an instance of either Internet Explorer 4.0+ or Netscape Navigator 4.0+ and enter the URL http:// <machine name>/<virtual directory>/TestChatClient.htm.
Enter some text into the two input fields and click on the corresponding ‘Send’ button to see the message displayed in the chat window.
SAMPLE CODE EXPLAINED
Chat applications are a popular collaboration mechanism on the web. The two types of chat applications that I have seen are
- A Java applet that manages the user interface as well as all communication to the server.
- An HTML page that is auto-refreshed every few seconds to display any new chat messages that have been sent since the last refresh.
Recently I had to implement a production quality chat application for our eCommerce product. After a lot of thought, I decided to use a hybrid approach. First and foremost, the Java applet is a faceless applet that implements the ISession interface.
Hide Copy Code
public interface ISession { <FONT COLOR="GREEN"> // Type is used to differentiate the actual message string </FONT> <FONT COLOR="GREEN"> // and can be set to ‘Text’, Hyperlink’ etc.</FONT> <FONT COLOR="GREEN"> // Should be invoked first to indicate to the server that a </FONT> <FONT COLOR="GREEN"> // new person has joined the chat.</FONT> public int BeginSession(String strAuthor, String strOptions, String strType, String strMessage); <FONT COLOR="GREEN"> // Should be invoked when the author wants to exit the chat.</FONT> public int EndSession(String strAuthor, String strType, String strMessage); <FONT COLOR="GREEN"> // Used to send the chat messages.</FONT> public int SendMessage(String strAuthor, String strType, String strMessage); }
I have modified this interface slightly from the production version of the Chat application to include the Author parameter for both
EndSession()
as well as SendMessage()
. This is because my demo uses one applet to channel chat messages from two different authors.
The ChatClient.java file is the actual implementation of the ISession interface. The functions
init()
,start()
and stop()
are invoked by the browser if they are implemented. The JSObject representing the document window is acquired during the init()
method.
Hide Copy Code
<FONT COLOR="GREEN"> // Get the JavaScript window that will have the various scripts that this applet will call.</FONT> m_JScriptWin = JSObject.getWindow(this);
Since the Java applet calls out to two different JavaScript functions, I decided to enable the web developer to be able to specify the names of these functions as paramerters to the applet, while providing defaults for the same.
Hide Copy Code
m_strMessageHandler = getParameter("MessageHandler"); m_strErrorHandler = getParameter("ErrorHandler");
BeginSession()
and EndSession()
are dummy implementations that just call SendMessage()
.SendMessage()
calls the JavaScript function whose name is specified in the m_strMessageHandler member variable. The default value is "HandleSessionMessage". The relevant code is shown here.
Hide Copy Code
if (m_JScriptWin != null) { String Arguments[] = {strAuthor, strType, strMessage}; m_JScriptWin.call(m_strMessageHandler, Arguments); }
HandleSessionError()
invokes a JavaScript function whose name is specified in them_strErrorHandler
member variable. The default value is "HandleSessionError".
The TestChatClient.htm file deals with the presentation aspects of the chat. The applet is included on the page using the <applet> tag.
Hide Copy Code
<applet id="ChatApplet" width="1" height="1" code="ChatClient.class" codebase="." VIEWASTEXT mayscript> <param name="MessageHandler" value="HandleSessionMessageEx"> <param name="ErrorHandler" value="HandleSessionErrorEx"> </applet>
The parameters specify names for the two JavaScript functions that the applet invokes. I’ve just indicated names other than the default to demonstrate how flexible this can be.
The two forms on the page simulate two people chatting with each other. The corresponding HTML is straightforward.
The actual messages themselves are displayed within the ChatMessages <DIV>. In the case of Internet Explorer, I use the Table Object Model to display each message in a separate row. Hence the ChatMessagesTable definition within the above DIV.
Finally, the
HandleSessionMessagesEx()
JavaScript function handles all the presentation aspects. Within Internet Explorer, a new row is added to the ChatMessagesTable table for every message that is sent. The scrollbar is displayed if required. Within Netscape Navigator, I append the new message to the Messages variable and use the latter to update the ChatMessages <DIV>. Since scrollbars cannot automatically be displayed within a Netscape <DIV> (which is really a LAYER), I display the last message received at the top. I have found articles on how to support scrollbars for LAYERs within Navigator, but that is not relevant for this demonstration.FINAL THOUGHTS
This article attempts to present some (neat) techniques for implementing your browser side logic. As I have mentioned earlier in the article, the
JSObject
is widely used by many applications, including Microsoft Corporation. All the same, carefully consider your individual situation to determine if the techniques presented here are applicable.
As for the demonstration sample that accompanies this article, I feel that allowing the presentation of the chat to be implemented in JavaScript / DHTML enables this code to be maintained by an entry level / junior programmer. Customization of the user interface is also easier using DHTML / JavaScript. Additionally, it allows for more powerful presentation techniques that seem consistent with the rest of the page contents.
In the production version of this application, I’ve added support for exchanging hyperlinks that open up on the participant’s machine, dynamic selection of colors for messages using cascading style sheets etc.
Any feedback is welcome.
0 comments:
Post a Comment