Closed dankurka closed 9 years ago
This is my stack trace in GWT 1.5.3:
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:25)
at test.frames.client.Sender.access$0(Sender.java:22)
at test.frames.client.Sender$1.onClick(Sender.java:16)
at
com.google.gwt.user.client.ui.ClickListenerCollection.fireClick(ClickListenerCollection.java:34)
at com.google.gwt.user.client.ui.FocusWidget.onBrowserEvent(FocusWidget.java:102)
at com.google.gwt.user.client.DOM.dispatchEventImpl(DOM.java:1308)
at com.google.gwt.user.client.DOM.dispatchEventAndCatch(DOM.java:1287)
at com.google.gwt.user.client.DOM.dispatchEvent(DOM.java:1255)
at sun.reflect.GeneratedMethodAccessor9.invoke(Unknown Source)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
at com.google.gwt.dev.shell.ie.IDispatchImpl.callMethod(IDispatchImpl.java:126)
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.win32.OS.DispatchMessageW(Native Method)
at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:1925)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:2966)
at com.google.gwt.dev.GWTShell.pumpEventLoop(GWTShell.java:720)
at com.google.gwt.dev.GWTShell.run(GWTShell.java:593)
at com.google.gwt.dev.GWTShell.main(GWTShell.java:357)
Reported by wyatt.bertel
on 2008-10-22 21:51:18
This example produces the exception:
-------------------------------------
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) {
receiver.@test.frames.client.Receiver::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>
-------------------------------------
Reported by wyatt.bertel
on 2008-10-22 21:58:38
Additional notes:
1. If the Sender and Receiver live in the same RootPanel (i.e. in the same frame) the
ClassCastException is not thrown in hosted mode.
2. Passing java.util.Dates between frames is safe, so I'd expand my workaround to
advise passing java.lang and java.util objects between frames.
Reported by wyatt.bertel
on 2008-10-22 22:03:56
This use case is explicitly not supported. Two different GWT applications running in
different frames cannot be considered the same app with the same types. The fact
that it works in web mode is purely accidental, and works only because you are using
identical compilations in each frame.
Were you to compile two different apps and run them in different frames, it would be
unlikely to work.
Reported by scottb+legacy@google.com
on 2008-10-22 22:56:38
AsDesigned
Roger that.
Is my workaround supported though? I.e. is it safe to pass java.lang.Integers,
java.util.Dates, etc. from one RootPanel to another? Or is it accidental that that
works as well?
Reported by wyatt.bertel
on 2008-10-23 07:24:33
No, that's accidental as well. It happens to work because in Java, the only way
those classes can be loaded are in the bootstrap JVM classloader, where they are
shared.
The right way to do what you're trying to do is to create plain old JS objects to
share. Check out 1.5's Overlay Types for a way to easily manipulate "POJSOs". :)
Reported by scottb+legacy@google.com
on 2008-10-23 18:22:17
Thank you very much! The JavaScript overlay types did the trick! For posterity's
sake, I updated my original post on the developer forum
(http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/f5816b66dec81b05)
with a working test case.
Reported by wyatt.bertel
on 2008-10-24 10:14:03
Originally reported on Google Code with ID 3018
Reported by
wyatt.bertel
on 2008-10-22 21:49:42