轻微更改后GWT + GXT序列化出错。但为什么?

时间:2013-10-29 13:07:52

标签: gwt gxt

我以为我知道GWT序列化规则,但显然我没有。这个案子很奇怪,我想弄清楚几个小时,仍然没有运气。也许你们,伙计们,可以借给我这个吗?

首先要做的事情是:堆栈跟踪。

...blah blah blah...
Caused by: com.google.gwt.user.client.rpc.SerializationException: Type 'geos.dto.common.client.Market' 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 = null
    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.HashSet_CustomFieldSerializer.serialize(HashSet_CustomFieldSerializer.java:39)
    at com.google.gwt.user.client.rpc.core.java.util.HashSet_CustomFieldSerializer.serializeInstance(HashSet_CustomFieldSerializer.java:51)
    at com.google.gwt.user.client.rpc.core.java.util.HashSet_CustomFieldSerializer.serializeInstance(HashSet_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.extjs.gxt.ui.client.data.RpcMap_CustomFieldSerializer.serialize(RpcMap_CustomFieldSerializer.java:35)
    ... 78 more

所以看来问题出在geos.dto.common.client.Market。让我们看看仍然可以编译的最小值。

package geos.dto.common.client;

public class Market extends RowModel<Integer>  {
    public static final String ID="id";
    public static final String NAME="name";

    public Market() { }
    public Market(int id, String name) { }
    public String getName() { }
    public void setName(String name) { }    
}

真的要么度假,要么就好了。 很多DTO类继承自RowModel,它们正在工作并正确序列化,没有任何问题。但当然我会告诉你。这次是一些GXT的事情。这门课程未经编辑,但仍然相当简单。

package geos.dto.common.client;

import com.extjs.gxt.ui.client.data.BaseModelData;

public class RowModel<I> extends BaseModelData implements IdentifiableModelData<I> {    
    private I identifier;
    private String identifierProperty;

    public RowModel() { }    

    public RowModel(String identifierProperty) {
        this.identifierProperty=identifierProperty;
    }       

    @Override
    public I getIdentifier() {
        return identifier;
    }

    public void setIdentifier(I identifier) {
        this.identifier = identifier;
        if((identifierProperty!=null)&&(!identifierProperty.isEmpty())) {
            set(identifierProperty,identifier);
        }
    }

    public void setIdentifierProperty(String identifierProperty) {
        this.identifierProperty = identifierProperty;
        if(identifier!=null) {
            set(identifierProperty,identifier);
        }
    }

    public String getIdentifierProperty() {
        return identifierProperty;
    }        

    @Override
    public <X> X set(String property, X value) {
        if(property.equals(identifierProperty)&&((identifier==null)||(!getIdentifier().equals(value)))) {
            setIdentifier((I)value);
        }
        return super.set(property, value);
    }            
}

我知道,看起来有些奇怪,但这些标识符非常重要。我删除了toString() - 在这种情况下 - 返回null(因为内部RpcMap为null,并且它为null,因为Market类中没有设置任何值)。最后一段代码,由RowModel实现的接口:

package geos.dto.common.client;

import com.extjs.gxt.ui.client.data.ModelData;
import java.io.Serializable;

public interface IdentifiableModelData<I> extends ModelData, Serializable {
    public I getIdentifier();
}

版本是GWT 2.4.0和GXT 2.2.5。我想尽快升级它,但首先我要处理像这样的问题。

我认为这就是全部。你看到我看不到的东西吗?我当然希望如此!谢谢!

2 个答案:

答案 0 :(得分:2)

期望您的包结构遵循命名约定:您是否可能必须将Market-class移动到共享包中?

如果进行rcp调用,则在客户端对该类进行序列化,并在服务器端进行反序列化。因此,必须可以从客户端和服务器访问该类。如果您的类位于client-package中,则服务器无法访问此类。客户端和服务器端使用的类放在名为shared的包中。

因此,所有只在客户端中需要的类应该位于名为client的包中。服务器和客户端所需的类应位于共享包中,并且只在服务器端的neede内部的类位于服务器包内。

这是我的抽象类,它扩展了BaseModelData并位于共享包中:

package de.gishmo.leela.application.shared.models;

import java.io.Serializable;

import com.extjs.gxt.ui.client.data.BaseModelData;

@SuppressWarnings("serial")
public abstract class MyBaseModel
  extends BaseModelData
  implements Serializable {

  public final static String MYFIELD = "myField";

  public abstract String getModelName();

}

在RCP调用中运行良好。

请实施Serializable接口。

答案 1 :(得分:2)

我被遗忘了。

问题不在于那个班级,根本不是。事实是,它是使用另一个类传递的,它也扩展了RowModel。它就是这样设置的:

public void setMarkets(Set<Market> markets) {
    set(MARKETS,markets);
}

因为我没有在该类中包含Market类型,所以GWT不知道它应该在编译时序列化。在该类中添加private Market _market;就可以了。实际上,这是众所周知的与BaseModelData的子类相关的问题(它不能序列化未声明为类字段的类型),但我完全忘记了它......