Nasty overlay types restrinction : Only one JavaScriptObject type may implement the methods of an interface

634 views
Skip to first unread message

Sebastián Gurin

unread,
Sep 6, 2012, 2:22:16 PM9/6/12
to google-we...@googlegroups.com
Hi all. I'm writing a lot of GWT overlay types for my new project YUIGWT - http://code.google.com/p/yuigwt/. I'm creating a nice and rich java hierarchy of overlay types there.

Today I discovered that it is not good to let overlay types (extends JavaScriptObject implement interfaces because it seems that for a certain interface, no more than one overlay type can implement its methods. The error in question is pasted below, but this arrises a big question for me:

While I understand perfectly what the error means, I would really appreciate if somebody can explain me the reasons behind this nasty restriction ? ??

    [ERROR] [org.sgx.yuigwt.YuiGwtTestOnline] - Line 9: Only one JavaScriptObject type may implement the methods of an interface that declared methods. The interface (org.sgx.yuigwt.yui.yql.api.YQLQueryResult) is implemented by both (org.sgx.yuigwt.yui.yql.api.desc.DescResult) and (org.sgx.yuigwt.yui.yql.api.wheather.forecast.WheatherForecastResult)

Thanks in advance.

Paul Stockley

unread,
Sep 6, 2012, 2:54:13 PM9/6/12
to google-we...@googlegroups.com
It's because they don't support polymorphism with overlay types. The same reason all methods are final and cannot be overridden in sub classes of a JSO.

Alain Ekambi

unread,
Sep 6, 2012, 4:04:21 PM9/6/12
to google-we...@googlegroups.com
We hit the problem while creating  our libraries.

Extending JavaScriptObject directly is not good because it restricts what your possibilities.
So  we used composition instead, giving us more power.

So instead of 

public class MyClass extends JavaScriptObject{
    protected MyClass(){
}
}

maybe you should consider something like 

public class MyClass{
    protected JavaScriptObject nativePeer;

    public MyClass(){
              nativePeer =  createNativeJsoObject();
   }
}
The the public API of MyClass will delegate to the JSO.
this will give you a bit more work but the API will me more flexible and your users will thank you :).

Cheers,

Alain



2012/9/6 Sebastián Gurin <sebast...@gmail.com>

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To view this discussion on the web visit https://groups.google.com/d/msg/google-web-toolkit/-/bVE-agIAe-kJ.
To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.

Thomas Broyer

unread,
Sep 6, 2012, 5:25:34 PM9/6/12
to google-we...@googlegroups.com


On Thursday, September 6, 2012 10:05:02 PM UTC+2, nino wrote:
We hit the problem while creating  our libraries.

Extending JavaScriptObject directly is not good because it restricts what your possibilities.
So  we used composition instead, giving us more power.

So instead of 

public class MyClass extends JavaScriptObject{
    protected MyClass(){
}
}

maybe you should consider something like 

public class MyClass{
    protected JavaScriptObject nativePeer;

    public MyClass(){
              nativePeer =  createNativeJsoObject();
   }
}
The the public API of MyClass will delegate to the JSO.
this will give you a bit more work but the API will me more flexible and your users will thank you :).


I once worked around this limitation by providing methods that simply cast the object into another JSO type.
The "native" FileStream implements the IDataInput and IDataOutput interfaces (in ActionScript, which translates to "having all the same methods" in JavaScript), the FileStream cannot implement IDataInput / IDataOutput interfaces (the problem we're talking about), and in Java I cannot use multiple inheritance either. Solution: FileStream has a forInput() method that simply cast()s it to a IDataInput (a JSO type), and similarly for IDataOutput with a forOutput() method.
In other cases, the methods could be called asXxx() (as in "see this object as an Xxx")

Sebastián Gurin

unread,
Sep 7, 2012, 11:45:44 AM9/7/12
to google-we...@googlegroups.com
Thanks Paul, Nino and Thomas

Paul: yes I suppose that too, but interfaces do not implement methods, so I thought it is strange.

Nino: I do not want to make object wrapping as you suggested because I want my library user's to use the overlay types directly for a zero-overhead API. Your approach however would make this kind of Java API much more confortable to Java users.

Thomas, thanks. Yes I'm using .cast() a lot, it is much more confortable than java casting. Also I have designed this YUI java API to be the most similar to the native javascript API. So code using mine YUIGWT will look strange to java programmers, for example, a js literal object definition :

in javascrpt:

var p = {name: "seba", age: 28}

in java:
Person p = Person.create().name("seba").age(28);

Alain Ekambi

unread,
Sep 7, 2012, 11:53:54 AM9/7/12
to google-we...@googlegroups.com
" Your approach however would make this kind of Java API much more confortable to Java users "

Is nt it why you are wrapping YUI in the first place ? To make it confortable for Java users ? 


2012/9/7 Sebastián Gurin <sebast...@gmail.com>
--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.

Chris Price

unread,
Sep 7, 2012, 12:05:14 PM9/7/12
to google-we...@googlegroups.com
Sebastián: You may already be aware of this, but when I first looked
into this problem it was a subtlety I had overlooked.

If you have -

interface A { void a();}
interface B extends A { void b(); }
interface C extends A { void c(); }

You can't have -

final class BImpl implements B {
void a() { ... }
void b() { ... }
}
final class CImpl implements C {
void a() { ... }
void c() { ... }
}

Because as has been pointed out "a" would be implemented twice.
However, you can have -

final abstract class AImpl implements A {
void a() { ... }
}
final abstract class BImpl extends A implements B {
void b() { ... }
}
final abstract class CImpl extends A implements C {
void c() { ... }
}

Because in this case "a" is only implemented once.

It may not help but when I was wrapping a third-party lib, I found the
above pattern worked almost everywhere.

Chris

Sebastián Gurin

unread,
Sep 8, 2012, 12:49:10 PM9/8/12
to google-we...@googlegroups.com
Chris: thank you very much: It didn't occured that to me and just tried and worked fine! Will use this pattern, thanks again. !
>> google-web-toolkit+unsub...@googlegroups.com.
>> For more options, visit this group at
>> http://groups.google.com/group/google-web-toolkit?hl=en.
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "Google Web Toolkit" group.
> To post to this group, send email to google-we...@googlegroups.com.
> To unsubscribe from this group, send email to
> google-web-toolkit+unsub...@googlegroups.com.

Sebastián Gurin

unread,
Sep 8, 2012, 1:00:00 PM9/8/12
to google-we...@googlegroups.com
Nino: mmm that depends. In my case the first thing I want is to provide Java and YUI users the possibility of using these two technologies together. Secondary, I want 2 things: zero-overhead API and an easy learning curve for YUI js users (so If you know Javascript YUI to be trivial to learn my YUI java API).

These last two items, lead me to write a Java API that is almost the same as the YUI Javascript API with the less Java sugar or Java helper classes I can. Just learn a few rules on how to "do JavaScript in Java code" and just use the Java API like you were using the js api. For example, compare these two equivalent js and java codes:

YUI Javascript:

YUI().use('button', function (Y) {
       
var button1 = new Y.Button({
          label
: 'a simple button'
       
}).render(parent);
        button1
.on("click", function(e){
                alert
("clicked at x = "+e.clientX);
       
})
});

Java YUI Equivalent in YUIGWT:

YUI.Use(new String[]{"button"}, new YUICallback() {
       
@Override
       
public void ready(YuiContext Y) {
               
Widget button1 = Y.newButton(
                       
ButtonConfig.create().label("a simple button")
               
).render(parent);      
                button1
.on("click", new NodeEventCallback() {                  
                       
@Override
                       
public void call(YuiEvent e) {
                               
Window.alert("button pressed at x  ="+e.clientX());
                       
}
               
});
               
       
}
});

hehe, a little weird to see for regular java users, but easy to understand to YUI and Java users.  Checkout an example gallery with java sources online at http://cancerbero.mbarreneche.com/yuigwt/gallery/ and some of my thoughts about this at http://code.google.com/p/yuigwt/wiki/YUIJavaApi . One of the god things I discovered for this approach is that Java API writing can me very mechanich, and I can take advance of eclipse java code templates for agile writing java YUI code.

Regards.

Alain Ekambi

unread,
Sep 10, 2012, 4:04:53 PM9/10/12
to google-we...@googlegroups.com
The main Question is do you want YUI users to use Java or do you want  to bring Java Devs to YUI ? 
I think you will get more traction by choosing the latter.

While a zero overhead API gives you the ability to  easely write YUI code in java soon you will get users request  like "Why cant i extends class X to add my own functions". Overlay types dont give you.

We had this problems while implementing our libraries. We started first with 1:1 match of the JS API. Until our users start complaining about the API not beeing extensible. What you would expect  when using an OO language like Java. 


YUI.Use(new String[]{"button"}, new YUICallback() {
        @Override
        public void ready(YuiContext Y) {
                Widget button1 = Y.newButton(
                        ButtonConfig.create().label("a simple button")
                ).render(parent);      
                button1.on("click", new NodeEventCallback() {                  
                        @Override
                        public void call(YuiEvent e) {
                                Window.alert("button pressed at x  ="+e.clientX());
                        }
                });
               
        }
});


That looks pretty cool. Now what if i want to extend Button  and override some methods ?




2012/9/8 Sebastián Gurin <sebast...@gmail.com>

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.

Sebastián Gurin

unread,
Sep 11, 2012, 12:48:11 AM9/11/12
to google-we...@googlegroups.com
Nino; I very like your thoughts and I agree with them. My reply between lines:

On Monday, September 10, 2012 5:05:25 PM UTC-3, nino wrote:
The main Question is do you want YUI users to use Java or do you want  to bring Java Devs to YUI ? 
I think you will get more traction by choosing the latter.


I also thought of that. I started learning how to port JavaScript libraries to GWT  with my project http://code.google.com/p/raphael4gwt/ , a vector drawing library. As such, performance was a requirement, and then a Java API using  GWT overlays directly was a requirement. But now for YUIGWT I wonder if that is true. Some notes:

1) overlay types CAN be inherited, but I agre that is very unconfortable for end GWT/Java users to do this... this is a very important  "issue" in my project I think...
2) I very liked your question: "do you want YUI users to use Java or do you want  to bring Java Devs to YUI ? " and it is making me reflect a lot. thanks.
 
While a zero overhead API gives you the ability to  easely write YUI code in java soon you will get users request  like "Why cant i extends class X to add my own functions". Overlay types dont give you.

We had this problems while implementing our libraries. We started first with 1:1 match of the JS API. Until our users start complaining about the API not beeing extensible. What you would expect  when using an OO language like Java. 

Well, but tell me, do you write a second Java API, with real java classes that wrapp the Js objects ? and if so, do you use your previous 1:1 Java API for writing the this second more-java-confortable API?  (I sould do that) and if so, do you use some Java code generator tool for artificial create the second Java API form the first 1:1 - overlays Java API ? can this be mechanized at all?

I'm questioning my self these kind of things for my project YUIGWT. YUI has a very big API, and unlike other libraries it contains utils for doing a more structured - object oriented javascript like classes, inheritance, plugins, attributes, events, etc. All artificially and fully extensible from javascript. The big desicion I have to make is this: "the objective of YUIGWT is to bring the YUI public concrete utilities to the GWT user, like a datatable, a button, etc ". But not to support those utilities enhancing the Javascript language.


.... code....

That looks pretty cool. Now what if i want to extend Button  and override some methods ?




This is the perfect example, thank you!

Currently in my YUIGWT project (very new project) I do not contemplate that. What I'm thinking can be a perfect solution for me is : to create a second Button class, that wraps all current Button methods, as you suggested in your first post. The user could override some methods, and it is his responsability to call super.(). In the constructor, they must pass me the Y object that is responsible for instantiate the "real - native" Button .
 
Well, a pleasure to read you, if you have any other suggestions or tips about this subject are most welcome.

Alain Ekambi

unread,
Sep 11, 2012, 6:24:26 AM9/11/12
to google-we...@googlegroups.com
Answer below in Bold.

Cheers

2012/9/11 Sebastián Gurin <sebast...@gmail.com>

Nino; I very like your thoughts and I agree with them. My reply between lines:

On Monday, September 10, 2012 5:05:25 PM UTC-3, nino wrote:
The main Question is do you want YUI users to use Java or do you want  to bring Java Devs to YUI ? 
I think you will get more traction by choosing the latter.


I also thought of that. I started learning how to port JavaScript libraries to GWT  with my project http://code.google.com/p/raphael4gwt/ , a vector drawing library. As such, performance was a requirement, and then a Java API using  GWT overlays directly was a requirement. But now for YUIGWT I wonder if that is true. Some notes:


        Yeah overlay type can be inherited but there is not much u can do with that.Plus the methods beeing all finals one cant override them. Not really flexible imho

1) overlay types CAN be inherited, but I agre that is very unconfortable for end GWT/Java users to do this... this is a very important  "issue" in my project I think...
2) I very liked your question: "do you want YUI users to use Java or do you want  to bring Java Devs to YUI ? " and it is making me reflect a lot. thanks.
 
While a zero overhead API gives you the ability to  easely write YUI code in java soon you will get users request  like "Why cant i extends class X to add my own functions". Overlay types dont give you.

We had this problems while implementing our libraries. We started first with 1:1 match of the JS API. Until our users start complaining about the API not beeing extensible. What you would expect  when using an OO language like Java. 

Well, but tell me, do you write a second Java API, with real java classes that wrapp the Js objects ? and if so, do you use your previous 1:1 Java API for writing the this second more-java-confortable API?  (I sould do that) and if so, do you use some Java code generator tool for artificial create the second Java API form the first 1:1 - overlays Java API ? can this be mechanized at all?

I'm questioning my self these kind of things for my project YUIGWT. YUI has a very big API, and unlike other libraries it contains utils for doing a more structured - object oriented javascript like classes, inheritance, plugins, attributes, events, etc. All artificially and fully extensible from javascript. The big desicion I have to make is this: "the objective of YUIGWT is to bring the YUI public concrete utilities to the GWT user, like a datatable, a button, etc ". But not to support those utilities enhancing the Javascript language.


We dont use generator for our APIs. We go the insane way to look at each methods in the APIs we try to wrap! This is a lot of work but it gives us the possibility to optimize/enhendce some stuff. And sometime leave some stuff out that dont make sence for a Java Developer. Plus you come to learn the JS library which is not bad (At my day to day work i dont use GWT but  EXTJS. So Wrapping ExtJS helped me understand  that library better, and hate it even more loooool). 
 
 Concerning building the objects. Like i said before we basically have a real Java Object wrapping a JSO. And we are just delegating to the native JSO. You can have a look at our Java API for Sencha Touch (http://emitrom.com/touch4j) to see it in action.
 
 If you have any question feel free to ping me.

 


.... code....

That looks pretty cool. Now what if i want to extend Button  and override some methods ?




This is the perfect example, thank you!

Currently in my YUIGWT project (very new project) I do not contemplate that. What I'm thinking can be a perfect solution for me is : to create a second Button class, that wraps all current Button methods, as you suggested in your first post. The user could override some methods, and it is his responsability to call super.(). In the constructor, they must pass me the Y object that is responsible for instantiate the "real - native" Button .
 
Well, a pleasure to read you, if you have any other suggestions or tips about this subject are most welcome.

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.

Sebastián Gurin

unread,
Sep 13, 2012, 1:53:43 PM9/13/12
to google-we...@googlegroups.com
Hi nino, i'm making a second Java API for my yuigwt project, on top of my JSO based Java API, wrapping JSO objects and delegating methods to it. I have a couple of questions for you about this. I'm not sure, perhaps the best is to create another thread for this questions, but here they go:

I have a rich class hierarchy for example, ClassC extends ClassB extends ClassA

Now for ClassA I'm writing:

public class ClassA {
protected JSOClassA _wrapped;
}

The problem is that in ClassB and ClassC I must cast _wrapped to JSOClassB and JSOClassC for implementing method delegation, so I ended with something like

public class ClassB extends ClassA {
  protected JSOClassB _wrappedClassB() {
    return _wrapped.cast();
  }
}
public class ClassC extends ClassB {
  protected JSOClassC _wrappedClassC() {
    return _wrapped.cast();
  }
}

can you think of another more simpler way to solve this ?

And the other question is, how or where should I initialize the _wrapped field ? at constructor ?

Regards and thanks in advance.
To unsubscribe from this group, send email to google-web-toolkit+unsub...@googlegroups.com.

Alain Ekambi

unread,
Sep 13, 2012, 4:50:56 PM9/13/12
to google-we...@googlegroups.com
In one our our project we have a base which goes something like 

public class ProxyObject {

    protected JavaScriptObject jsObj;

    protected ProxyObject() {

    }

}


The we do 

public class View extends ProxyObject {

    public View() {

        createPeer();

    }


    View(JavaScriptObject obj) {

        jsObj = obj;

    }


    private List<View> children = new ArrayList<View>();

    @Override

    public native Point getAnchorPoint() /*-{

var jso = this.@com.emitrom.gwt4.ti.mobile.client.core.ProxyObject::getJsObj()();

var obj = jso.anchorPoint;

var toReturn = @com.emitrom.gwt4.ti.mobile.client.ui.Point::new(Lcom/google/gwt/core/client/JavaScriptObject;)(obj);

return toReturn;

    }-*/;

}

We create the wrapped JSO in the  constructor and delegation is done using JSNI which save the need of the explicit cast.

To call methods on the wrapped JSO we use JSNI


Hope this could help



2012/9/13 Sebastián Gurin <sebast...@gmail.com>
To view this discussion on the web visit https://groups.google.com/d/msg/google-web-toolkit/-/pAMwpwmGowMJ.

To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.

Sebastián Gurin

unread,
Sep 14, 2012, 8:42:50 PM9/14/12
to google-we...@googlegroups.com
nino: thank you very much! I have my two question responded in your code snippet. My last question: I notice you perform most of the job in javascript / jsni, nice. How is your experience using  eclipse+google Java code refactoring tools ? in particular, method and class renames ? Thank you again.-
2012/9/13 Sebastián Gurin <sebast...@gmail.com>

To unsubscribe from this group, send email to google-web-toolkit+unsubscribe@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.

Alain Ekambi

unread,
Sep 18, 2012, 7:27:27 AM9/18/12
to google-we...@googlegroups.com
The GPE provides some help with JSNI.
But at some point you will have to write some JS by hand with no autocompletion :)



2012/9/15 Sebastián Gurin <sebast...@gmail.com>
To view this discussion on the web visit https://groups.google.com/d/msg/google-web-toolkit/-/MNdypItk-VUJ.

To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages