I learned from a good Google engineer on the GWT bug tracking site
(http://code.google.com/p/google-web-toolkit/issues/detail?id=3018)
that GWT is working as designed and that what I was doing was not
supported.  Instead of constructing MyObject in Java space, I should
be constructing the object in JavaScript space.  The values of
MyObject can be set by the Sender and read by the Receiver using
JavaScript overlay types (http://code.google.com/docreader/#p=google-
web-toolkit-doc-1-5&s=google-web-toolkit-
doc-1-5&t=DevGuideOverlayTypes).  Here is how the above test case
would be modified to do so:

-------------------------------------
The MyObject class is an overlay type:

package test.frames.client;

import com.google.gwt.core.client.JavaScriptObject;

class MyObject extends JavaScriptObject {
    protected MyObject() {}

    public final native int getNumber() /*-{
        return this.number;
     }-*/;

    public final native void setNumber(int number) /*-{
        this.number = number;
     }-*/;
}

-------------------------------------
The Sender class constructs an object in JavaScript space, brings it
back into Java space, and using the MyObject overlay type, sets the
values on it:

package test.frames.client;

import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class Sender extends VerticalPanel {

    private int messageNumber = 0;

    public Sender() {
        Button sendButton = new Button("Send");
        sendButton.addClickListener(new ClickListener() {
            public void onClick(Widget arg0) {
                send();
            }
        });
        add(sendButton);
    }

    private void send() {
        MyObject myObject = createMyObject();
        myObject.setNumber(messageNumber++);
        sendNative(myObject);
    }

    private native MyObject createMyObject() /*-{
        return new Object();
    }-*/;

    private native void sendNative(MyObject myObject) /*-{
        if (top.receive != null) {
            top.receive(myObject);
        }
    }-*/;
}

-------------------------------------

All other classes (and html) in the test case remain the same.


On Oct 8, 8:06 am, Wyatt <[EMAIL PROTECTED]> wrote:
> My web page has a frameset and I'm getting a ClassCastException when
> passing a Java object from a GWT widget in one from to a GWT widget in
> another frame via JSNI.
>
> Here is what I do:
> 1. I create two widgets (called "Sender" and "Receiver"), each in a
> separate frame in the frameset.
> 2. The Receiver widget creates a native javascript function (called
> "receive") and attaches it to "top".
> 3. The Sender method instantiates a MyObject object [MyObject is a
> dumb little class that holds an int]
> 4. The Sender passes the MyObject object to the native receive
> function via JSNI
> 5. The receive function then passes the MyObject object to the
> Receiver widget
> 6. The Receiver widget prints out a message saying it's received the
> object
>
> When I try this I get this exception:
> java.lang.ClassCastException
>         at java.lang.Class.cast(Class.java:2951)
>         at com.google.gwt.dev.shell.JsValueGlue.get(JsValueGlue.java:
> 122)
>         at
> com.google.gwt.dev.shell.ie.SwtOleGlue.convertVariantsToObjects(SwtOleGlue.java:
> 57)
>         at
> com.google.gwt.dev.shell.ie.IDispatchImpl.callMethod(IDispatchImpl.java:
> 119)
>         at
> com.google.gwt.dev.shell.ie.IDispatchProxy.invoke(IDispatchProxy.java:
> 155)
>         at
> com.google.gwt.dev.shell.ie.IDispatchImpl.Invoke(IDispatchImpl.java:
> 294)
>         at
> com.google.gwt.dev.shell.ie.IDispatchImpl.method6(IDispatchImpl.java:
> 194)
>         at
> org.eclipse.swt.internal.ole.win32.COMObject.callback6(COMObject.java:
> 117)
>         at org.eclipse.swt.internal.ole.win32.COM.VtblCall(Native
> Method)
>         at
> org.eclipse.swt.internal.ole.win32.IDispatch.Invoke(IDispatch.java:64)
>         at
> org.eclipse.swt.ole.win32.OleAutomation.invoke(OleAutomation.java:493)
>         at
> org.eclipse.swt.ole.win32.OleAutomation.invoke(OleAutomation.java:417)
>         at
> com.google.gwt.dev.shell.ie.ModuleSpaceIE6.doInvokeOnWindow(ModuleSpaceIE6.java:
> 67)
>         at
> com.google.gwt.dev.shell.ie.ModuleSpaceIE6.doInvoke(ModuleSpaceIE6.java:
> 152)
>         at
> com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:
> 447)
>         at
> com.google.gwt.dev.shell.ModuleSpace.invokeNativeVoid(ModuleSpace.java:
> 248)
>         at
> com.google.gwt.dev.shell.JavaScriptHost.invokeNativeVoid(JavaScriptHost.java:
> 107)
>         at test.frames.client.Sender.sendNative(Sender.java)
>         at test.frames.client.Sender.send(Sender.java:24)
>         at test.frames.client.Sender.access$0(Sender.java:22)
>         at test.frames.client.Sender$1.onClick(Sender.java:16)
>
>         ...
>
> Notes:
> 1. This only happens in hosted mode.  In web mode everything works
> fine.
> 2. If I pass a Date or Integer or some other object whose class I
> didn't define, everything works in both hosted mode and web mode.
> 2. When the Sender and Receiver live in the same html body (i.e. not
> in different frames) everything works in both hosted mode and web
> mode.
> 3. I am using GWT 1.5.2.
> 4. This stack trace looks very similar to that 
> inhttp://code.google.com/p/google-web-toolkit/issues/detail?id=2841, but
> from the description it doesn't appear (to me) to be the same issue.
>
> Below are my classes and html pages.  Thanks for you help.
>
> Wyatt
>
> -------------------------------------
> My EntryPoint class creates the appropriate Widget depending on which
> frame it's in:
>
> package test.frames.client;
>
> import com.google.gwt.core.client.EntryPoint;
> import com.google.gwt.user.client.ui.HorizontalPanel;
> import com.google.gwt.user.client.ui.RootPanel;
>
> public class FramesEntryPoint implements EntryPoint {
>
>     public void onModuleLoad() {
>         if (RootPanel.get("LeftFrame") != null) {
>             // This executes on the left side of Frames.html:
>             Sender sender = new Sender();
>             RootPanel.get().add(sender);
>         } else if (RootPanel.get("RightFrame") != null) {
>             // This executes on the right side of Frames.html:
>             Receiver receiver = new Receiver();
>             RootPanel.get().add(receiver);
>         } else if (RootPanel.get("Both") != null) {
>             // This only executes if you hit Both.html instead of
> Frames.html:
>             Sender sender = new Sender();
>             Receiver receiver = new Receiver();
>             HorizontalPanel hp = new HorizontalPanel();
>             hp.add(sender);
>             hp.add(receiver);
>             RootPanel.get().add(hp);
>         }
>     }
> -------------------------------------
> This is the object that is passed from one frame to another:
>
> package test.frames.client;
>
> public class MyObject {
>     private int number;
>
>     public MyObject(int number) {
>         this.number = number;
>     }
>
>     public int getNumber() {
>         return number;
>     }}
>
> -------------------------------------
> The Sender creates a MyObject and sends it to the other frame:
>
> package test.frames.client;
>
> import com.google.gwt.user.client.ui.Button;
> import com.google.gwt.user.client.ui.ClickListener;
> import com.google.gwt.user.client.ui.VerticalPanel;
> import com.google.gwt.user.client.ui.Widget;
>
> public class Sender extends VerticalPanel {
>
>     private int messageNumber = 0;
>
>     public Sender() {
>         Button sendButton = new Button("Send");
>         sendButton.addClickListener(new ClickListener() {
>             public void onClick(Widget arg0) {
>                 send();
>             }
>         });
>         add(sendButton);
>     }
>
>     private void send() {
>         MyObject myObject = new MyObject(messageNumber++);
>         sendNative(myObject);
>     }
>
>     private native void sendNative(MyObject myObject) /*-{
>         if (top.receive != null) {
>             top.receive(myObject);
>         }
>     }-*/;}
>
> -------------------------------------
> The Receiver lives in the second frame and receives the MyObject:
>
> package test.frames.client;
>
> import com.google.gwt.user.client.ui.Label;
> import com.google.gwt.user.client.ui.SimplePanel;
>
> class Receiver extends SimplePanel {
>
>     public Receiver() {
>         registerNativeFunction(this);
>     }
>
>     private native void registerNativeFunction(Receiver receiver) /*-{
>         top.receive = function (myObject) {
>             [EMAIL PROTECTED]::display(Ltest/
> frames/client/MyObject;)(myObject);
>         };
>     }-*/;
>
>     private void display(MyObject myObject) {
>         setWidget(new Label("Message: "+myObject.getNumber()));
>     }}
>
> -------------------------------------
> Frames.html: this is what you point the GWT shell at:
>
> <html>
>   <head>
>     <title>GwtFrames</title>
>     <meta http-equiv="Content-Type" content="text/html;
> charset=UTF-8">
>   </head>
> <frameset cols="50%,50%">
>     <frame id="TheLeftFrame" src="Left.html"></frame>
>     <frame id="TheRightFrame" src="Right.html"></frame>
> </frameset>
> </html>
> -------------------------------------
> Left.html:
>
> <html>
>     <head>
>         <meta name='gwt:module'
> content='test.frames.FramesTest=test.frames.FramesTest'>
>     </head>
>     <body>
>         <script language="javascript" src="test.frames.FramesTest/
> test.frames.FramesTest.nocache.js"></script>
>         <div id="LeftFrame"/>
>     </body>
> </html>
> -------------------------------------
> Right.html:
>
> <html>
>     <head>
>         <meta name='gwt:module'
> content='test.frames.FramesTest=test.frames.FramesTest'>
>     </head>
>     <body>
>         <script language="javascript" src="test.frames.FramesTest/
> test.frames.FramesTest.nocache.js"></script>
>         <div id="RightFrame"/>
>     </body>
> </html>
> -------------------------------------
> Both.html: if you point the GWT shell at this (instead of at
> Frames.html), both Sender and Receiver live in the same html body and
> you don't see the error:
>
> <html>
>     <head>
>         <meta name='gwt:module'
> content='org.gwtsandbox.frames.Frames=org.gwtsandbox.frames.Frames'>
>     </head>
>     <body>
>         <script language="javascript"
> src="org.gwtsandbox.frames.Frames/
> org.gwtsandbox.frames.Frames.nocache.js"></script>
>         <div id="Both"/>
>     </body>
> </html>
> -------------------------------------
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Google Web Toolkit" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/Google-Web-Toolkit?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to