GWT/JS Bridging with JSNI

42 views
Skip to first unread message

ahhughes

unread,
Oct 29, 2007, 11:45:56 PM10/29/07
to Google Web Toolkit
Hi All,

I'm trying to get a native JS bridge working. For those of you who
don't understand this is providing native JS constructors/functions to
your GWT objects/classes. When trying to access these functions from
js it always says that "Employee is not defined" in the example
below...

Obviously the export() has either not been executed, or there is
something wrong with my JSNI code.

----------------------------------------------------

package jsni.export.test;

public class Employee {

private String name;

public Employee(String name) {
this.name = name;
}

public String getName() {
return name;
}

public static Employee createEmployee(String name) {
return new Employee(name);
}

public native void export() /*-{
$wnd.Employee = function(name) {
// call factory method and store GWT reference
this.instance = @jsni.export.test.Employee::createEmployee(Ljava/
lang/String;)(name);

}
var _= $wnd.Employee.prototype;
_.getNameName = function() {
this.instance.@jsni.export.test.Employee::getName()();
}
}-*/;
}

--------------------------------------
js.....

var employee = new Employee('James Bond');
alert('Welcome '+employee.getName());

---------------

Can anyone confirm:
+ My JSNI/Code above looks ok... particularly..
this.instance = @jsni.export.test.Employee::createEmployee(Ljava/lang/
String;)(name);
+ Do I need to exclusively call Employee.export() from somewhere to
get method this to run? I have tried this, but it still doesn't seem
to matter.
+ Is there a problem with this not being in the *.client.Employee
package? I tried both inside and out without success.

thanks y`all

David Clément

unread,
Oct 30, 2007, 5:10:23 AM10/30/07
to Google-We...@googlegroups.com
You cannot call it directly in JS, GWT is not loaded when this code is running.

Try to call it from a button, you may have more success.

ahhughes

unread,
Oct 30, 2007, 7:09:13 AM10/30/07
to Google Web Toolkit
hmmm that is disappointing, but would be a fitting reason for my
problem.

is there a way around this... onLoad() could be used on the page?


On Oct 30, 7:10 pm, "David Clément" <dav.clem...@gmail.com> wrote:
> You cannot call it directly in JS, GWT is not loaded when this code is running.
>
> Try to call it from a button, you may have more success.
>

> > this.instan...@jsni.export.test.Employee::getName()();

David Clément

unread,
Oct 30, 2007, 7:21:38 AM10/30/07
to Google-We...@googlegroups.com
If you find the solution, I would really like to have it.
The only solution I have found is to create some "configurations" in
the JS and to retrieve these configurations in the GWT onModuleLoad().

Another option is to add a JSNI method call at the end of your GWT onModuleLoad.
As example a JSNI method like
if($wnd.onGWTLoaded){
$wnd.onGWTLoaded();
}

On 10/30/07, ahhughes <ahhu...@gmail.com> wrote:
>

ahhughes

unread,
Oct 30, 2007, 8:21:51 AM10/30/07
to Google Web Toolkit
We'll we *could* run this VERY NASTY piece of code in the js... which
will pole the exported gwt function until it succeeds.. but yeah, its
dodgy!

var gwtApplication = false;
while(!gwtApplication){
try {
gwtApplication = exportedGWTFunction();
} catch (e){
//pause for a micro second or so...

David Clément

unread,
Oct 30, 2007, 8:44:00 AM10/30/07
to Google-We...@googlegroups.com
Yes that's why I think that you should make GWT call your JS!

On 10/30/07, ahhughes <ahhu...@gmail.com> wrote:
>

TrashHalo

unread,
Oct 30, 2007, 8:49:48 AM10/30/07
to Google Web Toolkit
Why not use onModuleLoad? Create a method that forms all your exported
methods in JS then call it at the end of onModuleLoad

or did I miss something?

David Clément

unread,
Oct 30, 2007, 9:03:08 AM10/30/07
to Google-We...@googlegroups.com
It's what I was proposing ;-)

ahhughes

unread,
Oct 30, 2007, 9:10:01 AM10/30/07
to Google Web Toolkit
We'll I'm not 100% of how that would work... the onLoadModule() is
within the GWT app. I am looking to expose the constructor & methods
of my GWT application to native JS programmers. So the only way I
think this would work would be if I expected the js programmer to
provide a specifically named method to be called from inside the GWT
onLoadModule, or even at the end of the the native export() code....

public native void export() /*-{
$wnd.Employee = function(name) {
// call factory method and store GWT reference
this.instance =
@jsni.export.test.Employee::createEmployee(Ljava/
lang/String;)(name);

}
var _= $wnd.Employee.prototype;
_.getNameName = function() {

this.instan...@jsni.export.test.Employee::getName()();
}

//call the known function the js programmer must
provide
$wnd.initEmployee();
}-*/;

David Clément

unread,
Oct 30, 2007, 9:34:21 AM10/30/07
to Google-We...@googlegroups.com
Yes, that's what you need to do unless these methods are called once
GWT is loaded (from user interaction, as example)

On 10/30/07, ahhughes <ahhu...@gmail.com> wrote:
>

ahhughes

unread,
Oct 30, 2007, 10:27:10 AM10/30/07
to Google Web Toolkit
Thanks everyone for your help.


On Oct 30, 11:34 pm, "David Clément" <dav.clem...@gmail.com> wrote:
> Yes, that's what you need to do unless these methods are called once
> GWT is loaded (from user interaction, as example)
>

ahhughes

unread,
Oct 30, 2007, 7:27:59 PM10/30/07
to Google Web Toolkit
Hmmm this still does not work...

I've this but I just get employee.getName() being 'undefined'....

----HTML/JS----
<html>
......
<button onclick="runJSNI()">Run JSNI</button>
<script type="text/javascript">
runJSNI = function(){


var employee = new Employee('James Bond');

alert('The new employee is: '+employee.getName());
}

</script>
....
</html>

----Export of GWT via JSNI----
package mygwtapp.client;

public class Employee {

private String name;

public Employee(String name) {
this.name = name;
}

public String getName() {
return name;
}

public static Employee createEmployee(String name) {
return new Employee(name);
}

public native void export() /*-{


$wnd.Employee = function(name) {
// call factory method and store GWT reference
this.instance =

@mygwtapp.client.Employee::createEmployee(Ljava/lang/String)(name);

}
var _= $wnd.Employee.prototype;
_.getName = function() {
this.instance.@mygwtappclient.Employee::getName()
();
}
}-*/;
}

----Entry Point that triggers the Empoyee JSNI export()----
package myelders.demand.broadband.client;

import mygwtapp.client.contribute.ContributeWidget;

import com.google.gwt.core.client.EntryPoint;

public class Application implements EntryPoint {

public void onModuleLoad() {
Employee employee = new Employee("BLAH");
employee.export();
}
}

------

My head hurts :'( debugging native JS, calling JSNI, from GWT driven
JS...

stuckagain

unread,
Dec 7, 2007, 10:39:32 AM12/7/07
to Google Web Toolkit
Hi,

Did you get it working yet ? I tried your example code and while the
Javascript does not compile through GWT (some ; missing and such).

Here is code that works for me: (assuming groups does not modify it
like it apparently did to your post). (email me if you need the
working code)
The only thing that will not work is if you try to click the button
before the GWT application is fully loaded. For that you need to call
back into the
HTML/Javascript to signal when the app is ready for action.

Here are my changes:

Export test:
<html>
<head>
<script type="text/javascript" src="mygwtapp.App.nocache.js"></
script>
<title>JSExport test</title>
</head>
<body>
<button onclick="runJSNI()">Run JSNI</button>
<script type="text/javascript">
runJSNI = function(){
var employee = new Employee('James Bond');
alert('The new employee is:
'+employee.getName());
return false;
}

</script>
</body>
</html>

// GWT EntryPoint
public class Application implements EntryPoint {
public void onModuleLoad() {
Employee.export();
}

}

// Employee class
public class Employee {

private final String name;

public Employee(final String name) {
this.name = name;
}

public String getName() {
return name;
}

public static native void export() /*-{
$wnd.Employee = function( pName ) {
this.instance = @mygwtapp.client.Employee::createEmployee(Ljava/
lang/String;)(pName);
};
var _= $wnd.Employee.prototype;
_.getName = function() {
return this.instance.@mygwtapp.client.Employee::getName()();
};
}-*/;

public static Employee createEmployee(final String name) {
return new Employee(name);
}

}


On Oct 31, 12:27 am, ahhughes <ahhug...@gmail.com> wrote:
> Hmmm this still does not work...
>
> I've this but I just get employee.getName() being 'undefined'....
>
> ----HTML/JS----
> <html>
> ......
> <button onclick="runJSNI()">Run JSNI</button>
> <script type="text/javascript">
> runJSNI = function(){
> var employee = new Employee('James Bond');
> alert('The new employee is: '+employee.getName());
> }
>
> </script>
> ....
> </html>
>
> ----Exportof GWT via JSNI----
> package mygwtapp.client;
>
> public class Employee {
>
> private String name;
>
> public Employee(String name) {
> this.name = name;
> }
>
> public String getName() {
> return name;
> }
>
> public static Employee createEmployee(String name) {
> return new Employee(name);
> }
>
> public native voidexport() /*-{
> $wnd.Employee = function(name) {
> // call factory method and store GWT reference
> this.instance =
> @mygwtapp.client.Employee::createEmployee(Ljava/lang/String)(name);
>
> }
> var _= $wnd.Employee.prototype;
> _.getName = function() {
> this.instan...@mygwtappclient.Employee::getName()
> ();
> }
> }-*/;
>
> }
>
> ----Entry Point that triggers the Empoyee JSNIexport()----
> package myelders.demand.broadband.client;
>
> import mygwtapp.client.contribute.ContributeWidget;
>
> import com.google.gwt.core.client.EntryPoint;
>
> public class Application implements EntryPoint {
>
> public void onModuleLoad() {
> Employee employee = new Employee("BLAH");
> employee.export();
> }
>
> }
>
> ------
>
> My head hurts :'( debugging nativeJS, calling JSNI, from GWT drivenJS...
>
> On Oct 31, 12:27 am, ahhughes <ahhug...@gmail.com> wrote:
>
>
>
> > Thanks everyone for your help.
>
> > On Oct 30, 11:34 pm, "David Clément" <dav.clem...@gmail.com> wrote:
>
> > > Yes, that's what you need to do unless these methods are called once
> > > GWT is loaded (from user interaction, as example)
>
> > > On 10/30/07, ahhughes <ahhug...@gmail.com> wrote:
>
> > > > We'll I'm not 100% of how that would work... the onLoadModule() is
> > > > within the GWT app. I am looking to expose the constructor & methods
> > > > of my GWT application to nativeJSprogrammers. So the only way I
> > > > think this would work would be if I expected thejsprogrammer to
> > > > provide a specifically named method to be called from inside the GWT
> > > > onLoadModule, or even at the end of the the nativeexport() code....
>
> > > > public native voidexport() /*-{
> > > > $wnd.Employee = function(name) {
> > > > // call factory method and store GWT reference
> > > > this.instance =
> > > > @jsni.export.test.Employee::createEmployee(Ljava/
> > > > lang/String;)(name);
>
> > > > }
> > > > var _= $wnd.Employee.prototype;
> > > > _.getNameName = function() {
>
> > > > this.instan...@jsni.export.test.Employee::getName()();
> > > > }
> > > > //call the known function thejsprogrammer must
> > > > provide
> > > > $wnd.initEmployee();
> > > > }-*/;
>
> > > > }
>
> > > > On Oct 30, 10:49 pm, TrashHalo <TrashH...@gmail.com> wrote:
> > > > > Why not use onModuleLoad? Create a method that forms all your exported
> > > > > methods inJSthen call it at the end of onModuleLoad
>
> > > > > or did I miss something?
>
> > > > > On Oct 30, 8:21 am, ahhughes <ahhug...@gmail.com> wrote:
>
> > > > > > We'll we *could* run this VERY NASTY piece of code in thejs... which
> > > > > > will pole the exported gwt function until it succeeds.. but yeah, its
> > > > > > dodgy!
>
> > > > > > var gwtApplication = false;
> > > > > > while(!gwtApplication){
> > > > > > try {
> > > > > > gwtApplication = exportedGWTFunction();
> > > > > > } catch (e){
> > > > > > //pause for a micro second or so...
> > > > > > }
>
> > > > > > }
>
> > > > > > On Oct 30, 9:21 pm, "David Cl?ment" <dav.clem...@gmail.com> wrote:
>
> > > > > > > If you find the solution, I would really like to have it.
> > > > > > > The only solution I have found is to create some "configurations" in
> > > > > > > theJSand to retrieve these configurations in the GWT onModuleLoad().
>
> > > > > > > Another option is to add a JSNI method call at the end of your GWT onModuleLoad.
> > > > > > > As example a JSNI method like
> > > > > > > if($wnd.onGWTLoaded){
> > > > > > > $wnd.onGWTLoaded();
>
> > > > > > > }
>
> > > > > > > On 10/30/07, ahhughes <ahhug...@gmail.com> wrote:
>
> > > > > > > > hmmm that is disappointing, but would be a fitting reason for my
> > > > > > > > problem.
>
> > > > > > > > is there a way around this... onLoad() could be used on the page?- Hide quoted text -
>
> - Show quoted text -
Reply all
Reply to author
Forward
0 new messages