0

我以为我知道 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 (因为 internalRpcMap为 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。我想尽快升级它,但首先我想处理这样的问题。

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

4

2 回答 2

2

我有一个遗忘。

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

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

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

于 2013-10-29T14:40:05.363 回答
2

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

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

因此,仅在您的客户端中需要的所有类都应该在一个名为 client 的包中。服务器和客户端需要的类应该在共享包内,而只在服务器端需要的类在服务器包内。

这是我的抽象类,它扩展了 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 调用中效果很好。

请实现可序列化接口。

于 2013-10-29T14:07:34.660 回答