JSNI scope

95 views
Skip to first unread message

jissa

unread,
Sep 14, 2007, 6:41:36 PM9/14/07
to Google Web Toolkit
I have an application that is running on GWT 1.3.3. This application
uses the native interface to access an existing native javascript code
to retrieve data that the javascript collected. The javascript in turn
calls a function in the GWT application back with the data. I am
trying to using this data to update widget but I keep getting an error
that the objects are undefined.

The widgets in this class are not static, I tried making the widgets
static and it seems to work.

Is this the only way to access the widget when a function is being
called from Javascript or is there a way to do this differently.

Thank you.

This is a snippet of my code

private native void RequestBeaconData(BeaconPanel inst, String req) /*-
{
$wnd.makeRequest(req,
this.@com.datron.client.BeaconPanel::parseBeacon(Ljava/lang/String;));
}-*/;

private void parseBeacon(String responseText) {
String[] data = responseText.split(",");
try {
freq = Double.parseDouble(data[0]);
} catch (NumberFormatException e1) {
freq = 0.0;
}
try {
signal = Double.parseDouble(data[1]);
} catch (NumberFormatException e1) {
signal = 0.0;
}
try {
agc = Double.parseDouble(data[2]);
} catch (NumberFormatException e1) {
agc = 0.0;
}
try {
noise = Double.parseDouble(data[3]);
} catch (NumberFormatException e1) {
noise = 0.0;
}
try {
lock = Integer.parseInt(data[4]);
} catch (NumberFormatException e) {
lock = 0;
}
try {
state = Integer.parseInt(data[5]);
} catch (NumberFormatException e) {
state = 0;
}
if (data.length > 7) {
xtrack = Double.parseDouble(data[6]);
ytrack = Double.parseDouble(data[7]);
sdtrack = Double.parseDouble(data[8]);
}
updateStatus();
}
private void updateStatus() {

stsFreq.setText(""+freq);
stsSignal.setText(""+signal);
stsAgc.setText(""+agc);
stsNoise.setText(""+noise);

if (lock == 1) {
stsLock.setText("Locked");
stsLock.setStyleName("gui-BeaconLocked");
}
else {
stsLock.setText("UnLocked");
stsLock.setStyleName("gui-BeaconUnLocked");
}
if (state < states.length) {
stsTrackState.setText(states[state]);
}
else {
stsTrackState.setText("" + state);
}
stsXTracking.setText(""+xtrack);
stsYTracking.setText(""+ytrack);
stsSdTracking.setText(""+sdtrack);
}

Nathan Williams

unread,
Sep 15, 2007, 2:05:34 AM9/15/07
to Google Web Toolkit
If your host page has a JS function that returns some payload string:

function getData() {
return "some data";
}

Then you should be able to call that function and pass its result to
an instance method using JSNI that looks like this:

private native void loadData() /*-{
data = $wnd.getData();
this.@com.example.MyClass::setData(Ljava/lang/String;)(data);
}-*/;

private void setData(String data) {
// do something w/results
}

Note:
http://code.google.com/webtoolkit/documentation/com.google.gwt.doc.DeveloperGuide.JavaScriptNativeInterface.JavaFromJavaScript.html

jissa

unread,
Sep 15, 2007, 12:39:32 PM9/15/07
to Google Web Toolkit
What I am trying to do is to get an asynchronous call from JS into GWT
that contains the payload. The only way I see it is that when the
asynchronous call to my GWT function comes in, it can only access the
static member of that class whether it class variables or class
widgets.

I was wondering if that is the only way or is there another way to
make the call so i can get access to instance members not just static
members.

The main reason I am doing this is that I have a JS code that does
HTTP request and can return error without any memory leaks, while the
RequestBuilder in GWT has memory leaks in IE.

Thank you

Johnny

On Sep 14, 11:05 pm, Nathan Williams <nlwil...@gmail.com> wrote:
> If your host page has a JS function that returns some payload string:
>
> function getData() {
> return "some data";
> }
>
> Then you should be able to call that function and pass its result to
> an instance method using JSNI that looks like this:
>
> private native void loadData() /*-{
> data = $wnd.getData();

> th...@com.example.MyClass::setData(Ljava/lang/String;)(data);


> }-*/;
>
> private void setData(String data) {
> // do something w/results
> }
>

> Note:http://code.google.com/webtoolkit/documentation/com.google.gwt.doc.De...

Nathan Williams

unread,
Sep 15, 2007, 1:55:52 PM9/15/07
to Google Web Toolkit
How about this?

private native void loadData() /*-{

var handle = this;
callback = function(data) {

han...@com.example.MyClass::setData(Ljava/lang/String;)(data);
};
data = $wnd.getData(callback);
}-*/;


johnny

unread,
Sep 17, 2007, 12:39:22 PM9/17/07
to Google Web Toolkit
That would work but still would not solve my problem. My problem
occurs in the callback function where the call function can't access
any of the widgets in the instance class but the static widgets

Johnny

Reinier Zwitserloot

unread,
Sep 17, 2007, 6:41:41 PM9/17/07
to Google Web Toolkit
RequestBuilder has memory leaks?

First I heard of it. If this is true, you should file a bug report.

Sumit Chandel

unread,
Sep 17, 2007, 7:01:09 PM9/17/07
to Google-We...@googlegroups.com
Hi everyone,

It's possible that RequestBuilder has memory leaks in IE. There is already an issue that was created for this (Issue #1406) that we thought had been fixed, but it has since been reopened to investigate the issue further.

http://code.google.com/p/google-web-toolkit/issues/detail?id=1406&can=1&q=RequestBuilder

You can 'star' the issue to keep track of its status. In the meantime, I believe the workaround that Nathan suggested will work.

Thanks,
-Sumit Chandel

Nathan Williams

unread,
Sep 18, 2007, 12:23:11 AM9/18/07
to Google Web Toolkit
Actually, I think my second suggestion will solve your problem. Let
me rephrase it in the terms of your original post:

private native void RequestBeaconData(String req) /*-{
var handle = this; // is a reference to the instance
on which this method is being called
callback = function(data) {
// "this" in this scope is a different object,
so we have to call through "handle" instead

han...@com.datron.client.BeaconPanel::parseBeacon(Ljava/lang/String;)
(data);
}
$wnd.makeRequest(req, callback); // assuming call of
callback("...data-to-parse...") when done
}-*/;

Think of the callback like an anonymous inner class in Java. The
inner "this" references a completely different object than the outer
"this", and unfortunately it's the "outer this" that is connected to
the instance method you're trying to call. So, you have to find some
way to make it available in a scope that will be visible to the
callback method. The Java analogue is declaring a local variable or
parameter final so you can access it in an inner scope.

mP

unread,
Sep 18, 2007, 2:29:15 AM9/18/07
to Google Web Toolkit
Try and avoid jsni as much as possible. Only do small simple things
and no more with the majority of your logic in proper java.

Reply all
Reply to author
Forward
0 new messages