Accessing "basic" JS Object in JsInterop callback

789 views
Skip to first unread message

Andrea Martino

unread,
Aug 13, 2017, 10:53:34 AM8/13/17
to GWT Users
Hi all,
I have recently started testing JsInterop for our GWT 2.8.1 application and I have encountered a situation I could not solve without using the old style JSNI approach.

Consider the following minimal JS library I would like to use in Java/GWT:

(function (window, document, undefined) {

function WatchDog(name) {
   
this._name = name;
};

WatchDog.prototype.register = function(callback) {
   
this._callback = callback;
};

WatchDog.prototype.broadcast = function(msg) {
   
if (this._callback) {
       
this._callback({
           
'name' : this._name,
           
'timestamp' : new Date().getTime(),
           
'msg' : msg
       
});
   
}
};

window
.Dummy = {
    watchDog
: function(name) {
       
return new WatchDog(name);
   
}
};

}(window, document));

Please note that the broadcast function passes a "basic" JS Object {} (i.e. without a specific prototype) to the callback function.

Here below my JsInterop mappings:

package xxx;

import jsinterop.annotations.JsPackage;
import jsinterop.annotations.JsType;

@JsType(isNative = true, namespace = JsPackage.GLOBAL)
public class Dummy {
   
private Dummy() {}
   
public static native WatchDog watchDog(String name);
}

package xxx;

import jsinterop.annotations.JsMethod;
import jsinterop.annotations.JsType;

@JsType(isNative = true)
public class WatchDog {
   
private WatchDog() {}
   
@JsMethod
   
public native void register(Callback callback);
   
@JsMethod
   
public native void broadcast(String msg);
}

package xxx;

import jsinterop.annotations.JsFunction;

@JsFunction
public interface Callback {
   
void call(Object event);
}


In my Java code, when the callback function is invoked, the event parameter is an instance of com.google.gwt.core.client.JavaScriptObject.

Without using JSNI I am not able to access/read the object's properties. Does JsInterop addresses this scenario without falling-back to old style JSNI?

Thanks a lot in andvance
Andrea

Vassilis Virvilis

unread,
Aug 13, 2017, 11:46:59 AM8/13/17
to google-we...@googlegroups.com

I had this problem with DataTables Config. DataTables is a nice javascript library for tables https://datatables.net/ and Config is the initialization object like yours. So here is what I did:

    @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object")
    public static class Config {
        String name;
        TimeStamp timestamp;   // TimeStamp needs to be jsinteropified too or elementat2 needs to be used.
        String msg;
 
        @JsOverlay
        public static Config create(String name, TimeStamp timestamp, String msg) {
               final Config config = new Config()
               config.name = name;
               config.timestamp = timestamp;
               config.msg = msg;
        }
 }

Hope that helps.

1) It would be nice to initialize Objects from json. What would happen if the json text specifies members not in class though?

2) It would be interesting if JavaScriptObject was below Object in the GWT inheritance and expose .__set() for all java objects. I don't know if that is is possible but I find the thought intriguing. It would be break javac compilation though...

    Vassilis




--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsub...@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at https://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.



--
Vassilis Virvilis

Kirill Prazdnikov

unread,
Aug 15, 2017, 6:41:56 AM8/15/17
to GWT Users
What prevents you using a proper JsType for callback arg ?

public interface Callback {
void call(ArgT event);
}

@JsType
inerface ArgT {
@JsProperty A getA();
@JsProperty B getB();
// e.t.c
}

Vassilis Virvilis

unread,
Aug 15, 2017, 7:12:40 AM8/15/17
to google-we...@googlegroups.com
I don't think his problem was the callback. This is easily jsinteropified with @JsFunction.

I think his problem was initializing Object with json

    Vassilis

}

--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsub...@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at https://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.



--
Vassilis Virvilis

Jens

unread,
Aug 15, 2017, 10:23:57 AM8/15/17
to GWT Users

package xxx;

import jsinterop.annotations.JsFunction;

@JsFunction
public interface Callback {
   
void call(Object event);
}

If the JS library does not pass totally different JS objects into the callback but instead something that is worth defining as a class you can use void call(BroadCastEvent event) instead of using Object and define BroadCastEvent (or whatever name you choose) using the approach shown by Vassilis.

If the JS library passes in different kinds of JS objects then there needs to be some sort of discriminator property so you can check in Java which kind of Js object you have received, e.g. { messageType: 'BROADCAST' }. Then you could make this property available through JsInterop and use it to check the event type and hard cast it into one of the native JsTypes you have defined (one per messageType value). I think there is also a util method for casting in jsinterop.base library.

If the callback input is totally random, then it might be better to define a native JsType with just a getProperty(String name) JsOverlay method that delegates to a JSNI util method or an appropriate method in elemental.base library. In that case it is more a map like object.

In any case if you feel like you would need to use JSNI for something then first check the jsinterop.base library if it already has the util method you are looking for, because these methods will also work in J2CL if you will ever use it. If you can not find the method you need in jsinterop.base library then I think it is better to make a small utility JS library on your own and make it accessible through JsInterop instead of using JSNI.

-- J.

Tony BenBrahim

unread,
Aug 20, 2017, 10:47:58 AM8/20/17
to GWT Users

regarding 1) It would be nice to initialize Objects from json. What would happen if the json text specifies members not in class though?

You could always do this, if you just need to pass something to JavaScript and do not need to read it...

@JsType(isNative=true, name="JSON", namespace=@JsPackage.GLOBAL)
public class JSON {
   Object parse(String json);
}
....
Object config=JSON.parse("{foo:1, bar: ["a","b","c"], baz: {a: true, b: false}}");
You c​
You could even do this if Config is a JsType with name Object and namespace GLOBAL:

Config config=(Config) JSON.parse("{foo:1, bar: ["a","b","c"], baz: {a: true, b: false}}");

In that case, any properties that do not exist in Config would simply not be readable or writable from your Java code, without using JSNI...



Vassilis Virvilis

Vassilis Virvilis

unread,
Aug 20, 2017, 11:02:30 AM8/20/17
to google-we...@googlegroups.com
Great thought.

It could save me some hours/days of modeling the Config Object in java.

On the other hand my Config Object is strictly typed with all the usual benefits.

On the other hand (apparently the discussion requires 3 hands :) my java Config Object is not complete. I have defined only the fields I needed. I would say around 25%. So it needs even more work to be complete while your solution could be extended easily at request.

!


--
You received this message because you are subscribed to the Google Groups "GWT Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsub...@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at https://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.



--
Vassilis Virvilis
Reply all
Reply to author
Forward
0 new messages