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

1

6

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?

Grimona answered 22/2, 2011 at 23:23 Comment(0)
T
5

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);
Tweed answered 23/2, 2011 at 0:28 Comment(4)
Odd. If Java arrays become opaque to JSNI, then what good is Java->JSNI varargs? I'll try out your suggestion at work tomorrow. The main downside I see with it is not having type formatting done automatically.Grimona
The benefit, for now, of Java->JSNI varargs is being able to pass the arguments from JSNI to Java, i.e. Java->JSNI->Java. Limited to say the least. There's a GWT ticket open regarding this issue so it at least is on the dev team's radar.Tweed
Managed to dig up an old pre-Java 1.5 sprintf() implementation that I can use ( http://java.sun.com/developer/technicalArticles/Programming/sprintf/ ). Looks like your answer to the JSNI aspect is probably the right way to do if I were to go that way, though. Thanks.Grimona
just related to them code.google.com/p/google-web-toolkit/issues/detail?id=5255Photofluorography

© 2022 - 2024 — McMap. All rights reserved.