GWT - RPC序列化异常

17

我已经有一段时间没有使用GWT了,但是我需要快速完成一些小任务。我配置好了一切,现在我需要一个RPC,但是它失败了。

这个RPC会给我一个ArrayList,Vacancy位于#projectname#.client.model中。 调用是在#projectname#.client.model中进行的。
我的服务接口在#project#name.client.Service中定义。
最后,调用当然要发送到#projectname#.server。
Vacancy实现了IsSerializable。我从运行我的RPC中获得的异常如下:

Starting Jetty on port 8888
[WARN] Exception while dispatching incoming RPC call
com.google.gwt.user.client.rpc.SerializationException: Type 'firsteight.client.model.Vacancy' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.: instance = firsteight.client.model.Vacancy@15fdd2f
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:619)
    at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:126)
    at com.google.gwt.user.client.rpc.core.java.util.Collection_CustomFieldSerializerBase.serialize(Collection_CustomFieldSerializerBase.java:44)
    at com.google.gwt.user.client.rpc.core.java.util.ArrayList_CustomFieldSerializer.serialize(ArrayList_CustomFieldSerializer.java:39)
    at com.google.gwt.user.client.rpc.core.java.util.ArrayList_CustomFieldSerializer.serializeInstance(ArrayList_CustomFieldSerializer.java:51)
    at com.google.gwt.user.client.rpc.core.java.util.ArrayList_CustomFieldSerializer.serializeInstance(ArrayList_CustomFieldSerializer.java:28)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeImpl(ServerSerializationStreamWriter.java:740)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:621)
    at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:126)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter$ValueWriter$8.write(ServerSerializationStreamWriter.java:153)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeValue(ServerSerializationStreamWriter.java:539)
    at com.google.gwt.user.server.rpc.RPC.encodeResponse(RPC.java:616)
    at com.google.gwt.user.server.rpc.RPC.encodeResponseForSuccess(RPC.java:474)
    at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:571)
    at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:208)
    at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:248)
    at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:362)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.handler.RequestLogHandler.handle(RequestLogHandler.java:49)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:324)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
    at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843)
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:647)
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
    at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)

我发起的RPC如下:

void getVacs() {
    try {
        homeService.getVacancies(new AsyncCallback<ArrayList<Vacancy>>() {
            public void onFailure(Throwable caught)
            {
                RootPanel.get("grayblock").add(new HTML("Failed:" + caught.getMessage()));
            }

            public void onSuccess(ArrayList<Vacancy> result)
            {
                RootPanel.get("grayblock").add(new HTML(result.get(0).getTitle()));
            }
        });
    } catch (IllegalArgumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

我以为我已经做了所有必要的事情,使 Vacancy 可序列化,并且将 Vacancy 的 ArrayList 作为 RPC 的返回类型算作具有 Vacancy 作为返回类型..对吗?我做错了什么?

提前感谢!


你确定在你的 Vacancy 类中实现了 com.google.gwt.user.client.rpc.IsSerializable 接口吗? - Jama A.
1
import com.google.gwt.user.client.rpc.IsSerializable;public class Vacancy implements IsSerializable {当然可以。 - Mark Tielemans
6个回答

37
通常情况下,这是由于使用不可序列化的类所导致的,可能是因为您的类没有实现com.google.gwt.user.client.rpc.IsSerializable,或者您忘记添加一个空构造函数。
要传递一个Java bean,您需要满足以下要求(来自GWT网站):
1.它直接实现Java Serializable或GWT IsSerializable接口,或者从实现了这些接口的超类继承而来。
2.它的非final、非transient实例字段本身也是可序列化的。
3.它必须有一个默认的(零参数)构造函数,可以有任何访问修饰符(例如,private Foo(){}将起作用)。
即使您满足这些要求,GWT编译器仍可能会出现以下提示:
“未包含在此SerializationPolicy可以序列化的类型集合中,或其Class对象无法加载。出于安全考虑,此类型将不会被序列化。”
该问题可能有不同的原因。下面是一个完整的检查清单,可用于解决问题:
1.验证类是否具有默认构造函数(无参数)。
2.验证类是否实现了Serializable或IsSerializable,或实现了扩展Serializable的接口,或继承了实现了Serializable的类。
3.验证类是否位于client.*包中。
4.如果类不在client.*包中,请验证其是否在您的GWT xml模块定义中编译。默认情况下,标记已经存在。如果您的类在其他包中,您需要将其添加到xml中。例如,如果您的类在domain.*下,您应该将其添加为。请注意,该类不能属于server包!有关更多详细信息,请参阅GWT页面:http://code.google.com/webtoolkit/doc/latest/DevGuideOrganizingProjects.html#DevGuideModuleXml
5.如果您从另一个GWT项目中包含该类,则必须将其继承到xml模块定义中。例如,如果您的类来自另一个GWT项目,则必须将其添加到您的xml中:类Foo位于包com.dummy.domain中,您需要将其添加到模块定义中。 更多详细信息请参见: http://code.google.com/webtoolkit/doc/latest/DevGuideOrganizingProjects.html#DevGuideInheritingModules
  • 如果您从另一个已发布为jar的GWT项目中包含该类,请验证该jar中还包含源代码,因为GWT会重新编译传递给客户端的类的Java源代码。
  • 注:此内容来源于http://isolasoftware.it/2011/03/22/gwt-serialization-policy-error/,因为该网站当前不可用。如果您想阅读原始文章,请使用上述URL从谷歌搜索并从谷歌网络缓存中阅读。


    1
    我已经包含了以下构造函数:public Vacancy() {}。我从服务器检索到的对象使用参数化构造函数,但我认为这不应该有任何影响..(?) - Mark Tielemans
    你能分享一下实现RemoteService接口和传输对象Vacancy的类吗? - Jama A.
    服务器端实现,目前使用演示数据: http://pastebin.com/f88rMZEJ服务: http://pastebin.com/Yt8piq1m异步: http://pastebin.com/Lbuav4yr - Mark Tielemans
    我不再拥有项目代码,而且过去的粘贴已经过期了。然而,从异常信息来看,我认为我可能忘记将Vacancy类放在共享文件夹中。虽然很难想象,但无论如何该项目现在已经消失了,你的答案可能已经涵盖了正确的解决方案。谢谢! - Mark Tielemans
    我通过向编译器提供“-noincremental”选项使其工作。 - geoji

    8

    这个异常的另一个原因是浏览器端的javascript过时了。我需要强制刷新代码(CTRL + F5),然后这个异常就消失了。


    0

    当我使用子列表时,我也遇到了这个错误:

    return myList.subList(fromIndex, toIndex);
    

    如果你测试 return myList,它能否正常工作? sublist 不应该改变返回类型。 - Mark Tielemans
    myList 没有改变,但我想获取子列表,所以我用 for 循环做了它 (java 7) - paka

    0
    在我的情况下,我的target文件夹中有一些旧的缓存没有被正确更新。我不得不重建项目(Maven->更新项目),然后它才能正常工作。

    0
    首先,请确保已定义了一个空构造函数
    如果没有,您的类将无法序列化...

    如果您有一个空构造函数,请确保您的类(或扩展链中的任何类)实现IsSerializable(或任何其他扩展IsSerialisable的接口)

    如果您的类实现了IsSerialisable,请检查它是否非final...


    0
    如Cipous所述,在我的情况下,我在Pentaho BI Server的服务器输出中遇到了这个异常。简单的硬刷新(CTRL+F5)解决了问题。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接