GWT序列化破碎?

时间:2013-11-22 03:33:59

标签: gwt serialization gwt-rpc

我有一个相当简单的案例。我还简化了名称以便于阅读(见下文)。

我有一个枚举和一个用户定义的类,它使用这个枚举,以及一​​个字符串。

根据GWT:

  • 枚举应该是可序列化的。
  • 用户定义的类应该是可序列化的,因为:
  • 它直接实现Serializable。
  • 这是非最终的,非瞬态实例字段是可序列化的:
  • 枚举是可序列化的。
  • String是可序列化的。
  • 它有一个默认(零参数)构造函数。

尽管符合这些规则,但尝试使用这些类会导致以下错误:

SEVERE: Exception while dispatching incoming RPC call com.google.gwt.user.client.rpc.SerializationException: Type 'com.company.product.Bar 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 = com.company.product.Bar @4c19cc84

简单的案例。

GWT扼杀了它。

它坏了吗?

类型是可序列化的,如果满足下列条件之一,则可以在服务接口中使用:

  • 类型是原始的,例如char,byte,short,int,long,boolean,float或double。
  • 键入String,Date或基本包装器的实例,如Character,Byte,Short,Integer,Long,Boolean,Float或Double。
  • 类型是枚举。枚举常量仅作为名称序列化;没有任何字段值被序列化。
  • 类型是可序列化类型的数组(包括其他可序列化数组)。
  • 该类型是可序列化的用户定义类。
  • 该类型至少有一个可序列化的子类。
  • 该类型具有自定义字段序列化程序

如果满足以下所有条件,则用户定义的类是可序列化的:

  1. 可分配给IsSerializable或Serializable,因为它直接实现其中一个接口,或者因为它派生自一个超类
  2. 所有非最终的非瞬态实例字段本身都是可序列化的,
  3. 从GWT 1.5开始,它必须有一个默认(零参数)构造函数(带有任何访问修饰符)或根本没有构造函数。
  4. Foo.java

    public enum Foo {
     A, B, C;
    }
    

    Bar.java

    public class Bar implements Serializable {
    
     private static final long serialVersionUID = 604131643709466885L;
     private Foo foo;
     private String S;
    
     public Bar() {
     }
    
     public Foo getFoo() {
         return foo;
     }
     public void setFoo(Foo foo) {
         this.foo = foo;
     }
     public String getS() {
         return S;
     }
     public void setS(String S) {
         this.S = S;
     }
    }
    

2 个答案:

答案 0 :(得分:1)

您的课程在客户端和服务器端是否可用?

包名'com.company.product.Bar'表示该类可能不在正确的包中。通常你在GWT中有这样的包结构:

+- root package
   !
   +- client
   !
   +- server
   !
   +- shared
   !  ! 
   !  +- YourDTO.java
   !
   +- YourModuleDescriptor.gwt.xml

您的DTO应位于共享包中。

答案 1 :(得分:0)

  

类型'com.company.product.Bar未包含在可通过此SerializationPolicy序列化的类型集中无法加载其Class对象。出于安全考虑,此类型不会被序列化。

由于您已经非常清楚地遵循了它提到的特定规则,因此另一半 - 序列化策略本身可能出错。有两种情况可能会发生这种情况 - 服务器上没有策略(或者是过时的,实际上是相同的),或者策略不包括该类型,因为它无法通过RPC(不在客户端源路径上,显式列入黑名单,不能分配给其中一种预期类型 - java.lang.Object是作弊)。

如果文件完全丢失或过期,服务器将不会发送或接收它正在查看的类型。如果过时,客户端和服务器对可以通过网络传输的类型有不同的认识。每个rpc调用都包含对该调用使用的策略文件的引用 - 客户端和服务器需要保持同步。另一方面,如果由于RPC生成器确定通过线路发送类型不合法,则无法发送对象,则需要更改rpc接口(或引用类型)以正确引用它。

除此之外,还需要更多详细信息 - 您的RPC接口,服务器上的任何其他日志消息是服务器上存在的*.gwt.rpc文件?