JavaScript not being blocked/synched by Applet init()

Discussion in 'Java' started by Richard Maher, Apr 22, 2009.

  1. Hi,

    I'm probably seeing-things again but here goes: -

    IE6 with JRE 1.6.0_12 looks to continue the Javascript processing while my
    Applet.init() has yet to return. FireFox is fine and when I went for a small
    reproducer IE also performed as expected. (Both with Applet appended in a
    <div> or document.writeN() as an <object> in the body)

    See below for a reasonable code snippet, but the critical bit is this: -

    var tier3Chan;
    try {
    document.body.appendChild(appletDiv);
    tier3Chan = document.getElementById(appletId);
    alert("Auth = " + tier3Chan.getThree());
    var userAuthorized = tier3Chan.isAuthorized();
    }
    catch(err) {
    alert("Err =" + err.description);
    tier3Chan = null;
    };


    If I take out that 'alert("Auth =' bit then isAuthorised() gets called and
    returns false even though the user hasn't had a chance to enter their
    Username/Password yet. (Pop-up dialog currently sitting on the screen)

    I understand when it would be valid to let the JS run past the
    getElementById so I normally stick a method call (such as isAuthorized()) in
    their to force the block-for-init but this time it doesn't seem to work :-(

    For a similar setup please see: -
    http://manson.vistech.net/t3$examples/demo_client_flex.html
    Username: TIER3_DEMO
    Password: QUEUE

    All (slightly dated) Java/Javascript/HTML source code is at: -
    http://manson.vistech.net/t3$examples/

    Unfortunately that example works but the one below doesn't :-(

    Anyone know the mechanics behind what Javascript is looking for on IE to
    tell it that the Applet has finished init()ing? Or how I might be stomping
    on it? (Or at least failing to flag it?)

    Cheers Richard Maher


    /**
    * Copyright (c) Richard Maher. All rights reserved.
    */

    function Tier3Client(application,
    codeBase,
    port,
    maxBuf,
    hostCharSet,
    sslReqd)
    {
    this.application = application;
    this.codeBase = codeBase;
    this.port = port;
    this.maxBuf = maxBuf;
    this.hostCharSet = hostCharSet;
    this.sslReqd = sslReqd;

    var appletId = "Tier3__" + application + "_Applet";

    try {
    var idTaken = document.getElementById(appletId);
    }
    catch (err) {};

    if (idTaken != null) {
    throw new Error("Tier3 Client already registered for " +
    this.application);
    return;
    }

    var archiveName = "tier3Client.jar";
    var className = "tier3Client/Tier3Application";

    var appletParams = [{"name":"archive", "value":archiveName},
    {"name":"codebase", "value":codeBase },
    {"name":"code", "value":className },
    {"name":"mayscript", "value":"true" },
    {"name":"scriptable", "value":"true" },
    {"name":"APPLICATION", "value":application},
    {"name":"PORT", "value":port },
    {"name":"MAXBUF", "value":maxBuf },
    {"name":"HOSTCHARSET", "value":hostCharSet},
    {"name":"SSLREQD", "value":sslReqd }];
    var startParam = 0;

    var objectTag = "<object classid=";

    if (/Internet Explorer/.test(navigator.appName)) {
    objectTag = objectTag +
    '"clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" ';
    } else {
    objectTag = objectTag +
    '"java:' + className + '.class" type="application/x-java-applet
    " ' +
    'archive="' + codeBase + archiveName + '"';
    startParam = 1;
    }

    objectTag = objectTag + ' width= "0" height= "0" id="' + appletId +
    '">';

    for (i=startParam; i<appletParams.length; i++){
    objectTag = objectTag + '<param name ="' + appletParams.name +
    '" ' +
    'value ="' + appletParams.value +
    '">';
    }

    objectTag = objectTag + "</object>";

    var appletDiv = document.createElement("div");
    appletDiv.innerHTML = objectTag;

    var tier3Chan;
    try {
    document.body.appendChild(appletDiv);
    tier3Chan = document.getElementById(appletId);
    alert("Auth = " + tier3Chan.getThree());
    var userAuthorized = tier3Chan.isAuthorized();
    }
    catch(err) {
    alert("Err =" + err.description);
    tier3Chan = null;
    };
    alert("After check");
    if (tier3Chan == null) {
    throw new Error("Tier3 was unable to initialize the applet for " +
    this.application);
    return;
    } else {
    if (!userAuthorized) {
    throw new Error("Tier3 User authentication unsuccessful for " +
    this.application);
    return;
    }
    }

    this.chan = tier3Chan;

    Tier3Client.applications[this.application] = this;

    return this;
    }
    Richard Maher, Apr 22, 2009
    #1
    1. Advertising

  2. (Shameless bump.)

    Just in case you were on school holidays and missed the opportunity to solve
    this conundrum, here it is again :)

    Cheers Richard Maher

    "Richard Maher" <> wrote in message
    news:gsmp8k$hfo$...
    > Hi,
    >
    > I'm probably seeing-things again but here goes: -
    >
    > IE6 with JRE 1.6.0_12 looks to continue the Javascript processing while my
    > Applet.init() has yet to return. FireFox is fine and when I went for a

    small
    > reproducer IE also performed as expected. (Both with Applet appended in a
    > <div> or document.writeN() as an <object> in the body)
    >
    > See below for a reasonable code snippet, but the critical bit is this: -
    >
    > var tier3Chan;
    > try {
    > document.body.appendChild(appletDiv);
    > tier3Chan = document.getElementById(appletId);
    > alert("Auth = " + tier3Chan.getThree());
    > var userAuthorized = tier3Chan.isAuthorized();
    > }
    > catch(err) {
    > alert("Err =" + err.description);
    > tier3Chan = null;
    > };
    >
    >
    > If I take out that 'alert("Auth =' bit then isAuthorised() gets called and
    > returns false even though the user hasn't had a chance to enter their
    > Username/Password yet. (Pop-up dialog currently sitting on the screen)
    >
    > I understand when it would be valid to let the JS run past the
    > getElementById so I normally stick a method call (such as isAuthorized())

    in
    > their to force the block-for-init but this time it doesn't seem to work

    :-(
    >
    > For a similar setup please see: -
    > http://manson.vistech.net/t3$examples/demo_client_flex.html
    > Username: TIER3_DEMO
    > Password: QUEUE
    >
    > All (slightly dated) Java/Javascript/HTML source code is at: -
    > http://manson.vistech.net/t3$examples/
    >
    > Unfortunately that example works but the one below doesn't :-(
    >
    > Anyone know the mechanics behind what Javascript is looking for on IE to
    > tell it that the Applet has finished init()ing? Or how I might be stomping
    > on it? (Or at least failing to flag it?)
    >
    > Cheers Richard Maher
    >
    >
    > /**
    > * Copyright (c) Richard Maher. All rights reserved.
    > */
    >
    > function Tier3Client(application,
    > codeBase,
    > port,
    > maxBuf,
    > hostCharSet,
    > sslReqd)
    > {
    > this.application = application;
    > this.codeBase = codeBase;
    > this.port = port;
    > this.maxBuf = maxBuf;
    > this.hostCharSet = hostCharSet;
    > this.sslReqd = sslReqd;
    >
    > var appletId = "Tier3__" + application + "_Applet";
    >
    > try {
    > var idTaken = document.getElementById(appletId);
    > }
    > catch (err) {};
    >
    > if (idTaken != null) {
    > throw new Error("Tier3 Client already registered for " +
    > this.application);
    > return;
    > }
    >
    > var archiveName = "tier3Client.jar";
    > var className = "tier3Client/Tier3Application";
    >
    > var appletParams = [{"name":"archive", "value":archiveName},
    > {"name":"codebase", "value":codeBase },
    > {"name":"code", "value":className },
    > {"name":"mayscript", "value":"true" },
    > {"name":"scriptable", "value":"true" },
    > {"name":"APPLICATION", "value":application},
    > {"name":"PORT", "value":port },
    > {"name":"MAXBUF", "value":maxBuf },
    > {"name":"HOSTCHARSET", "value":hostCharSet},
    > {"name":"SSLREQD", "value":sslReqd }];
    > var startParam = 0;
    >
    > var objectTag = "<object classid=";
    >
    > if (/Internet Explorer/.test(navigator.appName)) {
    > objectTag = objectTag +
    > '"clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" ';
    > } else {
    > objectTag = objectTag +
    > '"java:' + className + '.class"

    type="application/x-java-applet
    > " ' +
    > 'archive="' + codeBase + archiveName + '"';
    > startParam = 1;
    > }
    >
    > objectTag = objectTag + ' width= "0" height= "0" id="' + appletId +
    > '">';
    >
    > for (i=startParam; i<appletParams.length; i++){
    > objectTag = objectTag + '<param name ="' + appletParams.name

    +
    > '" ' +
    > 'value ="' + appletParams.value

    +
    > '">';
    > }
    >
    > objectTag = objectTag + "</object>";
    >
    > var appletDiv = document.createElement("div");
    > appletDiv.innerHTML = objectTag;
    >
    > var tier3Chan;
    > try {
    > document.body.appendChild(appletDiv);
    > tier3Chan = document.getElementById(appletId);
    > alert("Auth = " + tier3Chan.getThree());
    > var userAuthorized = tier3Chan.isAuthorized();
    > }
    > catch(err) {
    > alert("Err =" + err.description);
    > tier3Chan = null;
    > };
    > alert("After check");
    > if (tier3Chan == null) {
    > throw new Error("Tier3 was unable to initialize the applet for " +
    > this.application);
    > return;
    > } else {
    > if (!userAuthorized) {
    > throw new Error("Tier3 User authentication unsuccessful for "

    +
    > this.application);
    > return;
    > }
    > }
    >
    > this.chan = tier3Chan;
    >
    > Tier3Client.applications[this.application] = this;
    >
    > return this;
    > }
    >
    >
    Richard Maher, Apr 27, 2009
    #2
    1. Advertising

  3. Hi,

    I've come up with a small reproducer (see below) that I hope will help
    someone sched light on what's going on. (Also a related SDN Bug ID 6742814
    may be of some help: -
    http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6742814 )

    In a nutshell with IE6 the Javascript resumes as soon as the init() method
    has called JSObject.getWindow(this) but *before* the init() method has
    completed/returned, as can be evidenced from the getNum() results. (Nice
    trick!) Try it on FireFox to see the difference.

    Is this a new bug that was introduced when trying to fix a "freeze" with
    JSObject.Call()? If not, how is one ever supposed to synchronize the
    completion of Applet initialization? "Callbacks" a la mode de Adobe
    FABridge?

    I'll do some more testing with other browsers/versions but surely this can't
    be right? Possibly fixed in a later version of IE, JRE, or LiveConnect?

    Cheers Richard Maher

    Sleeper.java
    =========

    import java.applet.Applet;
    import netscape.javascript.JSObject;
    import netscape.javascript.JSException;
    import java.lang.InterruptedException;

    public class Sleeper extends Applet {
    private int myNum = 0;
    private JSObject browser;

    public void init() {
    try {
    browser = JSObject.getWindow(this); }
    catch (netscape.javascript.JSException e) {
    e.printStackTrace(); }
    catch (Exception e) {
    e.printStackTrace(); }

    System.out.println("Before sleep call");
    try {
    Thread.sleep(5000);
    }
    catch (InterruptedException e){
    e.printStackTrace();
    }
    System.out.println("After sleep call");
    myNum = 33;
    }

    public int getNum(){
    int i = myNum++;
    System.out.println("in getNum " + myNum);
    return i;
    }

    }

    Sleeper.html
    =========


    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">

    <html>

    <meta name="author" content="Richard Maher"/>
    <meta name="description" content="JS Function and Applet Test"/>

    <head>


    <style>

    body
    {
    margin: 0px;
    background-color: white;
    color: Black;
    font-family: times;
    font-size: 16px;
    border: medium ridge;
    }

    </style>

    <script type="text/javascript">

    function load() {
    var lclNum;
    var chan;
    try {
    chan = document.getElementById("Sleeper");
    lclNum = chan.getNum();
    lclNum = chan.getNum();
    lclNum = chan.getNum();
    }
    catch (err) {
    alert("In catch " + err.description);
    }
    if (chan == null) alert("chan is null");
    alert(chan.getNum());
    }

    </script>

    </head>

    <body onload="load();">

    <br /><h2>Test it</h2><hr /><br />

    <form name="display" style="margin-left: 100px;">

    <input
    type="text"
    style="text-align: Left;"
    name="next"
    size=10
    />
    </form>

    <script type="text/javascript">

    var myDef;
    if (navigator.appName == "Microsoft Internet Explorer")
    myDef =
    '<object classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" ' +
    'width= "0" height= "0" id="Sleeper">'
    +
    '<param name="code" value="Sleeper">'
    +
    '<param name="mayscript" value="true">' +
    '<param name="scriptable" value="true">' +
    '</object>'
    else
    myDef =
    '<object classid="java:Sleeper.class" '
    +
    'type="application/x-java-applet" ' +
    'width= "0" height= "0" id="Sleeper">'
    +
    '<param name="code" value="Sleeper">'
    +
    '<param name="mayscript" value="true">' +
    '<param name="scriptable" value="true">' +
    '</object>'

    document.write(myDef);
    </script>

    </body>

    </html>

    "Richard Maher" <> wrote in message
    news:gsmp8k$hfo$...
    > Hi,
    >
    > I'm probably seeing-things again but here goes: -
    >
    > IE6 with JRE 1.6.0_12 looks to continue the Javascript processing while my
    > Applet.init() has yet to return. FireFox is fine and when I went for a

    small
    > reproducer IE also performed as expected. (Both with Applet appended in a
    > <div> or document.writeN() as an <object> in the body)
    >
    > See below for a reasonable code snippet, but the critical bit is this: -
    >
    > var tier3Chan;
    > try {
    > document.body.appendChild(appletDiv);
    > tier3Chan = document.getElementById(appletId);
    > alert("Auth = " + tier3Chan.getThree());
    > var userAuthorized = tier3Chan.isAuthorized();
    > }
    > catch(err) {
    > alert("Err =" + err.description);
    > tier3Chan = null;
    > };
    >
    >
    > If I take out that 'alert("Auth =' bit then isAuthorised() gets called and
    > returns false even though the user hasn't had a chance to enter their
    > Username/Password yet. (Pop-up dialog currently sitting on the screen)
    >
    > I understand when it would be valid to let the JS run past the
    > getElementById so I normally stick a method call (such as isAuthorized())

    in
    > their to force the block-for-init but this time it doesn't seem to work

    :-(
    >
    > For a similar setup please see: -
    > http://manson.vistech.net/t3$examples/demo_client_flex.html
    > Username: TIER3_DEMO
    > Password: QUEUE
    >
    > All (slightly dated) Java/Javascript/HTML source code is at: -
    > http://manson.vistech.net/t3$examples/
    >
    > Unfortunately that example works but the one below doesn't :-(
    >
    > Anyone know the mechanics behind what Javascript is looking for on IE to
    > tell it that the Applet has finished init()ing? Or how I might be stomping
    > on it? (Or at least failing to flag it?)
    >
    > Cheers Richard Maher
    >
    >
    > /**
    > * Copyright (c) Richard Maher. All rights reserved.
    > */
    >
    > function Tier3Client(application,
    > codeBase,
    > port,
    > maxBuf,
    > hostCharSet,
    > sslReqd)
    > {
    > this.application = application;
    > this.codeBase = codeBase;
    > this.port = port;
    > this.maxBuf = maxBuf;
    > this.hostCharSet = hostCharSet;
    > this.sslReqd = sslReqd;
    >
    > var appletId = "Tier3__" + application + "_Applet";
    >
    > try {
    > var idTaken = document.getElementById(appletId);
    > }
    > catch (err) {};
    >
    > if (idTaken != null) {
    > throw new Error("Tier3 Client already registered for " +
    > this.application);
    > return;
    > }
    >
    > var archiveName = "tier3Client.jar";
    > var className = "tier3Client/Tier3Application";
    >
    > var appletParams = [{"name":"archive", "value":archiveName},
    > {"name":"codebase", "value":codeBase },
    > {"name":"code", "value":className },
    > {"name":"mayscript", "value":"true" },
    > {"name":"scriptable", "value":"true" },
    > {"name":"APPLICATION", "value":application},
    > {"name":"PORT", "value":port },
    > {"name":"MAXBUF", "value":maxBuf },
    > {"name":"HOSTCHARSET", "value":hostCharSet},
    > {"name":"SSLREQD", "value":sslReqd }];
    > var startParam = 0;
    >
    > var objectTag = "<object classid=";
    >
    > if (/Internet Explorer/.test(navigator.appName)) {
    > objectTag = objectTag +
    > '"clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" ';
    > } else {
    > objectTag = objectTag +
    > '"java:' + className + '.class"

    type="application/x-java-applet
    > " ' +
    > 'archive="' + codeBase + archiveName + '"';
    > startParam = 1;
    > }
    >
    > objectTag = objectTag + ' width= "0" height= "0" id="' + appletId +
    > '">';
    >
    > for (i=startParam; i<appletParams.length; i++){
    > objectTag = objectTag + '<param name ="' + appletParams.name

    +
    > '" ' +
    > 'value ="' + appletParams.value

    +
    > '">';
    > }
    >
    > objectTag = objectTag + "</object>";
    >
    > var appletDiv = document.createElement("div");
    > appletDiv.innerHTML = objectTag;
    >
    > var tier3Chan;
    > try {
    > document.body.appendChild(appletDiv);
    > tier3Chan = document.getElementById(appletId);
    > alert("Auth = " + tier3Chan.getThree());
    > var userAuthorized = tier3Chan.isAuthorized();
    > }
    > catch(err) {
    > alert("Err =" + err.description);
    > tier3Chan = null;
    > };
    > alert("After check");
    > if (tier3Chan == null) {
    > throw new Error("Tier3 was unable to initialize the applet for " +
    > this.application);
    > return;
    > } else {
    > if (!userAuthorized) {
    > throw new Error("Tier3 User authentication unsuccessful for "

    +
    > this.application);
    > return;
    > }
    > }
    >
    > this.chan = tier3Chan;
    >
    > Tier3Client.applications[this.application] = this;
    >
    > return this;
    > }
    >
    >
    Richard Maher, May 9, 2009
    #3
  4. Richard Maher

    Mark Space Guest

    Richard Maher wrote:

    > trick!) Try it on FireFox to see the difference.


    I get the same thing in both IE and FF. I see Test it, a horizontal
    rule and a blank form field.

    I did redo the program with a lot of scratch work. What am I supposed to
    see?
    Mark Space, May 9, 2009
    #4
  5. "Mark Space" <> wrote in message
    news:cd6Nl.32805$...
    > Richard Maher wrote:
    >
    > > trick!) Try it on FireFox to see the difference.

    >
    > I get the same thing in both IE and FF. I see Test it, a horizontal
    > rule and a blank form field.
    >
    > I did redo the program with a lot of scratch work. What am I supposed to
    > see?


    On Firefox 2 the "alert(chan.getNum())" should result in the number "36" in
    the alert box, and the Java Console would contain: -

    Before sleep call
    After sleep call
    in getNum 34
    in getNum 35
    in getNum 36
    in getNum 37

    While over on IE6 the alert box would contain the number "3" and the Java
    Console would contain: -

    in getNum 1
    in getNum 2
    in getNum 3
    in getNum 4
    Before sleep call
    After sleep call

    If you're not seeing this then please let me know what versions of IE and
    JRE you're using. If you are seeing the above then try removing the call to
    JSObject.getWindow(this) to restore sanity.

    Regards Richard Maher
    Richard Maher, May 9, 2009
    #5
  6. Richard Maher

    Mark Space Guest

    Richard Maher wrote:

    >
    > On Firefox 2 the "alert(chan.getNum())" should result in the number "36" in
    > the alert box, and the Java Console would contain: -


    >
    > If you're not seeing this then please let me know what versions of IE and
    > JRE you're using. If you are seeing the above then try removing the call to
    > JSObject.getWindow(this) to restore sanity.



    Thanks for verifying. On both IE 8 and FF 3 I see a pop-up with the
    number 3. So I think IE 7 is correct and FF 2 is the buggy one.

    The solution is obvious and you mentioned it yourself. Synchronize the
    access of init and getNum. Just add the key word "synchronized" to both
    method declarations and both IE and FF display 36. I tested this in IE
    8 and FF 3, works fine.
    Mark Space, May 9, 2009
    #6
  7. Hi Mark,

    "Mark Space" <> wrote in message
    news:W_hNl.29577$...
    > Richard Maher wrote:
    >
    > >
    > > On Firefox 2 the "alert(chan.getNum())" should result in the number "36"

    in
    > > the alert box, and the Java Console would contain: -

    >
    > >
    > > If you're not seeing this then please let me know what versions of IE

    and
    > > JRE you're using. If you are seeing the above then try removing the call

    to
    > > JSObject.getWindow(this) to restore sanity.

    >
    >
    > Thanks for verifying. On both IE 8 and FF 3 I see a pop-up with the
    > number 3. So I think IE 7 is correct and FF 2 is the buggy one.


    Upon re-reading that bug report I quoted, I've come to the conclusion that
    (for whatever compelling reasons) it was a deliberate break of
    upward-compatibility and the laws of browser-physics as we knew them
    pre-Java6. (Java 1.4 and I'm guessing 5 behave "as expected" with IE6)

    A couple of relevant-sounding quotes from that bug report from Sept last
    year: -
    {
    The rules for initiating JavaScript-to-Java and Java-to-JavaScript
    calls (which will be formalized in the forthcoming new LiveConnect
    specification) are:

    - JavaScript-to-Java calls against a given applet block until that
    applet has completed init(), or

    - that applet initiates a Java-to-JavaScript call in init().
    }

    The definition of "initiates a Java-to-JavaScript" in that last line appears
    to have been further broadened and amplified to include: -
    {
    - If a request comes to the browser from an applet to fetch the
    JavaScript window object corresponding to the applet, drain the
    queued up messages corresponding to JavaScript-to-Java calls,
    which would otherwise occur when init() was completed.
    }

    So it appears that through the wonders of Java6 we now have your init()
    method and your JavaScript executing in parallel (presumably in seperate
    threads), but *only* if you're doing something with JSObject. And for the
    squeamish among us that like our initialization to finish before the
    mainline methods start crunching numbers, there's now a need for
    intervention.

    I do glance through the JRE release notes when they come out but can't
    recall seeing this one; anyone else?
    >
    > The solution is obvious and you mentioned it yourself. Synchronize the
    > access of init and getNum. Just add the key word "synchronized" to both
    > method declarations and both IE and FF display 36. I tested this in IE
    > 8 and FF 3, works fine.


    Well it's certainly obvious now that you've told me :) Thanks for the
    answer and thanks for trying it out on the other browsers for me. I had
    finer-grained synchronization blocks in my methods but your solution is
    simple and, what's far more important, effective.

    Thanks again.

    Cheers Richard Maher

    PS. Anyone got a link to this "forthcoming new LiveConnect specification"?
    Richard Maher, May 10, 2009
    #7
  8. "Richard Maher" <> wrote in message
    news:gu56jd$he8$...

    > PS. Anyone got a link to this "forthcoming new LiveConnect specification"?
    >


    I found this think for those who will also be looking. (I found the bug
    report to be less ambiguous in its terminology, but anyway here's the rules)

    https://jdk6.dev.java.net/plugin2/liveconnect/

    Cheers Richard Maher
    Richard Maher, May 12, 2009
    #8
  9. Richard Maher

    Mark Space Guest

    Richard Maher wrote:
    > "Richard Maher" <> wrote in message
    > news:gu56jd$he8$...
    >
    >> PS. Anyone got a link to this "forthcoming new LiveConnect

    specification"?
    >>

    >
    > I found this think for those who will also be looking. (I found the bug
    > report to be less ambiguous in its terminology, but anyway here's the

    rules)
    >
    > https://jdk6.dev.java.net/plugin2/liveconnect/
    >



    While direct from Sun, I'm pretty sure it's incorrect:

    "The JavaScript engines in all of today's web browsers are conceptually
    single threaded with respect to the web page. The Java language,
    however, is inherently multithreaded. If multiple Java threads attempt
    to call into the JavaScript engine, only one will be allowed through at
    any given time. The rest of the threads will wait for one of two
    situations to occur: either the initial Java-to-JavaScript call
    completes, or a JavaScript-to-Java call is made. In either of these
    occurrences, the JavaScript engine once again becomes "available" for
    Java-to-JavaScript calls. If multiple Java threads were attempting to
    make concurrent calls to the JavaScript engine, an arbitrary one will be
    selected for its call to proceed."


    JavaScript IS NOT single threaded. It can receive events from outside
    sources (hello XMLHttpRequest) and will spawn additional threads of
    execution. Since there's no synchronization method in JavaScript, this
    can be a huge hassle. There's an algorithm available to synchronize
    threads using only shared memory. Read on:


    <http://www.developer.com/lang/jscript/article.php/3592016>


    Anyway, with regard to Java, I think the best policy is to assume your
    JApplet is being accessed in a multithreaded environment and program
    defensively. I'd make all methods visible to JavaScript "synchronized",
    including redefining all JApplet methods just to make them synchronized.

    (I refuse to redefine the entire JComponent hierarchy, which is huge.
    This is one instance where one must just pray that these methods are
    never invoked. I don't think there's any way to synchronize a parent
    classes methods. Although if you know a specific method will be call
    (setSize() is common) synchronize that.)
    Mark Space, May 12, 2009
    #9
  10. Mark Space wrote:
    > JavaScript IS NOT single threaded. It can receive events from outside
    > sources (hello XMLHttpRequest) and will spawn additional threads of
    > execution. Since there's no synchronization method in JavaScript, this
    > can be a huge hassle. There's an algorithm available to synchronize
    > threads using only shared memory. Read on:


    I believe that, in the case of XMLHttpRequest, in Mozilla, everything is
    proxied back to the display thread. The definition of XMLHttpRequest
    also appears to not be thread-safe, which means that using the object
    from multiple threads is more or less A Bad Thing™.

    Although the SpiderMonkey engine is very much capable of doing
    multithreaded execution, the DOM itself is not threadsafe and has to be
    modified from a single thread, so must browser JS ends up running in one
    thread. Hence the statement: "The JavaScript engines in all of today's
    web browsers are conceptually single threaded with respect to the web page."

    Yes, I am aware of DOM workers, but these do not allow concurrent access
    to the DOM:
    "The DOM APIs (Node objects, Document objects, etc) are not available
    to workers in this version of this specification."
    <http://www.whatwg.org/specs/web-workers/current-work/>.

    --
    Beware of bugs in the above code; I have only proved it correct, not
    tried it. -- Donald E. Knuth
    Joshua Cranmer, May 12, 2009
    #10
  11. Richard Maher

    Mark Space Guest

    Joshua Cranmer wrote:

    > Although the SpiderMonkey engine is very much capable of doing
    > multithreaded execution, the DOM itself is not threadsafe and has to be
    > modified from a single thread, so must browser JS ends up running in one
    > thread. Hence the statement: "The JavaScript engines in all of today's
    > web browsers are conceptually single threaded with respect to the web
    > page."



    And Richard Maher was able to create concurrent access to his Java
    applet pretty much by accident. I don't think I really believe the
    documentation in this regard. The synchronization to make JavaScript
    single thread seems buggy at best, non-existent at worse. And this is
    from both IE and FF.
    Mark Space, May 12, 2009
    #11
  12. Hi Mark,

    "Mark Space" <> wrote in message
    news:Er6Ol.22158$...
    > Joshua Cranmer wrote:
    >
    > > Although the SpiderMonkey engine is very much capable of doing
    > > multithreaded execution, the DOM itself is not threadsafe and has to be
    > > modified from a single thread, so must browser JS ends up running in one
    > > thread. Hence the statement: "The JavaScript engines in all of today's
    > > web browsers are conceptually single threaded with respect to the web
    > > page."

    >
    >
    > And Richard Maher was able to create concurrent access to his Java
    > applet pretty much by accident.


    I may have come across it by accident (and I think the goodness of
    upward-compatibility dictates that the "old" behaviour should've been the
    default - along the lines of the new classloader_cache parameter) but it
    appears to have been definitely implemented on purpose. "Who uses the
    functionality and why?" - I know not.

    > I don't think I really believe the
    > documentation in this regard.


    If anyone can show me two JavaScript functions serving events simultaneously
    in the same browser-tab then I'd sure like to see it! (Or at least know
    about it) onreadystatechange, onclick, mouseover, whatever - it can't be
    done.

    Or so I thought, at least prior to Java 6. I just stuck a
    JSObject.getWindow(this).call("someFunc",null) into my Applet.init() -
    without the "synchronized" - and it looks very muh to me that the JavaScript
    onload event and someFunc are executing in parallel :-o

    > The synchronization to make JavaScript
    > single thread seems buggy at best, non-existent at worse. And this is
    > from both IE and FF.


    I'd disagree with you prior to Java 6, but as someone who will be
    manipulating the DOM from JSObject.call()s in a separate Java thread in my
    Applet, I am more than a tad concerned about developments.

    Cheers Richard Maher
    Richard Maher, May 12, 2009
    #12
  13. Hi Again,

    "Richard Maher" <> wrote in message
    news:guau5m$lb$...
    > Hi Mark,
    >
    > "Mark Space" <> wrote in message
    > news:Er6Ol.22158$...
    > > Joshua Cranmer wrote:
    > >
    > > > Although the SpiderMonkey engine is very much capable of doing
    > > > multithreaded execution, the DOM itself is not threadsafe and has to

    be
    > > > modified from a single thread, so must browser JS ends up running in

    one
    > > > thread. Hence the statement: "The JavaScript engines in all of today's
    > > > web browsers are conceptually single threaded with respect to the web
    > > > page."

    > >
    > >
    > > And Richard Maher was able to create concurrent access to his Java
    > > applet pretty much by accident.

    >
    > I may have come across it by accident (and I think the goodness of
    > upward-compatibility dictates that the "old" behaviour should've been the
    > default - along the lines of the new classloader_cache parameter) but it
    > appears to have been definitely implemented on purpose. "Who uses the
    > functionality and why?" - I know not.
    >
    > > I don't think I really believe the
    > > documentation in this regard.

    >
    > If anyone can show me two JavaScript functions serving events

    simultaneously
    > in the same browser-tab then I'd sure like to see it! (Or at least know
    > about it) onreadystatechange, onclick, mouseover, whatever - it can't be
    > done.
    >
    > Or so I thought, at least prior to Java 6. I just stuck a
    > JSObject.getWindow(this).call("someFunc",null) into my Applet.init() -
    > without the "synchronized" - and it looks very muh to me that the

    JavaScript
    > onload event and someFunc are executing in parallel :-o
    >
    > > The synchronization to make JavaScript
    > > single thread seems buggy at best, non-existent at worse. And this is
    > > from both IE and FF.

    >
    > I'd disagree with you prior to Java 6, but as someone who will be
    > manipulating the DOM from JSObject.call()s in a separate Java thread in my
    > Applet, I am more than a tad concerned about developments.
    >


    In case it helps the discussion any, below is a modified version of my
    earlier example that certainly appears to show two JavaScripr functions
    executing in parallel. (The DOM "value" of the html field "next" ends up
    "132" instead of "123")

    Ok, "moving forward" can anyone show me similar behaviour outside of the
    Applet.init()-JSObject interaction environment? (The work-around, as Mark
    suggested, being to stick "synchronized" on the applet methods and call-back
    onto the Applet as soon as possible to synch with the return from init() )

    Are all JSObject.call()s prone to threading issues rather than all being
    queued to the EDT? This'd be disaterous - please advise!

    Would a further setTimer(0,"pleaseFireMeOnEDT()") work-around mechanism be
    required?

    > Cheers Richard Maher
    >
    >


    Console output
    ============
    Before fromInit call
    in getNum 1
    in getNum 2
    in getNum 3
    in getNum 4
    After fromInit call
    Before sleep call
    After sleep call

    Sleeper.java
    ===========

    import java.applet.Applet;
    import netscape.javascript.JSObject;
    import netscape.javascript.JSException;
    import java.lang.InterruptedException;

    public class Sleeper extends Applet {
    private int myNum = 0;
    private JSObject browser;

    public void init() {
    super.init();
    try {
    browser = JSObject.getWindow(this); }
    catch (netscape.javascript.JSException e) {
    e.printStackTrace(); }
    catch (Exception e) {
    e.printStackTrace(); }

    System.out.println("Before fromInit call");
    browser.call("fromInit", null);
    System.out.println("After fromInit call");

    System.out.println("Before sleep call");
    try {
    Thread.sleep(5000);
    }
    catch (InterruptedException e){
    e.printStackTrace();
    }
    System.out.println("After sleep call");
    myNum = 33;
    }

    public int getNum(){
    int i = myNum++;
    System.out.println("in getNum " + myNum);
    return i;
    }

    public void destroy ()
    {
    System.out.println("Checked - out");
    super.destroy();
    }
    }

    sleeper.html
    =========

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">

    <html>

    <meta name="author" content="Richard Maher"/>
    <meta name="description" content="JS Function and Applet Test"/>

    <head>


    <style>

    body
    {
    margin: 0px;
    background-color: white;
    color: Black;
    font-family: times;
    font-size: 16px;
    border: medium ridge;
    }

    </style>

    <script type="text/javascript">
    var tmp;

    function load() {
    var lclNum;
    var chan;
    tmp ="Stage 1";
    document.display.next.value = "1";
    try {
    chan = document.getElementById("Sleeper");
    lclNum = chan.getNum();
    lclNum = chan.getNum();
    lclNum = chan.getNum();
    }
    catch (err) {
    alert("In catch " + err.description);
    }
    if (chan == null) alert("chan is null");
    alert(chan.getNum() + " tmp = " + tmp);
    document.display.next.value += "2";
    alert("onLoad tmp was " + tmp);
    tmp ="Stage 3";
    }

    function fromInit(){
    document.display.next.value += "3";
    var oldTmp = tmp;
    tmp = "Stage 2";
    alert("fromInit tmp = "+tmp+" oldTmp = "+oldTmp);
    }

    </script>

    </head>

    <body onload="load();">

    <br /><h2>Test it</h2><hr /><br />

    <form name="display" style="margin-left: 100px;">

    <input
    type="text"
    style="text-align: Left;"
    name="next"
    size=10
    />
    </form>

    <script type="text/javascript">

    var myDef;
    if (navigator.appName == "Microsoft Internet Explorer")
    myDef =
    '<object classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" ' +
    'width= "0" height= "0" id="Sleeper">'
    +
    '<param name="code" value="Sleeper">'
    +
    '<param name="mayscript" value="true">' +
    '<param name="scriptable" value="true">' +
    '</object>'
    else
    myDef =
    '<object classid="java:Sleeper.class" '
    +
    'type="application/x-java-applet" ' +
    'width= "0" height= "0" id="Sleeper">'
    +
    '<param name="code" value="Sleeper">'
    +
    '<param name="mayscript" value="true">' +
    '<param name="scriptable" value="true">' +
    '</object>'

    document.write(myDef);
    </script>

    </body>

    </html>
    Richard Maher, May 12, 2009
    #13
  14. Richard Maher

    Lew Guest

    Mark Space wrote:
    > Anyway, with regard to Java, I think the best policy is to assume your
    > JApplet is being accessed in a multithreaded environment and program
    > defensively. I'd make all methods visible to JavaScript "synchronized",
    > including redefining all JApplet methods just to make them synchronized.


    Side note: Any shared state that is protected by synchronization via some
    critical sections (e.g., a setter method) must be protected by synchronization
    for all accesses (e.g., a getter method). The memory model must be served;
    partial protection is just as bad as no protection at all.

    Synchronization can be achieved by means other than the 'synchronized'
    keyword, of course.

    --
    Lew
    Lew, May 13, 2009
    #14
  15. Richard Maher

    Mark Space Guest

    Lew wrote:
    > Side note: Any shared state that is protected by synchronization via
    > some critical sections (e.g., a setter method) must be protected by
    > synchronization for all accesses



    It appears that JavaScript is single-threaded, or tries to be. I did
    find one Opera developer who admitted that their implementation wasn't
    really.

    I think he's getting called in response to multiple threads from the
    JVM, probably (?) in response to JavaScript events, which DO run
    asynchronously with the Java applet. Hence the need for multi-thread
    support.

    I'm not 100% sure about that, but I think it makes sense. Just a little
    note for everyone if you ever have to write an applet.
    Mark Space, May 13, 2009
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Tony Cheng
    Replies:
    1
    Views:
    8,187
    Juan T. Llibre
    Feb 24, 2006
  2. Andrew May
    Replies:
    2
    Views:
    499
    Rhino
    Mar 4, 2005
  3. news.aon.at
    Replies:
    11
    Views:
    634
    Ian Collins
    Jan 29, 2011
  4. Richard Maher
    Replies:
    12
    Views:
    192
    Thomas 'PointedEars' Lahn
    May 12, 2009
  5. Replies:
    0
    Views:
    632
Loading...

Share This Page