Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Java varargs with the GWT Javascript Native Interface? (aka, "GWT has no printf()")

I'm trying to quickly learn GWT as part of a new project. I found out that GWT doesn't implement Java's String.format() function, so there's no printf()-like functionality. I knew that some printf() implementations exist for Javascript, so I figured I could paste one of those in as a GWT Javascript Native Interface function. I ran into problems, and decided I'd better make sure that the varargs values were being passed in correctly. That's where things got ugly. First, some example code:

// From Java, call the JSNI function:
test("sourceString", "params1", "params2", "params3");

....

public static native void test(Object... params) /*-{   
    // PROBLEM: this kills GWT!
    // alert(params.length);  

    // returns "function"
    alert(typeof(params));      

    // returns "[Ljava.lang.Object;@b97ff1"
    alert(params);
}-*/;

The GWT docs state that "calling a varargs JavaScript method from Java will result in the callee receiving the arguments in an array". I figured that meant I could at least check params.length, but accessing that throws a JavascriptException wrapped in an UmbrellaException, with no real information. When I do "typeof(params)", it returns "function". As if that weren't odd enough, if I check the string value of params, it returns what appears to be a string version of a Java reference.

So, I guess I'm asking a few different questions here:

1) How do GWT/JSNI varargs actually work, and do I need to do something special to pass in values?
2) What is actually going on here?
3) Is there any easier way to get printf()-style formatting in a GWT application?

like image 273
markerikson Avatar asked Feb 22 '11 23:02

markerikson


People also ask

What is the difference between GWT and Java Native methods?

Methods in Java marked as native may not have a method body. GWT introduces a special comment syntax that follows the Java native rule of having no method body, while allowing you to provide JavaScript code that can be picked up by the GWT compiler.

What is the use of varargs in Java?

The varrags allows the method to accept zero or muliple arguments. Before varargs either we use overloaded method or take an array as the method parameter but it was not considered good because it leads to the maintenance problem. If we don't know how many argument we will have to pass in the method, varargs is the better approach.

What is GWT jsni and how to use it?

GWT JSNI is used to solve problems such as, when we need to integrate GWT with existing handwritten JavaScript or with a third-party JavaScript library. Occasionally, we need to access low-level browser functionality which is not exposed by the GWT class API’s.

What is the difference between calling jsni from Java and native methods?

The caller can’t really tell if the method is native or not. This gives some flexibility in changing about how the method is implemented. It is more complex than calling JSNI from Java. For example, suppose we pass an object to a JSNI method and need to access a field or call a method in that object.


1 Answers

Your JSNI method is receiving the arguments but, unfortunately, can't do anything with them. Java arrays (varargs are implemented by constructing arrays of the passed arguments) are opaque when passed to JSNI methods. You can however achieve your goal with a JsArrayString:

public static native void test(JsArrayString strings) /*-{
  // strings is a normal JavaScript array of strings
}

And calling the method:

String[] jStrings = {"one", "two", "three"};
JsArrayString jsStrings = (JsArrayString)JsArrayString.createArray();

for (String s : jStrings) {
  jsStrings.push(s);
}

test(jsStrings);
like image 177
Jason Terk Avatar answered Sep 28 '22 05:09

Jason Terk