序列化生成的类时出现问题
我在我的应用程序中使用 GWT 2.3。我创建了一个生成器来生成类并向它们添加行为。
我的生成器工作正常,我可以在客户端上调用 GWT.create(MyClass.class) 。这确实返回具有正确字段/方法的 MyClassImpl 对象。当我尝试序列化对象以将其发送回服务器时,出现 SerializationException。
调试后,RPC 生成器似乎找不到 MyClassImpl 的类定义。
有办法解决这个问题吗?我假设我自己的生成器生成的类定义可用于 RPC 生成器,除非该生成器在我的生成器之前运行?
预先感谢您的帮助。
Farid
您好,谢谢您的快速回答,
我生成的类如下: - 它有一个公共的无参数构造函数 - 它实现了 Serialized (并且确保我尝试了 Serialized 和 IsSerializable 的所有组合) - 是在共享包中生成的(当我调用 GWT.create() 时由我的生成器生成) - 它的所有属性都是“简单”(原始或字符串)
它看起来像这样(其中 TestClass 是我的生成器标记接口):
package com.test.shared;
import com.test.shared.TestClass;
public class TestClass_Impl implements TestClass, Serializable {
private String testString = "TestString";
public TestClass_Impl() {}
public String getTestString() {
return testString;
}
}
我可以在客户端上调用 GWT.create(TestClass.class)。我得到了 TestClass_Impl 的一个实例,但是当我尝试通过 GWT RPC 调用将其通过网络发送到服务器时,我得到一个异常:
com.test.server.TestServiceServlet-29927840: An IncompatibleRemoteServiceException was thrown while processing this call.
com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: java.lang.ClassNotFoundException: com.test.shared.TestClass_Impl
at com.google.gwt.user.server.rpc.RPC.decodeRequest(RPC.java:315)
at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:206)
at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:248)
at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62)
....
Caused by: com.google.gwt.user.client.rpc.SerializationException: java.lang.ClassNotFoundException: com.test.shared.TestClass_Impl
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deserialize(ServerSerializationStreamReader.java:573)
at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamReader.readObject(AbstractSerializationStreamReader.java:119)
...
Caused by: java.lang.ClassNotFoundException: com.test.shared.TestClass_Impl
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:366)
at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:337)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deserialize(ServerSerializationStreamReader.java:543)
看起来 GWT RPC 在尝试实例化它时无法在服务器上找到类 TestClass_Impl 。
有什么想法吗? 谢谢,
法里德,
谢谢朱西奥。这正是发生的事情。 GWT 似乎生成 java 源代码只是为了将其交叉编译为 javascript,然后丢弃生成的 java 文件。有一个编译器选项可将生成的 java 代码保存在特定文件夹中,但生成的 .java 文件不会随构建一起编译。
尽管非常复杂和笨拙,但可以更改构建过程以获取由我的生成器生成的源文件并将它们包含在构建路径中,以便它们可以在运行时编译并可用。
相反,我创建了一个单独的类来生成我的 java 源代码。生成器使用该类来生成要由 GWT 交叉编译的 java 源代码。然后,我的应用程序使用同一个类来动态生成这些 java 类并将其加载到 VM 中。然后它们在运行时可用,并且一切似乎都工作正常。
再次感谢您的帮助,如果有人需要有关此解决方法的更多信息,我很乐意将其发送给他们。
I am using GWT 2.3 for my application. I created a generator to generate classes and add behaviour to them.
My generator works fine and I can call GWT.create(MyClass.class) on the client. This does return a MyClassImpl object with the correct fields/methods. When I try to serialise the object to send it back to the server I have a SerializationException.
After debugging it appears that the RPC generator cannot find the class definition for MyClassImpl.
Is there a way of fixing this? I assumed the class definition generated by my own generator would be available to the RPC generator unless this one is run before my generator?
Thank you in advance for your help.
Farid
Hello and thank you for you quick answer,
My generated class is as follows:
- it has a public no arg constructor
- it implements Serializable (and to be sure I tried all combinations of Serializable and IsSerializable)
- is is generated (by my generator when I call GWT.create() ) in a shared package
- All its attributes are "Simple" (primitive or String)
It looks like this (where TestClass is my marker interface for the generator):
package com.test.shared;
import com.test.shared.TestClass;
public class TestClass_Impl implements TestClass, Serializable {
private String testString = "TestString";
public TestClass_Impl() {}
public String getTestString() {
return testString;
}
}
I can call GWT.create(TestClass.class) on the client. I get a instance of TestClass_Impl but as soon as I try to send it over the network to teh server through a GWT RPC call I get an exception:
com.test.server.TestServiceServlet-29927840: An IncompatibleRemoteServiceException was thrown while processing this call.
com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: java.lang.ClassNotFoundException: com.test.shared.TestClass_Impl
at com.google.gwt.user.server.rpc.RPC.decodeRequest(RPC.java:315)
at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:206)
at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:248)
at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62)
....
Caused by: com.google.gwt.user.client.rpc.SerializationException: java.lang.ClassNotFoundException: com.test.shared.TestClass_Impl
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deserialize(ServerSerializationStreamReader.java:573)
at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamReader.readObject(AbstractSerializationStreamReader.java:119)
...
Caused by: java.lang.ClassNotFoundException: com.test.shared.TestClass_Impl
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:366)
at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:337)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deserialize(ServerSerializationStreamReader.java:543)
It looks like GWT RPC cannot find the class TestClass_Impl on the server when it tries to instantiate it.
Any idea?
Thanks,
farid
Thank you Jusio. That is exactly what was going on. GWT seems to generate the java source only for the purpose of cross-compiling it into javascript and then discards the generated java files. There is a compiler option to keep the generated java code in a specific folder but the resulting .java file is not compiled with the build.
It is possible, although very convoluted and clumsy, to change the build process to pick up source files generated by my generator and include them in the build path so they can be compiled and available at runtime.
I have instead created a separate class to generate my java source code. This class is used by the generator to generate the java source to be cross-compiled by GWT. The same class is then used by my application to dynamically generate and load these java classes into the VM. They are then available at runtime and all seems to be working fine.
Thank you again for your help and if anyone needs more information about this workaround I will be happy to send it to them.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为问题是,生成的类应该存在于客户端和服务器上。这就是您收到此错误的原因。据我所知,生成器不能在服务器端工作。可能有一种方法可以让它们发挥作用,但我不知道。可能的解决方案 - 使用 -gen 选项启动编译器,将生成的类保存到磁盘,将它们编译为 *.class 并复制到服务器类路径。或者不要使用 GWT-RPC =)
I believe the problem is, that generated class should exist on both client and server. That's why you get this error. As far as i know generators don't work on the server side. May be there is a way to make them work, but I don't know about it. Possible solution - launch compiler with -gen option to save generated classes to the disk, compile them to *.class and copy to the server class path. Or don't use GWT-RPC =)
确保您的生成器使生成的类
IsSerialized
(即实现IsSerializable 接口)。Ensure that your generator makes the generated class
IsSerializable
(i.e., implements the IsSerializable interface).