GWT RCP - 序列化异常

Posted

技术标签:

【中文标题】GWT RCP - 序列化异常【英文标题】:GWT RCP - SerializationException 【发布时间】:2011-05-09 10:39:42 【问题描述】:

从头开始一个新项目,转换为 JPA,我的持久化提供程序是 EclipseLink,添加了必要的库(eclipselink.jar、eclipselink.jar、javax.persistence、mysql-connector-java-5.1)。测试连接,ping 正常。然后创建一个新包 New > JPA > Entities from Tables > Selected all Entities and Key generator > Identity。

GestorIpca.java

            GestorIpcaService.util.getInstance().getLista(new AsyncCallback<ArrayList<Docente>>() 

                @Override
                public void onFailure(Throwable caught) 
                    Window.alert("Erro na Ligacao efectuada");
                    caught.getStackTrace();
                

                @Override
                public void onSuccess(ArrayList<Docente> result) 
                    Window.alert("Ligacao efectuada com sucesso:" + result.size());
                
            );    

GestorIpcaService

@RemoteServiceRelativePath("greet")
public interface GestorIpcaService extends RemoteService 
    String greetServer(String name) throws IllegalArgumentException;

    public static class util
        public static GestorIpcaServiceAsync instance;
        public static GestorIpcaServiceAsync getInstance()
            if(instance == null)
                instance = GWT.create(GestorIpcaService.class);
            
        return instance;
        
    
    public ArrayList<Docente> getLista() throws IllegalArgumentException;
    

GestorIpcaServiceAsync

public interface GestorIpcaServiceAsync 
        void greetServer(String input, AsyncCallback<String> callback)
                throws IllegalArgumentException;

        void getLista(AsyncCallback<ArrayList<Docente>> callback);
    

GestorIpcaServiceImpl

@SuppressWarnings("serial")
public class GestorIpcaServiceImpl extends RemoteServiceServlet implements
        GestorIpcaService 

    public ArrayList<Docente> getLista() throws IllegalArgumentException  
        //Criamos um EntityManager
        EntityManager em = JpaUtil.getEntityManagerFactory().createEntityManager();
        //Criamos a consulta
        String consulta = "SELECT r from Docente r";
        //Executamos a consulta
        Query q = em.createQuery(consulta);
        ArrayList<Docente> lista = new ArrayList<Docente>(q.getResultList());
        return lista;
    
/*  public static void main(String args[])
        GestorIpcaServiceImpl serviceImpl = new GestorIpcaServiceImpl();
        for (Docente docente : serviceImpl.getLista())
            System.out.println("nome: " + docente.getNome());
        
    
    */   

在此文件中,我尝试以 > Java 应用程序的身份运行,并在控制台中向我显示了 2 条记录。 包 com.GestorIpca.factory

import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class JpaUtil 
    private static final EntityManagerFactory emf;
    //Método estático
    static
        //BLoco try
        try
        
            //Criação de EntityManagerFactory
            emf = Persistence.createEntityManagerFactory("GestorIpca");
        catch (Throwable e)
            //Controlar as excepções
            System.err.println("A criação de SessionFactory falhou" + e);
            e.printStackTrace();
            throw new ExceptionInInitializerError(e);
        
    

    public static EntityManagerFactory getEntityManagerFactory()
        return emf;
    
    

我的 persistence.xml 是自动创建的。放置在 META-INF 中

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="GestorIpca">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>

    <class>com.GestorIpca.shared.Ano</class>
    <class>com.GestorIpca.shared.Categoria</class>
    <class>com.GestorIpca.shared.Curso</class>
    <class>com.GestorIpca.shared.Disciplina</class>
    <class>com.GestorIpca.shared.Disponibilidade</class>
    <class>com.GestorIpca.shared.Docente</class>
    <class>com.GestorIpca.shared.Sala</class>
    <class>com.GestorIpca.shared.Semestre</class>
    <class>com.GestorIpca.shared.TipoCurso</class>
    <class>com.GestorIpca.shared.Turma</class>
    <class>com.GestorIpca.shared.User</class>
        <properties>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/timetable"/>
            <property name="javax.persistence.jdbc.user" value="root"/>
            <property name="javax.persistence.jdbc.password" value="k771u3"/>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
        </properties>
    </persistence-unit>
</persistence>

最后一步 > 运行方式 > Web 应用程序 错误 > 无法连接到数据库并在 Eclipse 控制台中打印堆栈跟踪

[EL Info]: 2011-05-09 10:03:08.78--ServerSession(8068087)--EclipseLink, version: Eclipse Persistence Services - 2.2.0.v20110202-r8913
[EL Info]: 2011-05-09 10:03:09.297--ServerSession(8068087)--file:/C:/Users/Martinho/WorkSpace/GestorIpca/war/WEB-INF/classes/_GestorIpca login successful
Starting Jetty on port 8888
   [WARN] Exception while dispatching incoming RPC call
com.google.gwt.user.client.rpc.SerializationException: java.lang.reflect.InvocationTargetException
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeWithCustomSerializer(ServerSerializationStreamWriter.java:764)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeImpl(ServerSerializationStreamWriter.java:727)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:616)
    at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:126)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter$ValueWriter$8.write(ServerSerializationStreamWriter.java:152)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeValue(ServerSerializationStreamWriter.java:534)
    at com.google.gwt.user.server.rpc.RPC.encodeResponse(RPC.java:616)
    at com.google.gwt.user.server.rpc.RPC.encodeResponseForSuccess(RPC.java:474)
    at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:571)
    at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:208)
    at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:248)
    at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:362)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.handler.RequestLogHandler.handle(RequestLogHandler.java:49)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:324)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
    at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843)
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:647)
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
    at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeWithCustomSerializer(ServerSerializationStreamWriter.java:746)
    ... 30 more
Caused by: com.google.gwt.user.client.rpc.SerializationException: Type 'org.eclipse.persistence.indirection.IndirectSet' 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 = IndirectSet: not instantiated
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:614)
    at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:126)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter$ValueWriter$8.write(ServerSerializationStreamWriter.java:152)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeValue(ServerSerializationStreamWriter.java:534)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeClass(ServerSerializationStreamWriter.java:704)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeImpl(ServerSerializationStreamWriter.java:734)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:616)
    at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:126)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter$ValueWriter$8.write(ServerSerializationStreamWriter.java:152)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeValue(ServerSerializationStreamWriter.java:534)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeClass(ServerSerializationStreamWriter.java:704)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serializeImpl(ServerSerializationStreamWriter.java:734)
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:616)
    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:45)
    at com.google.gwt.user.client.rpc.core.java.util.ArrayList_CustomFieldSerializer.serialize(ArrayList_CustomFieldSerializer.java:38)
    ... 35 more
[ERROR] 500 - POST /gestoripca/greet (127.0.0.1) 57 bytes
   Request headers
      Host: 127.0.0.1:8888
      Connection: keep-alive
      Referer: http://127.0.0.1:8888/GestorIpca.html?gwt.codesvr=127.0.0.1:9997
      Content-Length: 132
      Origin: http://127.0.0.1:8888
      X-GWT-Module-Base: http://127.0.0.1:8888/gestoripca/
      X-GWT-Permutation: HostedMode
      User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.30 Safari/534.30
      Content-Type: text/x-gwt-rpc; charset=UTF-8
      Accept: */*
      Accept-Encoding: gzip,deflate,sdch
      Accept-Language: pt-PT,pt;q=0.8,en-US;q=0.6,en;q=0.4
      Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
   Response headers
      Content-Type: text/plain    

注意:我在包 com.GestorIpca.shared 中更改了我从表生成的所有类

public class Ano implements Serializable 

public class Ano implements IsSerializable    

还更改了我的 GestorIpca.gwt.xml 并在末尾添加了这一行

<extend-configuration-property name="rpc.blacklist" value="com.google.gwt.user.client.ui.*Collection"/>
<extend-configuration-property name="rpc.blacklist" value="-.*List"/>
<extend-configuration-property name="rpc.blacklist" value="-.*Map"/>
<extend-configuration-property name="rpc.blacklist" value="-.*Collection"/>
<extend-configuration-property name="rpc.blacklist" value="+java.util.HashMap"/>
<extend-configuration-property name="rpc.blacklist" value="+java.util.LinkedHashMap"/>
<extend-configuration-property name="rpc.blacklist" value="+java.util.ArrayList"/>

我错过了什么?

【问题讨论】:

【参考方案1】:

我取决于您的实体是如何定义的。也许存在 GWT RPC 不喜欢的连接。在这种情况下,我建议创建 DTO 或实施 RequestFactory

【讨论】:

【参考方案2】:

在不知道您的实体是什么样子的情况下,我会从异常中猜测原因可能是您的实体如何被持久性提供程序增强:

这对 GWT RPC 意味着,当对象准备好通过网络传输时,它实际上并不是编译器认为要传输的同一个对象,因此在尝试反序列化时, GWT RPC 机制不再知道类型是什么并且拒绝反序列化它。

引用自:http://code.google.com/intl/de-DE/webtoolkit/articles/using_gwt_with_hibernate.html

那篇文章还建议了如何创建 DTO 来解决这个问题。

【讨论】:

所以我需要为每个班级创建一个 DTO?我的天啊。文章发表于 2009 年。2 年后他们仍然没有解决问题? 是的,他们做到了:他们建立了 RequestFactory。【参考方案3】:

我知道这是一个非常古老的问题,但我今晚遇到了这个确切的问题。

GWT 序列化似乎不喜欢 java.util.Set。我几乎觉得 java.util.Set 与 org.eclipse.persistence.indirection.IndirectSet 混淆了。

一旦我将 Set 切换为 ArrayList,错误就消失了。

【讨论】:

以上是关于GWT RCP - 序列化异常的主要内容,如果未能解决你的问题,请参考以下文章

GWT 序列化异常

GWT RCP ServiceEntryPointSpecifiedException

如何序列化 AutoBean (GWT) 中的列表?

GWT:枚举列表抛出“无法反序列化响应”

GWT JPA - 无法反序列化响应

调试 GWT Rcp 失败且无错误