PDA

View Full Version : JSNI/GXT problem: this$static.items is undefined



jobe451
14 Jun 2009, 3:45 PM
I came around some very odd JSNI/GXT problem. I tried for hours to wrap some os-file-uploader project into gxt and failed. Explaining what I had to do might be confusing. Only so much: I tried to assign to some project specific native javascript EventHandles some GWT-functions via JSNI.

To describe where I got stuck I wrote some sample code.

The code below has a function called printString(String t).

The button "direct Call" executes this function:
1. it pops up an alert box "printing: direct call"
2. after clicking "ok", it adds the text "direct Call" to the page

The button "via JSNI call" actually should do the very same. However it does a detour via nativ javascript using JSNI. First I assign to a javascript function the gwt-function printString(String t). Second I call this native javascript function(printStringJs) which refers to my GWT-function (printString). What happens is:
1. The alert box pops up just as before
2. no text is add but, I get a java script error: this$static.items is undefined

What is highly odd is: I obviously managed to access the very same GWT method (the alert box is shown as before). However, when it tries to execute the second instruction (adding a GXT Text Object) the whole thing fails. Some how the same function from the same object does not the same...

Maybe somebody knows some help. Or maybe this can/should be fixed somewhere else?

Here now my sample code:


package dk.demo.client;

import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.Text;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootPanel;


public class Demo implements EntryPoint {

private LayoutContainer content = new LayoutContainer ();
private final Demo thisPage = this;

public void onModuleLoad() {

// Assign printString(String t) to a native javascript function
initScript(this);

Button dButton = new Button("direct call");
dButton.addSelectionListener(new SelectionListener<ButtonEvent>() {
public void componentSelected(ButtonEvent ce) {
thisPage.printString("direct Call");
}
});

Button sButton = new Button("via JSNI call");
sButton.addSelectionListener(new SelectionListener<ButtonEvent>() {
public void componentSelected(ButtonEvent ce) {
thisPage.printStringJs("same call via JSNI Function");
}
});

content.add(dButton);
content.add(sButton);
RootPanel.get().add(content);
}

private void printString(String t) {
Window.alert("printing: " + t);
content.add(new Text(t));
content.layout();
}

private native void initScript(Demo d) /*-{
$wnd.myFunc = d.@dk.demo.client.Demo::printString(Ljava/lang/String;);
}-*/;

private native void printStringJs(String s) /*-{
$wnd.myFunc(s);
}-*/;
}

jobe451
15 Jun 2009, 12:05 AM
I'd like to add some details to what I described above.

The described behaviour only applies to browser mode.

In hosted mode I get an error instead:
com.google.gwt.dev.shell.ie.IDispatchImpl$HResultException: Instance method 'printString' needed a qualifying instance (did you forget to prefix the call with 'this.'?)


In my orignal implementation, in hosted mode I didn't get that error. Instead, in hosted mode when calling back to gwt, 'nothing' happend. It seems I can exactly reproduce my orignal problem. However, also this behaviour I don't understand.

I found a page with a similar problem here:
http://www.gwt-ext.com/forum/viewtopic.php?f=8&t=3165&p=10062

jobe451
15 Jun 2009, 3:16 AM
I am sorry for the confusion. I found the problem. Seems that the method should be assigned in a different way.

According to the guy here, the way I chose makes javascript see the assigned method as static one:
http://markmail.org/message/ra2i4s5gxoibyjvt#query:%22com.google.gwt.dev.shell.ie.IDispatchImpl%24HResultException%3A%20Instance%20method%20%22+page:1+mid:3hz6bbpqbna4vejm+state:results

This works now:


package dk.demo.client;

import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.Text;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootPanel;


public class Demo implements EntryPoint {

private LayoutContainer content = new LayoutContainer ();
private final Demo thisPage = this;

public void onModuleLoad() {

// Assign printString(String t) to a native javascript function
initScript(this);

Button dButton = new Button("direct call");
dButton.addSelectionListener(new SelectionListener<ButtonEvent>() {
public void componentSelected(ButtonEvent ce) {
thisPage.printString("direct Call");
}
});

Button sButton = new Button("via JSNI call");
sButton.addSelectionListener(new SelectionListener<ButtonEvent>() {
public void componentSelected(ButtonEvent ce) {
thisPage.printStringJs("same call via JSNI Function");
}
});

content.add(dButton);
content.add(sButton);
RootPanel.get().add(content);
}

private void printString(String t) {
Window.alert("printing: " + t);
content.add(new Text(t));
content.layout();
}

public native void initScript(Demo d) /*-{
$wnd.myFunc = function(s) {
d.@dk.demo.client.Demo::printString(Ljava/lang/String;)(s);
}
}-*/;

private native void printStringJs(String s) /*-{
$wnd.myFunc(s);
}-*/;
}