Trouble understanding JsInterop

321 views
Skip to first unread message

Philipp

unread,
Apr 11, 2017, 4:43:06 AM4/11/17
to GWT Users
If I have a java class and I mark it with @JsType I create a contract between Java and Javascript that I can use this class with it's given Java name in Javascript - is this correct?

package com.test.workertest.shared;


import com.google.gwt.core.shared.GWT;


import jsinterop.annotations.*;


@JsType(namespace = "test", name = "JsOpClass")
public class JsOpClass
{


   
@JsMethod
   
public void printStuff()
   
{
        GWT
.log("asdfasdf");
   
}
}


I would like to be able to create now a JsOpClass object in javascript and call printStuff() on this object but I actually don't understand where this is meant to be working. If I create for example a web worker which would create this class it reports that 

com.google.gwt.event.shared.UmbrellaException: Exception caught: (ReferenceError) : testis not defined

which makes sense because my worker.js knows nothing about GWT (would this be possible?)

And even if I try it in the GWT HTML file it doesn't seem to know about this class and I get a test is not defined error.

How do I actually call exposed classes/methods and from where is it possible? Is it only a JSNI substitute (but even then I was not able to call it from a JSNI method).

Thomas Broyer

unread,
Apr 11, 2017, 5:32:36 AM4/11/17
to GWT Users
First, you have to pass -generateJsInteropExports to GWT (compiler, codeserver, devmode), to actually export the JsType to JavaScript.
Then, from the context the GWT app (*.nocache.js) was loaded in, you should be able to do '(new test.JsOpClass()).printStuff()', after your GWT app has been loaded/started (once onModuleLoad has been called)
 
Is it only a JSNI substitute

Yes.
 
(but even then I was not able to call it from a JSNI method).

var o = new $wnd.test.JsOpClass();
o.printStuff();

…but maybe all you miss is the -generateJsInteropExports?

Philipp Gloor

unread,
Apr 11, 2017, 10:30:17 AM4/11/17
to google-we...@googlegroups.com
Can I access Classes and Methods decorated with JsType/JsMethod from anywhere within GWT granted I'm inside a JSNI block? Or is it restricted to packages?

I added the -generateJsInteropExports to the run configuration arguments but when I try to create a new object JsOpClass() it tells me $wnd.pdf is undefined.

--
You received this message because you are subscribed to a topic in the Google Groups "GWT Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/google-web-toolkit/wpcpNJka5qo/unsubscribe.
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.
Visit this group at https://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.

Philipp Gloor

unread,
Apr 11, 2017, 10:31:22 AM4/11/17
to google-we...@googlegroups.com
NB: I changed the namespace from test to pdf -> that's why it is now $wnd.pdf is undefined.

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

Vassilis Virvilis

unread,
Apr 11, 2017, 10:43:08 AM4/11/17
to google-we...@googlegroups.com
Hi,

1. With jsinterop you won't need any JSNI normally.
2. If you have older JSNI code that calls your new code (can't really happen) you can
  a) use new $wnd.test.JsOpClass(); with -generateJsInteropExports as Thomas suggested
  b) use the old syntax found here http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJSNI.html and that would be something like @com.test.workertest.shared.JsOpClass::new()() Note the ()() double parenthesis.

Do you want JsOpClass to be visible from both js and java?


To unsubscribe from this group and all its topics, send an email to google-web-toolkit+unsubscribe@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.

--
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

Philipp Gloor

unread,
Apr 11, 2017, 10:53:24 AM4/11/17
to google-we...@googlegroups.com
Where do I use $wnd.test.JsOpClass()? It doesn't work within <script> tags inside the HMTL file of my GWT project.

The reason I'm looking at JsInterop was because we want to use web workers. And since there is no GWT implementation of web workers I would do this via native calls. And the web worker would only forward methods because once I'm in the worker thread I have to call GWT functions again.

GWT Mainthread --->   Worker.js  ---> GWT in a worker thread

The calls from Worker.js to GWT in the worker thread would also pass an instance of the worker itself into GWT (as JavaScriptObject) so I could call worker.postMessage to get back to the main thread.



To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscribe@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

--
You received this message because you are subscribed to a topic in the Google Groups "GWT Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/google-web-toolkit/wpcpNJka5qo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to google-web-toolkit+unsub...@googlegroups.com.

Vassilis Virvilis

unread,
Apr 11, 2017, 11:01:11 AM4/11/17
to google-we...@googlegroups.com
It should work but you also have to make sure that GWT code is loaded.

So after the crash - hit F12 go to console and try to reference $wnd.test.JsOpClass
or
put a console print inside onModuleLoad to see when GWT code is loaded: before or after the crash

  Vassilis

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

Thomas Broyer

unread,
Apr 11, 2017, 11:30:39 AM4/11/17
to GWT Users, philip...@gmail.com


On Tuesday, April 11, 2017 at 4:53:24 PM UTC+2, Philipp Gloor wrote:
Where do I use $wnd.test.JsOpClass()? It doesn't work within <script> tags inside the HMTL file of my GWT project.

$wnd (and $doc) is specific to JSNI. Outside JSNI, in "pure JS", should be able to use "new test.jsOpClass()", after the GWT app has been loaded/started (onModuleLoad).
 
The reason I'm looking at JsInterop was because we want to use web workers. And since there is no GWT implementation of web workers I would do this via native calls. And the web worker would only forward methods because once I'm in the worker thread I have to call GWT functions again.

GWT Mainthread --->   Worker.js  ---> GWT in a worker thread

The calls from Worker.js to GWT in the worker thread would also pass an instance of the worker itself into GWT (as JavaScriptObject) so I could call worker.postMessage to get back to the main thread.

A worker is another browsing context as far as browsers are concerns, so you cannot use GWT to write the worker code from within the application code; those would have to be 2 distinct GWT applications.
You can write web worker code with GWT if you use a specific linker that doesn't depend on the DOM. You could try to use the "sso" linker (<add-linker name="sso"/>) maybe, or look for some existing third-party linker for web workers.

Using JsInterop, you could then easily share Java code for the objects that you pass back and forth between the app and the worker.

David

unread,
Apr 12, 2017, 3:01:37 AM4/12/17
to google-we...@googlegroups.com
There is one thing people keep on repeating:
You can only invoke the exported class/method when the gwt app is loaded.

Is there a GWT supported default way that would allow this ?
Otherwise I guess you would need to add a callback mechanism in the EntryPoint (Using JsInterop)



--
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-tool...@googlegroups.com.
To post to this group, send email to google-we...@googlegroups.com.

Philipp

unread,
Apr 12, 2017, 3:41:47 AM4/12/17
to GWT Users, philip...@gmail.com
The JsInterop part worked now - in the end it was the missing -generateJsInteropExports and my confusion when to use $wnd and when not.

Thomas Broyer

unread,
Apr 12, 2017, 5:10:43 AM4/12/17
to GWT Users


On Wednesday, April 12, 2017 at 9:01:37 AM UTC+2, DavidN wrote:
There is one thing people keep on repeating:
You can only invoke the exported class/method when the gwt app is loaded.

Just like with any asynchronously loading script.
For example, the Google Analytics snippet sets up window.ga() so you can call it before the script is loaded, queuing the calls, and when the script loads it'll (probably) replace window.ga() with its own and processing the queued calls.
Shadow AMP works the same (though even simpler): https://www.ampproject.org/fr/docs/guides/pwa-amp/amp-in-pwa
 
Is there a GWT supported default way that would allow this ?
Otherwise I guess you would need to add a callback mechanism in the EntryPoint (Using JsInterop)

You cannot do the same as GA or Shadow AMP by simply exporting some class, but this can (probably) be done using a native JsType to read and re-define the global variable from your onModuleLoad.
Or you could simply check whether a global variable/function with a specific name is defined and then call it from your onModuleLoad (contrary to an approach like Shadow AMP, only one such callback could be defined then).
Reply all
Reply to author
Forward
0 new messages