После незначительных изменений сериализация 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()
который - в этом случае - возвращает ноль (потому что внутренний RpcMap
является нулевым, и это является нулевым, потому что никакие значения не установлены в 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 ответа
Ожидая, что структура вашего пакета соответствует соглашениям об именах: возможно ли, что вам придется переместить ваш Market-класс в общий пакет?
Если вы делаете вызов rcp, класс сериализуется на стороне клиента и десериализуется на стороне сервера. Поэтому класс должен быть доступен с клиента и с сервера. Если ваш класс лежит в клиентском пакете, сервер не сможет получить доступ к этому классу. Классы, которые используются на стороне клиента и сервера, помещаются в пакет, называемый общим.
Итак, все классы, которые нужны только вашему клиенту, должны быть внутри пакета под названием 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-вызовах.
И, пожалуйста, реализуйте Сериализуемый интерфейс.
У меня есть забвение.
Проблема была не в этом классе, совсем нет. Дело в том, что он передается с использованием другого класса, который также расширяет RowModel. И это установлено так:
public void setMarkets(Set<Market> markets) {
set(MARKETS,markets);
}
И поскольку я не включил тип Market в этот класс, GWT не знал, что его нужно сериализовать во время компиляции. Добавление private Market _market;
в этом классе сделали свое дело. На самом деле это хорошо известная проблема, связанная с подклассами BaseModelData
(что он не может сериализовать типы, которые не объявлены как поля класса), но я полностью забыл это...