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
-~----------~----~----~----~------~----~------~--~---