On 18 avr, 22:24, Bobby <
bobbysoa...@gmail.com> wrote:
> I'm in the process of trying to dynamically generate a GWT wrapper for
> an existing JS library and i have a few questions which come down to
> best practices for the most part.
>
> 1. When wrapping a JS library with GWT, is it recommended to leave the
> namespaces intact? If the JS library and the GWT wrapper library have
> the same namespaces, is there a chance of a conflict where GWT code
> will overwrite the original namespaces of the JS library? (i don't
> think this is the case but i wanted to verify)
There's no notion of "namespaces" in the Javascript code resulting
from GWT compilation (actually, there's no notion of "namespaces" in
JavaScript either, at all, but that's just a problem of vocabulary).
Even when compiling in -style PRETTY or DETAILED, GWT shouldn't
override/shadow any JavaScript variable defined outside the GWT code
(everything's initialized in a closure to not polute the global scope,
and in JSNI you should use $wnd.XXX to access a variable called XXX
defined in the global namespace, so...)
> 2. If the JS library that's being wrapped around has classes that may
> need to be constructed from the Java side, then are Overlay Types
> automatically out of the question (in which case plain Java wrapper
> classes would be used) or is it better to still use Overlay Types and
> just expose factory methods for doing the job of the constructors?
Overlay types have no overhead, at all, compared to wrapper classes,
so prefer overlay types and static factory methods.
> 3. If the original JS library has classes where fields are commonly
> accessed directly, as opposed to via getters and setters, then is it
> recommended to remain faithful to the original JS library and expose
> the fields without getters/setters (in which case Overlay Types are
> out of the picture) or ignore this aspect of the original JS library
> and expose getters/setters instead.
See answer to 2; yes, use getters/setters in Java overlay types, I
repeat: there's no overhead implied!
> 4. If the original JS library has a method that has optional
> parameters, for example, myFunc(a, b) where b may be undefined, should
> a single Java method be added, or should multiple overloaded methods
> be used? For example:
> myFunc(a)
> myFunc(a, b)
You can use overloads.
> 5. Should constants be automatically converted to enumerations or
> should they just be left alone?
As you like. There are many ways to map JS constants to GWT Java; all
imply an overhead, except if you hard-code the constant value as a
constant Java field, or if you provide a static getter method that
returns the JS constant using JSNI.
> If you have some insight on these questions (or any others i missed) i
> would really welcome your input.
On 19 avr, 22:42, Bobby <
bobbysoa...@gmail.com> wrote:
> One more for the list:
>
> 6. When the original JS library contains one or more classes with
> methods that receive functions as parameters, what is the best way to
> implement these methods? Should there be a generic Function or
> Callback class on the GWT side that is used as the function parameter
> type?
Functions are not a first-class citizen in Java, so you have to use
interfaces or abstract classes or... and in your JSNI code, pass a
function as the argument that will call back the... callback ;-)
I wouldn't use a generic Callback interface though. One of the
advantages of working with Java is static typing: if you use specific
interfaces, your IDE will flag an error if you pass an erroneous such
callback instance as an argument to a method (and now that the Google
Plugin for Eclipse checks the JSNI code as well and allows for
autocompletion there, there really is not reason not to do it; apart
for the fear of the overhead implied by adding such an interface --
very minor, compared to the number of classes implementing those
interfaces, and probably quickly overweighted by the additional checks
that you'd have to make in your callback instances)
> The function that is passed to the JS method may expect to
> receive a different number of parameters itself, so one option is to
> define the following class in Java:
>
> public class GenericCallback(){
> public void Execute(Object[] Parameters){
> ...
> }
>
> }
>
> With this approach the following JavaScript method:
>
> function doSomething(myCallback){}
>
> Would be translated to the following in GWT:
>
> public final native void doSomething(GenericCallback myCallback)/*-{
> var cb = function(a, b, c, d, e){
> var pars = [a,b,c,d,e];//something fancier than this
> var jcb = this.handler;
> @jcb.GenericCallback::Execute([Ljava/lang/Object;)(pars);
> }
> cb.handler = myCallback;//or something like this that actually
> works
> this.doSomething(cb);
>
> }-*/
public final native void doSomething(GenericCallback myCallback)/*-{
var that = this;
this.doSomething(function(a, b, c, d, e) {
@jcb.MyClass::doSomethingCallback(Ljcb.GenericCallback;IIIII)
(myCallback);
});
}-*/
private static void doSomethingCallback(GenericCallback callback, int
a, int b, int c, int d, int e) {
UncaughtExceptionHandler handler = GWT.getUncaughtExceptionHandler
();
if (handler == null) {
doSomethingCallbackImpl(callback, a, b, c, d, e);
} else {
doSomethingCallbackAndCatch(handler, callback, a, b, c, d, e);
}
}
private static void doSomethingCallbackImpl(GenericCallback callback,
int a, int b, int c, int d, int e) {
callback.onSomething(a, b, c, d, e);
}
private static void doSomethingCallbackAndCatch
(UncaughtExceptionHandler handler, GenericCallback callback, int a,
int b, int c, int d, int e) {
try {
doSomethingCallbackImpl(callback, a, b, c, d, e);
} except (Throwable t) {
handler.onUncaughtException(t);
}
}
> I don't like the idea of joining all the parameters in an array or of
> having a function in Java receive an object array, but otherwise there
> would need to be multiple Execute methods with a different number of
> parameters or even multiple Callback classes in Java, each with its
> own particular Execute method. This wouldn't be so difficult if i was
> generating the code manually.
>
> Here's a concrete example of what i'm talking about:
http://code.google.com/apis/gdata/jsdoc/1.8/google/gdata/Entry.html
>
> This class has methods that receive function callbacks (for example
> deleteEntry). If you were trying to auto generate a GWT wrapper for
> that class how would you handle the methods that receive Function
> parameters? (assuming that we're using Overlay Types for the
> wrapping).
There would be two interfaces involved, one for the <function(Object)>
and another for the <function(Error)>. If the actual type of the
argument can be implied (or at least approached) at compile-time, or
if it depends on how you're calling the methods, I'd probably use
generics:
interface <T> Continuation<T> {
void onContinue(T scope);
}
But actually, in this particular case, I would use a single interface
with onSuccess and onError methods; you could even re-use the
com.google.gwt.user.client.rpc.AsyncCallback interface, wrapping the
JS "Error" object in a custom Java exception.