GWT: сбит с толку ошибкой сериализации

#java #gwt #serialization

#java #gwt #сериализация

Вопрос:

Я использую GWT 2.4. У меня проблема с сериализацией. У моей службы есть метод…

 @RemoteServiceRelativePath("retrieveChild")
public interface ChildRetrievalService extends RemoteService {
    ...
    Collection<Node> getRootNodes();   
  

В котором мой класс «Node» определяется следующим образом…

 public class Node implements Serializable {

    private Long id;
    private Node parent;
    private String info;
    private List<Node> children;

    public Node() { 
        this.children = new ArrayList<Node>();
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) { 
        this.id = id;
    }   // setId

    public Node getParent() {
        return parent;
    }

    public void setParent(Node parent) {
        this.parent = parent;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) { 
        this.info = info;
    }   // setInfo

    public List<Node> getChildren() {
        return children;
    }

    public boolean equals(Object node) { 
        return node != null amp;amp;
            node instanceof Node amp;amp;
            ((Node) node).getId() == id;
    }

    public int hashCode() { 
        return getId().hashCode();
    }

}
  

Но я получаю сообщение об ошибке при попытке вызвать метод service, жалуясь на сериализацию. И HashMap, и Node сериализуемы, так где же все ломается?

 [WARN] Exception while dispatching incoming RPC call
  

com.google.gwt.user.client.rpc.SerializationException: Введите ‘java.util.HashMap$Values’ не был включен в набор типов, которые могут быть сериализованы этой SerializationPolicy, или не удалось загрузить его объект класса. В целях безопасности этот тип не будет сериализован.: instance = [com.cme.draganddroptree.shared.Узел @0, com.cme.draganddroptree.shared.Узел @1, com.cme.draganddroptree.shared.Узел @2, com.cme.draganddroptree.shared.Узел @3, com.cme.draganddroptree.shared.Узел @4]
в com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:619)
в com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:126)
в com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter$ValueWriter$8.write(ServerSerializationStreamWriter.java:153)
в com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeValue(ServerSerializationStreamWriter.java:539)
в com.google.gwt.user.server.rpc.RPC.encodeResponse(RPC.java:616)
в com.google.gwt.user.server.rpc.RPC.encodeResponseForSuccess(RPC.java:474)
в com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java: 571)
в com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:208)
в com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:248)
в com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62)
в javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
в javax.servlet.http.HttpServlet.service(HttpServlet.java: 717)
в org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
в org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java: 362)
в org.mortbay.причал.безопасность.SecurityHandler.handle(SecurityHandler.java: 216)
в org.mortbay.jetty.servlet.Обработчик сеанса.дескриптор (SessionHandler.java: 181)
в org.mortbay.причал.обработчик.ContextHandler.handle(ContextHandler.java:729)
в org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java: 405)
в org.mortbay.причал.обработчик.HandlerWrapper.handle(HandlerWrapper.java:152)
в org.mortbay.причал.обработчик.RequestLogHandler.handle(RequestLogHandler.java:49)
в org.mortbay.причал.обработчик.HandlerWrapper.handle(HandlerWrapper.java:152)
в org.mortbay.причал.Server.handle(Server.java:324)
в org.mortbay.причал.HttpConnection.handleRequest(HttpConnection.java: 505)
в org.mortbay.причал.HttpConnection$RequestHandler.content(HttpConnection.java:843)
в org.mortbay.причал.HttpParser.parseNext(HttpParser.java:647)
в org.mortbay.причал.HttpParser.parseAvailable(HttpParser.java: 205)
в org.mortbay.причал.HttpConnection.обработайте (HttpConnection.java: 380)
в org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
в org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)

Спасибо, — Дэйв

Комментарии:

1. Я бы попробовал поместить конкретный тип коллекции, который находится в интерфейсе RemoteService. иногда GWT может сойти с ума по поводу того, занесен он в белый список или нет.

Ответ №1:

Вы не можете использовать абстрактный тип (или интерфейс) для параметра метода для GWT RPC:

Текущая система GWT RPC основана на сериализации конкретных типов. В общем случае идентичный конкретный тип должен быть доступен как на клиенте, так и на сервере. Хотя пользовательский сериализатор может использоваться для изменения фактического типа, используемого либо на клиенте, либо на сервере, сериализованный тип должен иметь представление об используемом сериализаторе. Это проблематично, когда интерфейсы RPC объявляются с использованием (абстрактных) типов, реализаций которых на сервере произвольно много.

Подробности смотрите здесь.

Это сводится к тому, что механизм RPC не может сериализовать ваш параметр, потому что он не знает, каким он действительно будет. В качестве альтернативы, любой подход к сериализации любой возможной конкретной реализации просто непрактичен. Итак, вам нужно выбрать конкретный класс, который наилучшим образом соответствует вашим потребностям.

Ответ №2:

Всегда используйте конкретный тип для данных, используемых в RPC. Потому что компилятору GWT необходимо сгенерировать реализации для всех подклассов, поскольку он не знает, какой подтип будет отправлен с сервера. Это может означать, что для некоторых типов или интерфейсов это может привести к большим накладным расходам, добавлению множества типов, которые никогда не используются. Например, вы знаете, что используете ArrayList только тогда, когда у вас указан список.

Вероятно, это также может вызвать эту ошибку, потому что он хочет добавить подтип, который он не может сериализовать.