2010-11-17 93 views
10

我在GWT应用程序的客户端部分有一个枚举,当我尝试运行与序列化问题有关的运行时,出现异常。我做错了什么?我读过,GWT支持枚举,我使用的是最后一个版本。GWT和枚举的问题

枚举:

public enum AnEnum implements Serializable { 

    ITEM_A("Item a description"), ITEM_B("Item b description"); 

    private String description; 

    private AnEnum(String description) { 
     this.description = description; 
    } 

    public String getDescription() { 
     return description; 
    } 

    public void setDescription(String description) { 
     this.description = description; 
    } 

} 

例外:

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:742) 
    ... 47 more 
Caused by: com.google.gwt.user.client.rpc.SerializationException: Type '(...).client.(...).AnEnum' 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 = ITEM_A 
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:610) 
    at com.google.gwt.user.client.rpc.impl.AbstractSerializationStreamWriter.writeObject(AbstractSerializationStreamWriter.java:129) 
    at com.google.gwt.user.client.rpc.core.java.util.Collection_CustomFieldSerializerBase.serialize(Collection_CustomFieldSerializerBase.java:43) 
    at com.google.gwt.user.client.rpc.core.java.util.LinkedList_CustomFieldSerializer.serialize(LinkedList_CustomFieldSerializer.java:36) 
    ... 52 more 
+0

什么包是在枚举,什么路径在gwt.xml的源代码上市? – 2010-11-17 20:05:06

+1

肯定有一个问题/错误与枚举和GWTRPC!我用GWT 2.0.3测试了你的代码,并且它可以工作(甚至不需要无参数构造函数)。但是,当我在调用服务方法之前使用'setDescription(“new value”)'时,在传输到服务器期间,对'description'的改变**丢失** - 即服务器将'description'仍然设置为“项目说明“。我还没有用最新版本的GWT尝试过,但也许Google试图解决GWT 2.1的这个问题,但引入了序列化问题。 – 2010-11-17 23:35:44

+5

刚刚在[documentation](http://code.google.com/webtoolkit/doc/latest/DevGuideServerCommunication.html)中找到了关于此的一些内容:“枚举常量仅作为名称序列化;没有任何字段值被序列化“。因此,在GWTRPC中使用带有可变域的枚举可能不是一个好主意。 – 2010-11-17 23:43:46

回答

14

添加IsSerializable接口,一个默认的scoped no-arg构造函数,并确保它位于gwt.xml文件中源标记中列出的路径之一中。 <source path="client">

我真的认为第三个建议是问题;我记得之前有过这个问题,那是因为我在源路径之外有一个dto。

您可以有多个源标签。

<source path="common" /> 
<source path="client" /> 

一种模式是把直属com.mysite.common持久对象,并得到转移了在com.mysite.common.dto电线持久项目混搭,当然还有客户端GUI代码在客户端。

package com.mysite.client; 

import java.io.Serializable; 

import com.google.gwt.user.client.rpc.IsSerializable; 

public enum AnEnum implements Serializable, IsSerializable { 

    ITEM_A("Item a description"), ITEM_B("Item b description"); 

    private String description; 

    AnEnum() { 
    } 

    AnEnum(String description) { 
     this.description = description; 
    } 

    public String getDescription() { 
     return description; 
    } 

    public void setDescription(String description) { 
     this.description = description; 
    } 

} 
+0

我已经这样做了,它不起作用。有趣的是,应用程序始终与该枚举一起工作。当我改变了一些枚举常量的名字时,它停止了工作,但没有任何错误。 – AntonioJunior 2010-11-17 20:23:41

+0

我不能再现你的bug了... – 2010-11-17 20:36:56

+1

谢谢!你的建议解决了我的问题。即使在我做了你所建议的事情之后,它仍然无法正常工作。事实证明,我需要在Eclipse中清理我的项目才能使其运行。 – AntonioJunior 2010-11-18 19:31:11

1

我认为你需要一个无参数的构造函数。

+1

嗨,尼克。感谢您的及时回复。我试过了,但没有奏效。 – AntonioJunior 2010-11-17 19:05:08

-1

a)你肯定需要一个无操作构造函数来进行序列化。

b)您可以扩展GWT的IsSerializable类,或者如果您想使用Java的序列化接口,您必须设置一个策略来允许这样做。有一个帖子与How do I add a type to GWT's Serialization Policy whitelist?有关。另外,请查看GWT视野以获取更多关于IsSerializable与Serializable的信息。

+2

a)在枚举的情况下,这个错误是错误的。 – jusio 2012-01-09 14:43:26

1

我一直在研究上面来解决写于2008年,当升级到GWT SDK 2.4.0一些GWT代码(带最新的GXT的* .jar)给我:

[WARN] adempiereService: An IncompatibleRemoteServiceException was thrown while processing this call. 
com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: com.google.gwt.user.client.rpc.SerializationException: Type 'org.idempiere.ui.gwt.client.util.AdempiereGXTUtil$LoginStage' was not included in the set of types which can be deserialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be deserialized. 
    at com.google.gwt.user.server.rpc.RPC.decodeRequest(RPC.java:315) 
    at com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall(RemoteServiceServlet.java:206) 

...

Caused by: com.google.gwt.user.client.rpc.SerializationException: com.google.gwt.user.client.rpc.SerializationException: Type 'org.idempiere.ui.gwt.client.util.AdempiereGXTUtil$LoginStage' was not included in the set of types which can be deserialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be deserialized. 
at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamReader.deserialize(ServerSerializationStreamReader.java:581) 

那臭名昭著的等级如下表所示(编辑遵循这个线程给出的观点):

public class AdempiereGXTUtil { 

    public enum LoginStage implements IsSerializable, Serializable { 
     LOGOUT, 
     LOGIN, 
     ISLOGGEDIN, 
     ROLES, 
     WRONGUSER, 
     WRONGROLE; 

     LoginStage(){ 
     } 
    }; 

} 

思考Andrej的answer将类型添加到白名单,但枚举不是一些新的myType,对吧?反正这里是在代码库一定的参考(非相关领域去除):

public interface AdempiereService extends RemoteService { 

    public static final String SERVICE_URI = "adempiereService"; 

    public static class Util { 

     public static AdempiereServiceAsync getInstance() { 

      AdempiereServiceAsync instance = (AdempiereServiceAsync) GWT 
        .create(AdempiereService.class); 
      return instance; 
     } 
    } 

...  
    public LoginStage getLoginStage(); 

有:

public interface AdempiereServiceAsync { 

... 
    public void getLoginStage(AsyncCallback<LoginStage> callback); 

本来AdempiereGXTUtil没有实行IsSerializable,序列化也没有空的构造函数,但将它们放在上面,并在Eclipse中清理项目不会改变相同的错误。所用的Eclipse版本是Mac Lion环境中的Java 1.6上的Indigo。希望从这个主题中获得更多,这在技术深度上是惊人的。

+1

安德烈的解决方案似乎是前进的道路。我通过包装Enum来解决它,以便使用正常的序列化类。然后它不会再出现这个错误。我在他的职位给他+1。非常感谢Andrej!如果有人想知道这是他的虚拟假人(Dummy d)解决方法(第二篇文章)。如果有人问我可以发布我上面对我的代码所做的修改。 – 2012-01-11 15:23:48

+0

我上传了一部关于我如何使用Andrej的想法并解决了上述问题的YouTube电影。 http://youtu.be/gGqvM9pc4mg – 2012-01-12 13:46:31

4

你可以试试这个检查表:

  1. 验证类有一个默认的构造函数(不带参数)
  2. 验证类实现Serializable或IsSerializable或 实现扩展序列化或扩展接口一个类 ,实现Serializable
  3. 验证该类是在客户端。*包或...
  4. 验证,如果该类不在客户端。*包,那是comp你的GWT xml模块定义在 。默认情况下, 存在。如果你的课程在另一个包中,你必须将其添加到源代码 。例如,如果你的班级在域名下。*你应该将 添加到xml中。请注意,类 不能属于服务器包! GWT上的更多详细信息:http://code.google.com/webtoolkit/doc/latest/DevGuideOrganizingProjects.html#DevGuideModuleXml
  5. 如果您要从另一个GWT项目中包含该类,则必须将其添加到 将继承添加到您的xml模块定义中。例如,如果您的 类Foo包含在com.dummy.domain包中,则必须将 添加到模块定义中。 更多细节在这里:http://code.google.com/webtoolkit/doc/latest/DevGuideOrganizingProjects.html#DevGuideInheritingModules
  6. 如果是包括释放 另一个GWT项目类中的罐子验证罐子还包含了源代码,因为GWT 重新编译也传递到客户端的类Java源代码。

字体:http://isolasoftware.it/2011/03/22/gwt-serialization-policy-error/

0

在这种情况下,枚举不能在类。你必须创建一个外部枚举。