JSO: Why does this fail?

63 views
Skip to first unread message

Mickaël Leduque

unread,
Feb 26, 2015, 7:18:01 AM2/26/15
to google-we...@googlegroups.com
Hi,

We switched to gwt 2.7 and now i have a compilation failure

[ERROR] JSNI method JsPromise.thenJava(Lcom/codenvy/api/promises/client/Thenable;)Lcom/codenvy/api/promises/client/Promise; attempts to call method Thenable.then(Ljava/lang/Object;)Lcom/codenvy/api/promises/client/Thenable; on an instance which might be a JavaScriptObject. Such a method call is only allowed in pure Java (non-JSNI) functions.

The code in question does

    @Override
    public final <B> Promise<B> then(final Thenable<B> thenable) {
        if (thenable instanceof JavaScriptObject) {
            return this.thenJs((JavaScriptObject)thenable);
        } else {
            return this.thenJava(thenable);
        }
    }

    private final native <B> Promise<B> thenJs(JavaScriptObject thenable) /*-{
        return this.then(thenable);
    }-*/;

    private final native <B> Promise<B> thenJava(Thenable<B> thenable) /*-{
        return this.then(function() {
            then: function(arg) {
                return thenable.@com.codenvy.api.promises.client.Thenable::then(*)(arg);
            }
        });
    }-*/;

And there's a JSO implementation of the Thenale interface.

I've seen for example https://code.google.com/p/google-web-toolkit/issues/detail?id=9008, but that's not the case as ThenJava will never be called with a JavaScripObject (unless I misunderstood).

So what's the problem?

Thomas Broyer

unread,
Feb 26, 2015, 7:41:58 AM2/26/15
to google-we...@googlegroups.com
To be honest, I don't know what the *problem* is, but there should be a simple workaround:

    private final native <B> Promise<B> thenJava(Thenable<B> thenable) /*-{
        return this.then(function() {
            then: function(arg) {
                return @::staticThen(*)(thenable, arg);
            }
        });
    }-*/;

    private static <B> Promise<B> staticThen(Thenable<B> thenable, B arg) {
      return thenable.then(arg);
    }

(or something along those lines)

BTW, you might want to add a bunch of calls to $entry() here and there.

Mickaël Leduque

unread,
Feb 26, 2015, 8:25:13 AM2/26/15
to google-we...@googlegroups.com
OK thanks, thant would be

    private static <B> Thenable<B> staticThen(Thenable<B> thenable, B arg) {
      return thenable.then(arg);
    }


2015-02-26 13:41 GMT+01:00 Thomas Broyer <t.br...@gmail.com>:


BTW, you might want to add a bunch of calls to $entry() here and there.


I wondered about that.

I have seen mention of $entry in the doc, but never saw an actual documentation on what it does, when to use it and when not to use it.

Thomas Broyer

unread,
Feb 26, 2015, 8:47:46 AM2/26/15
to google-we...@googlegroups.com
Whenever you "enter GWT code" from the outside, wrap that function with $entry().
$entry() will decorate any function and make sure that:
  • exceptions are routed to the GWT.UncaughtExceptionHandler, if any.
  • scheduleEntry / scheduleFinally commands are run
Basically:

function $entry(fn) {
  return function() {
    var _entry = function(fn, args) {
      try {
        runScheduledEntryCommands();
        fn.apply(this, args);
      } finally {
        funScheduledFinallyCommands();
      }
    }
    if (hasUncaughtExceptionHandler) {
      try {
        _entry(fn, arguments);
      } catch (e) {
        callUncaughtExceptionHandler(e);
      }
    } else {
      _entry(fn);
    }
  };
}

Mickaël Leduque

unread,
Feb 26, 2015, 8:59:43 AM2/26/15
to google-we...@googlegroups.com
So the answer to
When use it ? When not use it ?

is respectively always and never ? That's easy to follow, thanks!


--
You received this message because you are subscribed to a topic in the Google Groups "Google Web Toolkit" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/google-web-toolkit/luuAC9kq2-k/unsubscribe.
To unsubscribe from this group and all its topics, send an email to google-web-tool...@googlegroups.com.
To post to this group, send email to google-we...@googlegroups.com.
Visit this group at http://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.

Thomas Broyer

unread,
Feb 26, 2015, 10:21:33 AM2/26/15
to google-we...@googlegroups.com


On Thursday, February 26, 2015 at 2:59:43 PM UTC+1, Mickaël Leduque wrote:
So the answer to
When use it ? When not use it ?

is respectively always and never ? That's easy to follow, thanks!

Hmm, no. If your JSNI calls back into Java "synchronously", then you don't need to use $entry (exceptions will still "bubble" up to your GWT.UncaughtExceptionHandler Java→JSNI→Java, and you're still in the same event-loop wrt scheduled commands). You use $entry() whenever the browser calls back into your GWT/Java code "asynchronously" (event handling, promises, etc. basically whatever comes from the browser's own event loop).
Note that $entry is re-entrant though, so calling it too many times won't break your app (but possibly affect performance).
 


To unsubscribe from this group and all its topics, send an email to google-web-toolkit+unsub...@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.

Thomas Broyer

unread,
Feb 26, 2015, 10:22:57 AM2/26/15
to google-we...@googlegroups.com


On Thursday, February 26, 2015 at 4:21:33 PM UTC+1, Thomas Broyer wrote:


On Thursday, February 26, 2015 at 2:59:43 PM UTC+1, Mickaël Leduque wrote:
So the answer to
When use it ? When not use it ?

is respectively always and never ? That's easy to follow, thanks!

Hmm, no. If your JSNI calls back into Java "synchronously", then you don't need to use $entry (exceptions will still "bubble" up to your GWT.UncaughtExceptionHandler Java→JSNI→Java, and you're still in the same event-loop wrt scheduled commands). You use $entry() whenever the browser calls back into your GWT/Java code "asynchronously" (event handling, promises, etc. basically whatever comes from the browser's own event loop).


Basically, whenever you pass a "callback" to be called "later", decorate it with $entry().

Mickaël Leduque

unread,
Feb 26, 2015, 10:28:13 AM2/26/15
to google-we...@googlegroups.com
OK, I understood (which actually I find scary).
Thanks!

--
You received this message because you are subscribed to a topic in the Google Groups "Google Web Toolkit" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/google-web-toolkit/luuAC9kq2-k/unsubscribe.
To unsubscribe from this group and all its topics, send an email to google-web-tool...@googlegroups.com.
To post to this group, send email to google-we...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages