JSInterop assign a function/callback to a property

667 views
Skip to first unread message

Kay-Uwe Janssen

unread,
Nov 5, 2014, 2:28:21 AM11/5/14
to google-web-tool...@googlegroups.com
As i had no luck on Google+ yet, i'll try it here.

First the G+ Post: https://plus.google.com/116136390679208063122/posts/52kcbwwngWo


Well I just started to work on a ChromeCast Receiver built with GWT. As the Receiver API is in JS i wanted to try JSInterop over JSNI but had some struggle.

The ChromeCast Api has some properties that can be set with a function to act as a callback. eg for onReady.

castReceiverManager.onReady = function(event) {
  // do stuff
};

Now my question is: How can i do this with JsInterop or is it not yet possible?

as mentioned in https://docs.google.com/document/d/1tir74SB-ZWrs-gQ8w-lOEV3oMY6u6lF2MmNivDEihZ4 below "Single Abstract Method Handling" i tried something like this

@JsType
public interface Receiver {
  @JsProperty
  void onReady(Runnable onReady);
}

when trying to execute the method with this snipped i get "Exception caught: (TypeError) : object is not a function"

private native void test(Receiver receiver)/*-{
  receiver.onReady();
}-*/;


to see whats the value of onReady i did console.log(receiver) and got this: (where onReady is set the way above and onSenderConnected has been set the JS way inside an JSNI method.

onReady: JsTest$1_1_g$
onSenderConnected: function (event_0_g$)


is there a way to achieve this yet or do i have to wait for 2.8/3.0?

i tried to dig into the gwt code to see if there is a way to add something to support this but unfortunately the gwt code for js processing is a bit out of my scope.


some possible solutions would be either
interface JsFunction {
<T> T call(Object... args);
}
or
interface MyOnReadyCallback {
  @JsFunction
  MyReturnType anyName(String arg1, boolean arg2, SomeOtherType arg3);
}

and let the "Single Abstract Method Handling" find the method and add it.


Thanks! :)

Ray Cromwell

unread,
Nov 5, 2014, 3:17:29 AM11/5/14
to google-web-toolkit-contributors
That document represents intent to implement, but SAM handling isn't
implemented yet in GWT 2.7, since it is most useful after Java8 lands.
Shortly Java8 will land, and then SAM handling in JsInterop and you'll
be able to use GWT 2.8 nightly snapshots. For now, you'll need a
utility function that wraps a SAM as a function, e.g.

public static native JavaScriptObject samToFunction(MyCallback cb) /*-{
return function(arg) { return cb.@MyCallback::someMethod(*)(arg); };
}-*/;
> --
> You received this message because you are subscribed to the Google Groups
> "GWT Contributors" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to google-web-toolkit-co...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/google-web-toolkit-contributors/d4c8fb2c-6060-4680-9b24-e118a452dc0d%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Kay-Uwe Janssen

unread,
Nov 5, 2014, 4:22:53 AM11/5/14
to google-web-tool...@googlegroups.com
Hello Ray,

thank you for your reply.
Okay, i already assumed that it is not yet in.

do i understand your suggestion correctly that i then could do


@JsType
public interface Receiver {
  @JsProperty
  void onReady(JavaScriptObject onReady);
}

receiver.onReady(samToFunction(myCallback)); ?

btw: for me the short version like cb.@MyCallback::someMethod did not work in jsni even if i had the class imported and also used in java part (method params) of the code. i had to use the fully qualified name.

Cristian Rinaldi

unread,
Nov 5, 2014, 6:20:42 AM11/5/14
to google-web-tool...@googlegroups.com
@kay-uwe what Ray says is:

@JsType
public interface Receiver {
    void onReady(Function onReadyFn);

    public static class Static {
        public static native Receiver create() /*-{
           return //TODO return Receiver!!!
        }-*/;
    }
}

......

@JsType
public interface Function {
    void f(JavaScriptObject param );
}

......

Using all together:

Receiver receiver = Receiver.Static.create();
receiver.onReady(new Function(){
   public void f(JavaScriptObject param){
       //TODO work!!
   }
});

I am working in some projects with JsInterop:

Cheers :)

Kay-Uwe Janssen

unread,
Nov 6, 2014, 2:46:08 AM11/6/14
to google-web-tool...@googlegroups.com
@Cristian Rinaldi unfortunately this does not work how i need it. it still assignes the object and not the javascript function.

i think i have to wait for 2.8 to get it working. but thanks anyway :-)

Cristian Rinaldi

unread,
Nov 6, 2014, 8:28:29 AM11/6/14
to google-web-tool...@googlegroups.com
@Kay-Uwe Janssen

I am doing support IndexedDB with JsInterop to do some tests, and also I have to assign a function:

interface IDBRequest : EventTarget {
   ...
   attribute EventHandler   onsuccess;
   attribute EventHandler   onerror;
};

Use the request in JS:

request.onsuccess = function() { ... };
This can be translated as follows:

@JsType
public interface IDBRequest {
    
@JsProperty
   
public void onsuccess(Function fn);
}


@JsType
public interface IDBOpenDBRequest extends IDBRequest{}

@JsType
public interface IDBFactory {
   
public  IDBOpenDBRequest open(String db, int version);
}

@JsType
public interface IDBEnvironment {
   
@JsProperty
   
IDBFactory indexedDB();
}

@JsType(prototype = "window")
public interface Window extends IDBEnvironment{}

And use:

IDBOpenDBRequest req = Window.Static.get().indexedDB().open("db", 1);
req
.onsuccess(Function.Static.newInstance(new Function<Object, Void>() {
     
@Override
     
public Void f(Object changed) {
        console
.log(changed);
       
return null;
   
}
}));

The code here:
Cheers!!

Kay-Uwe Janssen

unread,
Nov 8, 2014, 4:02:20 PM11/8/14
to google-web-tool...@googlegroups.com
Thank you!

That works. It seems I missed the "Function.Static.newInstance" in my last test. :S


Am Mittwoch, 5. November 2014 08:28:21 UTC+1 schrieb Kay-Uwe Janssen:
Reply all
Reply to author
Forward
0 new messages