Applet <=> Javascript interaction. Need of generic factories for core framework classes ?

12 views
Skip to first unread message

nouknouk

unread,
Mar 30, 2008, 2:54:39 PM3/30/08
to PulpCore
Hi,

I would like to allow my pulpcore applet to communicate with
(java)scripts embedded in the web page.

In the direction applet => javascript (I mean calling a javascript
function from the applet) it seems to be easily doable, with the
netscape.javascript.JSObject class.
I didn't tested it yet, but according to articles I've readen on the
web, it should not be a problem, except maybe taking care of several
browsers versions. If someone already did such thing, I'm interrested
on his feedback.

BUT, in the other direction (calling an applet function from
javascript), it seems the only way to do that is to add the function
to be called directly inside the Applet class. Indeed, the only class
that an external javascript code can access seems to be the Applet
one.

This is my problem : it looks not doable with pulpcore's framework
without patching the pulpcore library and
pulpcore.platform.applet.CoreApplet class, each time i would like to
add my specific function.

So I would have a suggestion : what about the implementation of
factories, used by the framework to instanciate the base classes,
instead of 'hard coded' instanciation inside the code.

That way, instead of always instanciating the CoreApplet class, the
developper would be able to subclass CoreApplet, to include his class
inside the 'jar' file and add something like the classname as a
(optionnal) parameter in the <objet> tag of the web page. This could
also be done to other 'core' classes (Stage, ...).

What do you think ?

Regards,

Nouk²

David Brackeen

unread,
Mar 30, 2008, 3:11:33 PM3/30/08
to pulp...@googlegroups.com
The BubbleMark example contains JavaScript -> Java communication. CoreApplet has a getCurrentScene() method, and the applets always have an ID in the DOM named "pulpcore_object"

onclick="pulpcore_object.getCurrentScene().setCapFrameRate(this.checked);"

Although, I wouldn't recommend requiring JavaScript for any game - it doesn't work in some browsers (Opera on Mac) and can cause nasty bugs like this one: http://bugs.sun.com/view_bug.do;jsessionid=1187bd21c3c171ffffffffaab373f13ccd0e5?bug_id=6669818

Alexandre BRAGANTI

unread,
Mar 31, 2008, 3:32:36 AM3/31/08
to pulp...@googlegroups.com
Hi,

first, thanks a lot for the link.
I'm sorry, I forbid to take a look on the bubblemark example.

The problem on my side is I'm quite prompted to use such interaction, because embedding all the features I plan to develop inside the applet is a big overload and anyway, it won't be as 'smooth' in terms of user experience.

According to your link and other searchs, i see two points:

- the bug look a regression one, meaning it only affects java 1.6.0_03 (+) and will (hopefully) be fixed in the near future. Don't know if such regression bug with the same priority (medium) are usually quickly solved by Sun. Any idea ?

Anyway, if I understand well the case only happens if the reverse DNS lookup doesn't return the same IP adress than the DNS one. It's for example the case with my sample 'minigame' (with my dns like 'no-ip.org'), but it won't be as soon as I buy a 'real' DNS and rent a private server. Right ?

Are there any other known bugs related to LiveConnect ?


- for the incompatibility of LiveConnect with Opera on Mac, it doesn't look critical for me: if it cannot work at all for that browser, I'll simply detect its user agent and prompt the user to use the default browser (Safari). Opera represents less than 2% of the market share according to W3Schools' statistics (*), and opera is not the default browser of any operating system, so it ensures at least one compatible web browser is installed on any computer. To my mind, that's the more important. No ?

Just hoping I understood well and Opera is the only one 'representative' browser (with IE, Firefox, Safari, Konqueror) that won't work.


What do you think ?

Best regards,

Nouk²


(*) http://www.w3schools.com/browsers/browsers_stats.asp



2008/3/30, David Brackeen <brac...@gmail.com>:

nouknouk

unread,
Mar 31, 2008, 5:56:44 AM3/31/08
to PulpCore
Just another thing i forgot in my previous post :

Even if it's not required for javascript interaction, more generally,
what do you think about adding factories for generic classes of the
pulpcore's framework (CoreApplet, Stage, ...) ?

Best regards,

Nouk²

gjuggler

unread,
Mar 31, 2008, 11:00:06 AM3/31/08
to PulpCore
I would also favor a bit more opening up of the pulp.js scripts and
CoreApplet classes. For example, if you make the CoreApplet class non-
final and modify the asset building tools to use a property for the
"appletClass" instead of using a hard-coded value of
pulpcore.applet.CoreApplet.class (as is currently the case), a
developer could easily subclass CoreApplet and add any new public
methods they want to access via LiveConnect in that subclass. I've
done this, and it doesn't require too much reworking to achieve.

greg

David Brackeen

unread,
Mar 31, 2008, 1:27:26 PM3/31/08
to pulp...@googlegroups.com
Yeah if that FF bug gets fixed, LiveConnect will work in the vast majority of situations. That bug only exists on virtual name-based hosts. I think there is other weirdness between implementations, though, so be sure and test on all major browsers.

At the moment I'm not inclined to provide anything in the pulpcore.platform.* packages and part of the standard API. One of the goals of PulpCore is to get a standard API that's the same on different platforms (Applets, desktop, etc). Plus, CoreApplet is final because calling certain methods in a subclass's constructor could cause PulpCore to break. 

You should be able to do it since the getCurrentScene() method is provided. If you need the same methods in every scene, create an abstract MyScene2D with those methods!

I'd be fine if someone wants to fork the pulpcore.js loader into a separate project for folks with legacy applets or other projects. The callback code is mostly in AppletAppContext. 

nouknouk

unread,
Mar 31, 2008, 8:13:47 PM3/31/08
to PulpCore
Hi,

On 31 mar, 19:27, "David Brackeen" <brack...@gmail.com> wrote:
> At the moment I'm not inclined to provide anything in the
> pulpcore.platform.* packages and part of the standard API. One of the goals
> of PulpCore is to get a standard API that's the same on different platforms
> (Applets, desktop, etc). Plus, CoreApplet is final because calling certain
> methods in a subclass's constructor could cause PulpCore to break.

I totally agree that pulpcore is a little bit specific because the
base framework classes are like a 'black box' due to the sepcific
needs of applet (smart loading feature, the compiling toolchain
including assets, ...).

The high integration of several features has got one enormous
advantage : providing a whole framework allowing the developper to use
it 'out of the box' and develop in three lines a first 2D applet. The
little disadvantage (to my mind) is that those specific things reduce
the genericity, and thus the possibility to develop things not
explicitely handled by the framework yet.

Adding a way for the developper to subclass core classes can be useful
to do specific things. If he does so, it's the developper's
responsibility to be aware of their internal behavior, that the core
classes are highly coupled and that things cannot be done without
investigating deeply the framework.

But, in case of specific needs, it would be useful to make the
framework as customizable as possible for any further specific need.

One concrete example : the Applet => Javascript communication (and
*not* Javascript => Applet discussed before). For that, I need to pass
to my JSObject one reference to the CoreApplet. Currently, It seems
(afaik) I cannot do it without patching pulpcore, because the only way
to do that is to call the static function AppletPlatform::getApplet()
and this function is 'package private'.

Best regards,

Nouk²

David Brackeen

unread,
Apr 1, 2008, 2:07:37 PM4/1/08
to pulp...@googlegroups.com
For now, you can use AppletAppContext.isJavaScriptEnabled() and AppletAppContext.callJavaScript(method) to call some JavaScript. It works around the FF bug, and it won't use LiveConnect in that situation.

If you add stuff to CoreApplet, it would be great if it were done in a way that other people can use it! By adding API in other parts, for example.

nouknouk

unread,
Apr 5, 2008, 8:54:20 AM4/5/08
to PulpCore
Hi,

I've got an issue when I would like to call an applet function by a
javasciprt function. My javascript code is :

document.getElementById("pulpcore_object").getCurrentScene().myPulpcoreSceneFunction();


But, i get an exception.
It seems it's because the call of the applet's function is not done in
the Stage's thread, that's why getCurrentScene() does not work.
Any idea on how to do it another way ?

Best regards,

Nouk²


PS: The exception is:

java.lang.Error: No context found for thread
at
pulpcore.platform.applet.AppletPlatform.getThisAppContext(AppletPlatform.java:
138)
at pulpcore.CoreSystem.getThisAppContext(CoreSystem.java:121)
at pulpcore.Stage.getThisStage(Stage.java:163)
at pulpcore.Stage.getScene(Stage.java:290)
at
pulpcore.platform.applet.CoreApplet.getCurrentScene(CoreApplet.java:
167)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.plugin.javascript.JSInvoke.invoke(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.plugin.javascript.JSClassLoader.invoke(Unknown Source)
at sun.plugin.com.MethodDispatcher.invoke(Unknown Source)
at sun.plugin.com.DispatchImpl.invokeImpl(Unknown Source)
at sun.plugin.com.DispatchImpl$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.plugin.com.DispatchImpl.invoke(Unknown Source)

nouknouk

unread,
Apr 5, 2008, 9:18:36 AM4/5/08
to PulpCore
After investigations, the problem is quite more annoying :

In fact, when the browser runs only one pulpcore applet, everything is
ok (I mean no exception).
BUT if several applets are running at the same time (in two tabs, for
example), the exception is thrown.

Note that if I run two pulpcore applets in two different browser (eg.
IE + Firefox), in that case, it works well, as each one has got its
own JVM.

The problem comes from the AppletPlatform::getThisAppContext() code:
- when there's only one pulpcore applet, the app context is immediatly
returned
- when there's more than one pulpcore applet running, the function
tries to guess the applet context by finding to which applet belongs
the Thread executing getThisAppcontext(). As - when a javascript call
is made - the thread calling this function doesn't belong to any
pulpcore applet, the exception is thrown.

D'ont know yet if there's any way to change that and make javascript
calls work when multiple pulpcore applets are running in the same
sandbox.
Any idea ?

Best regards,

Nouk²

David Brackeen

unread,
Apr 5, 2008, 2:01:21 PM4/5/08
to pulp...@googlegroups.com
This is fixed in SVN.

nouknouk

unread,
Apr 6, 2008, 9:41:55 AM4/6/08
to PulpCore


On 5 avr, 20:01, "David Brackeen" <brack...@gmail.com> wrote:
> This is fixed in SVN.

Thanks for the fix.

It seems to work well on firefox, but unfortunately there's still
something wrong with Internet Explorer 7.0 : An exception is thrown
when the page is closed and there was multiple pulpcore applets
running.

I reproduced the problem with the HelloWorld sample (made with the
'quick project' in pulpcore netbeans module) with the previous version
and the new one.

Best regards,
Nouk²


PS: The exception thrown when closing the tab:

java.lang.Error: No context found for thread
at
pulpcore.platform.applet.AppletPlatform.getThisAppContext(AppletPlatform.java:
138)
at pulpcore.CoreSystem.getThisAppContext(CoreSystem.java:121)
at pulpcore.Stage.getThisStage(Stage.java:163)
at pulpcore.Stage.getFrameRate(Stage.java:251)
at pulpcore.scene.Scene2D.hideNotify(Scene2D.java:635)
at pulpcore.Stage.doDestroy(Stage.java:741)
at pulpcore.Stage.destroy(Stage.java:460)
at
pulpcore.platform.applet.AppletAppContext.destroy(AppletAppContext.java:
163)
at
pulpcore.platform.applet.AppletPlatform.unregisterApp(AppletPlatform.java:
221)
at pulpcore.platform.applet.CoreApplet.destroy(CoreApplet.java:97)
at sun.applet.AppletPanel.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
java.lang.Error: No context found for thread
at
pulpcore.platform.applet.AppletPlatform.getThisAppContext(AppletPlatform.java:
138)
at pulpcore.CoreSystem.getThisAppContext(CoreSystem.java:121)
at pulpcore.Stage.getThisStage(Stage.java:163)
at pulpcore.Stage.getFrameRate(Stage.java:251)
at pulpcore.scene.Scene2D.hideNotify(Scene2D.java:635)
at pulpcore.Stage.doDestroy(Stage.java:741)
at pulpcore.Stage.destroy(Stage.java:460)
at
pulpcore.platform.applet.AppletAppContext.destroy(AppletAppContext.java:
163)
at
pulpcore.platform.applet.AppletPlatform.unregisterApp(AppletPlatform.java:
221)
at pulpcore.platform.applet.CoreApplet.destroy(CoreApplet.java:97)
at sun.applet.AppletPanel.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)


nouknouk

unread,
Apr 6, 2008, 9:45:17 AM4/6/08
to PulpCore
My mistake : the exception is thrown too in firefox, when multiple
tabs with pulpcore applets are running.

David Brackeen

unread,
Apr 6, 2008, 12:09:12 PM4/6/08
to pulp...@googlegroups.com
Ok, thanks, I'll take a look. I'll be away from computers today so it may not be until tmrw.

nouknouk

unread,
Apr 6, 2008, 1:04:19 PM4/6/08
to PulpCore
> Ok, thanks, I'll take a look. I'll be away from computers today so it may
> not be until tmrw.

Thanks for being involved.

In the meanwhile, I found a hack to avoid that exception: in
AppletPlatform::getThisAppContext(), when the calling thread is not
found in any thread group belonging to one pulpcore applet, I return
'mainContext' instead of throwing an error (see below the source).
This is probably not secure at all, but for the moment, it behaves
well on my side.

I deeper investigated, because i was quite surprised for such
behavior : indeed, the examples on your website don't throw such
exception when you close them. Thus, I recompiled the library from SVN
with revisions 522, 520, 518 & 480, but I get exactly the same bug
(tested with the 'Quick' template of the netbeans plugin).

So i don't really understand what happens. Maybe a mistake on my
side ?

Best regards,

Nouk²


PS: The source of my temporary hack:

public AppContext getThisAppContext() {
// In most cases, there will be only one registered App. In
that case, this method
// returns as quickly as possible.
if (allContexts == null) {
return mainContext;
}

synchronized (this) {
// Double check inside the lock
if (allContexts == null) {
return mainContext;
}

// Look through all registered apps and find the context
for this ThreadGroup
// TODO: implement as ThreadLocal instead? (This
implementation was Java 1.1 compatible)
ThreadGroup currentThreadGroup =
Thread.currentThread().getThreadGroup();
for (int i = 0; i < allContexts.size(); i++) {
AppletAppContext context =
(AppletAppContext)allContexts.get(i);
ThreadGroup contextThreadGroup =
context.getThreadGroup();
if (contextThreadGroup == currentThreadGroup ||
contextThreadGroup.parentOf(currentThreadGroup))
{
return context;
}
}

// here is the change:
return mainContext;
// instead of:
// throw new Error("No context found for thread");
}

nouknouk

unread,
Apr 7, 2008, 4:20:22 PM4/7/08
to PulpCore
About Java <=> javascript interaction, it works well in both ways
now ... when I'm testing on Internet Explorer 7.

But unfortunately, it is not possible at all with Firefox. The reason
seems to be the feature is automatically disabled by pulpcore
framework (i get 'javascript: false' in pulpcore's console).

That's quite amazing, as if I test with the same JVM and the same
Firefox versions, it seems to work well with a sample found here :

http://www.raditha.com/java/jsapplet.jar

According to what I found in pulpcore's code, javascript is
disactivated because JSObject.getWindow() returns null.

If I test on my side, it doesn't return null with exactly the same
code embedded in a basic applet. You can check it here :
http://jooez.no-ip.org/test.html

What could be happening ?

note: I'm using JRE 1.6_05 and Firefox 2.0.0.13

nouknouk

unread,
Apr 7, 2008, 4:42:02 PM4/7/08
to PulpCore
Oops : my mistake about pulpcore's source investigations.

In fact, the liveconnect boolean is automatically set to 'false' if
the following condition is true:
"isSun && CoreSystem.isJava16orNewer() && isMozillaFamily() &&
isVirtualHost()"

As seen before, on my side, the liveConnect feature shouldn't as it
works perfectly with my environment (I just commented the test above,
recompiled pulpcore library, and my applet works well even with
liveconnect features).

Thus, there is my question is : why is liveConect disactivated a
priori ? Shouldn't we better rely on the test coded in
'isJavascriptEnabled()', and that is never used for the moment ?

Best regards,

Nouk²

David Brackeen

unread,
Apr 7, 2008, 4:48:33 PM4/7/08
to pulp...@googlegroups.com
That code is a workaround for this bug:
If LiveConnect is used in that situation, other applets on the same domain will fail (the first applet always works fine).
Like I mentioned before, because of this bug and other issues, I wouldn't recommend requiring LiveConnect for any game.

Alexandre BRAGANTI

unread,
Apr 7, 2008, 5:37:34 PM4/7/08
to pulp...@googlegroups.com
The problem on my side is that I need to use LiveConnect.
What do you mean with "because [of this bug] and other issues" ? Are you aware of other issues about liveConnect ?

About the test, wouldn't it be better to catch the security exception while calling the 'callJavascript()' function.
That way, liveconnect would work every time the bug does not appears and fail gracefully when it appears.

This would be especially usefull for cases where only one applet is launched on the website (or several times the same applet: I tested it and it works fine on my side).

Best regards,

Nouk²


David Brackeen a écrit :

David Brackeen

unread,
Apr 7, 2008, 6:35:55 PM4/7/08
to pulp...@googlegroups.com
wouldn't it be better to catch the security exception while calling the 'callJavascript()' function.
 
I wish it were possible to catch any exceptions, but it's more complicated that - using LiveConnect in that situation actively prevents other applets on that domain from downloading files. 

This would be especially usefull for cases where only one applet is launched on the website
 
For the defaults, PulpCore is going to have to go with the majority on this one: assuming that most developers are going to have multiple applets on one virtual host, and not using LiveConnect, that code absolutely has to have the code workaround.

 Are you aware of other issues about liveConnect ?
 
Other LiveConnect issues like implementation differences between IE and FF (this may be easy to workaround). Also LiveConnect doesn't work in these situations:
  • Opera 9 on Mac OS X
  • Safari 3 on Windows
  • IE6 if the site is externally framed. For example, if SomeGamePortal.com creates a frameset that contains MyGameSite.com/MyGame, LiveConnect does not work.
Now, your solutions. Until Sun fixes the problem, if you need LiveConnect in FF, I can see three options:

1) if possible, do not use a virtual name-based host (in other words the host name needs to be the default host for the IP address)
2) hack your own version of PulpCore that doesn't have that LiveConnect workaround
3) a cleaner version of #2 - submit a patch where the applet param "force_liveconnect" doesn't use the above workaround

David Brackeen

unread,
Apr 8, 2008, 2:51:11 PM4/8/08
to pulp...@googlegroups.com
The bug when closing two applets in the same VM instance is now fixed, in SVN.
Reply all
Reply to author
Forward
0 new messages