GWT problem with calling Java methods from JSNI - gwt

I tried the example from google at this page:
http://code.google.com/docreader/#p=google-web-toolkit-doc-1-5&s=google-web-toolkit-doc-1-5&t=DevGuideJavaFromJavaScript
I want to be able to call a Java method from JSNI, but nothing happens. No errors but the methods are not called. However, I can modify the fields from my class.
Here is the code I tried:
package com.jsni.client;
import com.google.gwt.core.client.EntryPoint;
public class Testjsnii implements EntryPoint {
String myInstanceField;
static int myStaticField;
void instanceFoo(String s) {
System.out.println(s);
}
static void staticFoo(String s) {
System.out.println(s);
}
public native void bar(Testjsnii x, String s) /*-{
this.#com.jsni.client.Testjsnii::instanceFoo(Ljava/lang/String;)(s);
x.#com.jsni.client.Testjsnii::instanceFoo(Ljava/lang/String;)(s);
#com.jsni.client.Testjsnii::staticFoo(Ljava/lang/String;)(s);
var val = this.#com.jsni.client.Testjsnii::myInstanceField;
}-*/;
public void onModuleLoad() {
bar(this,"Hello");
}
}
It prints nothing on the console but only a waring that says:
[WARN] [testjsnii] - JSNI method
'#com.jsni.client.Testjsnii::bar(Lcom/jsni/client/Testjsnii;Ljava/lang/String;)' returned > a value of type JavaScript object(1) but was declared void; it should not have returned a > value at all
I wonder what is the problem.
Thanks for the help.

You're actually running into a Chrome (10-dev) issue with the GWT DevMode plugin: http://code.google.com/p/google-web-toolkit/issues/detail?id=5778

Related

GWT JSNI: pass js element to gwt Element will lose all children

I was trying to wrap some jquery function to GWT, run below js code, the size is 2.
var html="<div><p>paragraph</p><div>second</div></div>";
var size=$(html).get(0).children.length;
alert(size);
but run below GWT code
select(html).get(0).getChildCount();
just return 0, the select function is like below:
public class JQuery extends JavaScriptObject {
protected JQuery() {
}
public static final native JQuery select(String selector) /*-{
return $wnd.jQuery(selector);
}-*/;
public final native Element get(int index) /*-{
return this.get(index) || null;
}-*/;
}
I'd like to know why it just loses the children elements from JSNI method, and what's the right way to this wrapping to let it behave exactly same to native jquery?
Thanks.
-------------EDIT------------------------------------------------------------
I test above JSNI code in a real gwt project and it works fine, the children elements are returned from js to java. But in GwtTestCase problem exists.
public class JQueryTest extends GWTTestCase {
#Override
public String getModuleName() {
return "com.jsnitest.JsniTest";
}
public void testSelectHtml() {
ScriptInjector.fromUrl("http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js").setWindow(
ScriptInjector.TOP_WINDOW).setCallback(new Callback<Void, Exception>() {
#Override
public void onFailure(Exception reason) {
}
#Override
public void onSuccess(Void result) {
int childCount = select("<div><p>paragraph</p><div>second</div><ul></ul></div>").get(0).getChildCount();
//Fail! childCount=0
assertEquals(3, childCount);
}
}).inject();
}
}
gwtquery a.k.a. gQuery is a jQuery-like API written in GWT.
Following the principle of DRY, I would use this library instead of wrapping jQuery.
The only reason I see to wrap jQuery in GWT is that you needed very specific features in jQuery not present in gQuery, although gQuery has almost completed the jQuery API.

Cordova.exec function doesn't run the native function

I try to make a cordova plugin in IBM worklight.
Javascript:
HelloWorld = {
sayHello: function (success, fail, resultType) {
Cordova.exec(
success,
fail,
"HelloWorld",
"HelloWorld",
[resultType]
);
}
};
function callFunction() {
HelloWorld.sayHello(basarili, basarisiz, "sinan");
}
Java:
package com.Cordova1;
import org.apache.cordova.api.CordovaPlugin;
import org.json.JSONArray;
import android.util.Log;
public class HelloWorld extends CordovaPlugin {
public boolean execute(String arg0, JSONArray arg1, String arg2) {
Log.d("HelloPlugin", "Hello, this is a native function called from PhoneGap/Cordova!");
return true;
}
}
When I call callFunction I see that fail function worked. Also, I can't see any HelloPlugin message in log window.
What can I do ?
module 09_3 ApacheCordovaPlugin in the samples is indeed using the deprecated Plugin class instead of CordovaPlugin. I have rewritten the HelloWorldPlugin class in module 09_3 to eliminate the deprecated Cordova Plugin API usage. The sample is working fine.
package com.AndroidApacheCordovaPlugin;
import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.CordovaPlugin;
import org.json.JSONArray;
import org.json.JSONException;
public class HelloWorldPlugin extends CordovaPlugin {
#Override
public boolean execute(String action, JSONArray arguments,
CallbackContext callbackContext) throws JSONException {
if (action.equals("sayHello")) {
String responseText = "Hello world";
try {
responseText += ", " + arguments.getString(0);
callbackContext.success(responseText);
return true;
} catch (JSONException e) {
callbackContext.error(e.getMessage());
}
} else {
callbackContext.error("Invalid action: " + action);
return false;
}
return false;
}
}
A couple of things, 1) did you add a line for your plugin into the config.xml file? and 2) you seem to be overriding the wrong method in CordovaPlugin. It should be:
public boolean execute(String action, JSONArray args, CallbackContext callbackContext)
I was having the same problem. Have a look at module 09_3 ApacheCordovaPlugin in the samples. That example does work for me, but they are using the deprecated Plugin class instead of CordovaPlugin.
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
...
public class HelloWorldPlugin extends Plugin {
public PluginResult execute(String action, JSONArray arguments, String callbackId) {
The deprecated class returns PluginResult, not a boolean. I've tried the same code using the CordovaPlugin signature and that results in a fail every time. Apparently whatever WL code is invoking the plugin is apparently expecting the signature of the deprecated class.
I solved the problem.
I use the version 2.4 of cordova. I can't understand why it didn't work. when I use "cordova.exec" it doesn't work, however when I use PhoneGap.exec it works.
Also I looked for the definition;
In the last line of cordova-2.4.0.js, it says
var PhoneGap = cordova;
Ok, Phonegap was defined, but I don't know why cordova doesn't work.
Thank you for your answers.

How to call java method from javascript method that located within another jsni method

public class A{
private void javaMethod(int a,int b){}
private native void init()/*-{
function OnMouseMove(e) {
//blow calling doesn't work
this.#p::javaMethod(Ljava/...teger;Ljava.../Integer;)(intVal,intVal);
}
}-*/;
}
As described above,how to make that invoking work?
Answered on the Google Group: https://groups.google.com/d/msg/google-web-toolkit/qE2-L4u_t4s/YqjOu-bUfsAJ
Copied here for reference and convenience:
First, int is not java.lang.Integer, so your method signature in JSNI is wrong; it should read javaMethod(II).
(I suppose the #p:: while javaMethod is defined in class A is over-simplification in your question, but is OK in your code)
You'll also probably have a problem with this, that might not be what you think it is. A common pattern is to assign the current object (this, at the time) to a variable that you'll reference from your closure:
var that = this;
…
function OnMouseMove(e) {
that.#p.A::javaMethod(II)(intVal, intVal);
}
You're doing two things wrong:
You're not defining the class name after #p, (assuming #p is actually just a shortened version of the real package's name);
You're attempting to pass java.lang.Integer in place of int. You should be saying (II) as the types, as described here.
Your code should look more like this:
package com.my.package;
public class ClassA {
private static void javaMethod(int a, int b) { ... }
public static native void init() /*-{
$wnd.javaMethod = function(a, b) {
return #com.my.package.ClassA::javaMethod(II)(a,b);
}
function OnMouseMove(e) {
$wnd.javaMethod(a,b);
}
}-*/;
}

Use Java constant in GWT Javascript Overlay Type (JSO)?

I would like to define the GWT JSO property name as a constant in the JSO, in order to avoid typos and benefit from Eclipse code completion, like so:
public final class MyJSO extends JavaScriptObject
{
/** here is the constant */
private static final String MY_CONST = "myPropName";
protected MyJSO() {
super();
}
public native void setMyProp(final boolean pFlag)
/*-{
this.#fully.qualified.MyJSO::MY_CONST = pFlag;
}-*/;
public native boolean isMyProp()
/*-{
if (this.hasOwnProperty(#fully.qualified.MyJSO::MY_CONST)) {
return this.#fully.qualified.MyJSO::MY_CONST;
} else {
return false;
}
}-*/;
}
The GWT compiler should be able to replace the String from the constant at compile time, so there is no problem with the object living as Javascript later on.
But this is so totally not working, I'm thinking I may be wrong. :-) Can anyone explain why? Do you have better ideas how to achieve this?
Thanks!
The correct syntax to refer to a static variable is:
#fully.qualified.MyJSO::MY_CONST
No qualifier (this., in your example) is needed since the variable is static.
If you want to set/get a property on the JavaScript object with the constant name do so as follows:
public native void setMyProp(final boolean pFlag) /*-{
this[#fully.qualified.MyJSO::MY_CONST] = pFlag;
}-*/;
public native boolean isMyProp() /*-{
if (this[#fully.qualified.MyJSO::MY_CONST] != null) {
return this[#fully.qualified.MyJSO::MY_CONST];
} else {
return false;
}
}-*/;

Using phonegap audio api in gwt

I am wanting to use the phonegap audio api in GWT using JSNI.I cannot figure out how to code the methods in JSNI.
Wondering if anyone know of any tutorials.They javascript methods are really pretty simple.
http://docs.phonegap.com/phonegap_media_media.md.html
Basically it sounds like it would be something like this:
public final class Media extends JavaScriptObject {
protected Media() {}
public static native final Media newInstance(String src, Command command) /*-{
var callback = function() { command.execute(); };
return new Media(src, callback);
}-*/;
public native final void getCurrentPosition(AsyncCallback<String> command) /*-{
var callback = function(position) { command.onSuccess('' + position); };
this.getCurrentPosition(callback);
}-*/;
public native final void play() /*-{
this.play();
}-*/;
//... more methods here
}
Usage:
Media m = Media.newInstance("http://www.example.com/src.mp3", new Command() {
#Override
public void execute() {
// Code executed after Media is created.
}
});
m.getCurrentPosition(new AsyncCallback<String>() {
#Override
public void onSuccess(String position) {
Window.alert(position);
}
});
m.play();
That's a rough sketch, if you know more about what the type being passed to the callback is you can do nicer things like have it be an int or another JS Overlay Type.
The API is kind of weird because everything is apparently asynchronous, but that's life.
Once you've gotten the hang of writing GWT JSNI bindings it's pretty straightforward.
If you end up getting further down this road, it would be awesome if you open-sourced your GWT wrapper library so other GWT developers could write some iPhone/Android apps.
I just need the play method really.I am not quite as knowledgeable to do this correctly I guess.That code looks really foreign to me :-)
Still cannot accept your answer.The site does not recognize me it is strange.
I get the following error when trying to use the media in my onModuleLoad
The constructor TESTPHONEGAP.Media(String, new Command(){}) is undefined
Media m = new Media("test.mp3", new Command() {
#Override
public void execute() {
}
});
m.play()
Using your class as an "inner class" in same file as my main onModuleLoad