Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Java to JavaScript Communication

0.00/5 (No votes)
25 May 2000 1  
Give Java applets a second chance (as COM style binary components)
  • Download demo project - 5 Kb
  • Credits

    1. 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.

    2. The technical information for communicating between Java and JavaScript has been gathered from reading numerous articles on the Netscape Developer site.
    3. I first came across the term ‘Faceless applet’ while reading an article by Danny Goodman (The JavaScript Apostle on the Netscape site). Thus I give credit to Danny for coining this very apt term.

    Disclaimers

    1. 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.

    2. 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 Java applets 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:

    <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.

    <script language="Javascript">
    function SetCalculatorMode(Mode)
    {
    document.Calculator.SetCalculatorMode (Mode);
    // Alternative way to reference the applet.
    // document.applets[0].SetCalculatorMode(Mode);
    }
    </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 by JavaScript 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 applets collection.

    For example,

        document.Calculator.SetCalculatorMode(Mode);
    // or
    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,

    JSObject MainWindow = JSObject.getWindow ( this );

    public Object call ( String methodName, Object args[ ] )

    This invokes a JavaScript method from within a Java applet. For example,

    JSObject MainWindow = JSObject.getWindow ( this );
    String Arguments[ ] = {"90", "2"}; // {"Percent complete", "Time remaining"}
    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 by this. For example,

    JSObject 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 to this.name in JavaScript. For example,

    JSObject 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 to this [index] in JavaScript. For example,

    JSObject 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 to this.name = value in JavaScript. For example,

    JSObject 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 to this[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 at http://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 intermediate JavaScript 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.

    <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.

        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 intermediate JavaScript 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.

    public interface ISession
    {
    // Type is used to differentiate the actual message string
    // and can be set to &#145;Text&#146;, Hyperlink&#146; etc.

    // Should be invoked first to indicate to the server that a
    // new person has joined the chat.
    public int BeginSession(String strAuthor, String strOptions, String strType, String strMessage);

    // Should be invoked when the author wants to exit the chat.
    public int EndSession(String strAuthor, String strType, String strMessage);

    // Used to send the chat messages.
    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.

        // Get the JavaScript window that will have the various scripts that this applet will call.
    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.

    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.

    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 the m_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.

    <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.

    License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here