java GWT 和 Enum 的问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4207988/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 05:19:19  来源:igfitidea点击:

Problems with GWT and Enum

javagwtenums

提问by AntonioJunior

I have an enum in the client part of a GWT application and I am getting an exception when I try to run it that is related to serialization problems. Am I doing anything wrong? I read that enums are supported by GWT and I am using the last version.

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

The enum:

枚举:

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;
    }

}

The exception:

例外:

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

回答by antony.trupe

Add IsSerializable interface, a default scoped no-arg constructor, and make sure its in one of the paths listed in the source tags in your gwt.xml file. <source path="client">

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

I really think the third suggestion is the issue; I remember having this issue before and it was because I had a dto outside the source paths.

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

You can have multiple source tags.

您可以有多个源标签。

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

One pattern is to put persisted objects directly under com.mysite.common, and mashups of persisted items that get transferred over the wire in com.mysite.common.dto, and of course the client gui code is in client.

一种模式是将持久化对象直接放在 com.mysite.common 下,并将通过网络传输的持久化项的混搭放在 com.mysite.common.dto 中,当然客户端 gui 代码在 client.xml 中。

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;
    }

}

回答by HenioJR

You can try this check list:

你可以试试这个检查清单:

  1. Verify that the class has a default constructor (without arguments)
  2. Verify that the class implements Serializable or IsSerializable or implements an Interface that extends Serializable or extends a class that implement Serializable
  3. Verify that the class is in a client.* package or …
  4. Verify, if the class is not in client.* package, that is compiled in your GWT xml module definition. By default is present. If your class is in another package you have to add it to source. For example if your class is under domain.* you should add it to xml as . Be aware that the class cannot belong to server package! More details on GWT page: http://code.google.com/webtoolkit/doc/latest/DevGuideOrganizingProjects.html#DevGuideModuleXml
  5. If you are including the class from another GWT project you have to add the inherits to your xml module definition. For example if your class Foo is in the package com.dummy.domain you have to add to the module definition. More details here: http://code.google.com/webtoolkit/doc/latest/DevGuideOrganizingProjects.html#DevGuideInheritingModules
  6. If you are including the class from another GWT project released as a jar verify that the jar contains also the source code because GWT recompile also the Java source for the classes passed to the Client.
  1. 验证该类是否具有默认构造函数(不带参数)
  2. 验证该类是否实现了 Serializable 或 IsSerializable 或实现了扩展 Serializable 的接口或扩展了实现 Serializable 的类
  3. 验证该类是否在 client.* 包中或...
  4. 验证该类是否不在 client.* 包中,是否在您的 GWT xml 模块定义中编译。默认情况下存在。如果您的类在另一个包中,则必须将其添加到源中。例如,如果您的课程在 domain.* 下,您应该将其添加到 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. 如果您要包含来自另一个作为 jar 发布的 GWT 项目的类,请验证该 jar 还包含源代码,因为 GWT 还会为传递给客户端的类重新编译 Java 源。

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

字体:http: //isolaso​​ftware.it/2011/03/22/gwt-serialization-policy-error/

回答by Nick Siderakis

i think you need a no arg constructor.

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

回答by Redhuan D. Oon

I been studying above to solve some GWT code written in 2008, when upgraded to GWT SDK 2.4.0 (with latest gxt*.jar) gives me:

我一直在研究上面解决一些在 2008 年编写的 GWT 代码,当升级到 GWT SDK 2.4.0(使用最新的 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)

That notorious class is as follows (edited to follow ideas given in this thread):

那个臭名昭著的课程如下(根据此线程中给出的想法进行了编辑):

public class AdempiereGXTUtil {

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

        LoginStage(){
        }
    };

}

Thinking about Andrej's answerto add type to white-list but enum is not some new myType, right? Anyway here is some reference in the codebase (non-relevant fields removed):

考虑 Andrej将类型添加到白名单但枚举不是一些新的 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();

with:

和:

public interface AdempiereServiceAsync {

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

Originally the AdempiereGXTUtil did not implement IsSerializable, Serializable nor has empty constructor but putting them in above, and cleaning out project in Eclipse does not change the same errors. Eclipse version used is Indigo on Java 1.6 in a Mac Lion environment. Hoping to get more from this thread, which by the way is amazing in its technical depth.

最初 AdempiereGXTUtil 没有实现 IsSerializable、Serializable 也没有空的构造函数而是将它们放在上面,并且在 Eclipse 中清理项目不会改变相同的错误。在 Mac Lion 环境中使用的 Eclipse 版本是 Java 1.6 上的 Indigo。希望从这个线程中获得更多,顺便说一下,它的技术深度令人惊叹。

回答by HenioJR

In this case, Enum cannot be in the class. You have to create an external Enum.

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

回答by jpleal

Only names of enumeration constants are serialized by GWT's RPC. Field values are notserialized.

GWT 的 RPC 仅序列化枚举常量的名称。字段值序列化。

GWT:Server Communication:Serializable Types

GWT:服务器通信:可序列化类型

回答by karakuricoder

a) You definitely need a no-op constructor for serialization.

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

b) You can either extend GWT' IsSerializable class or, if you want to use Java's Serialization interface you must setup a policy to allow this. There's a post related to this at How do I add a type to GWT's Serialization Policy whitelist?. Also, check the GWT sight for more information on IsSerializable vs. Serializable.

b) 您可以扩展 GWT 的 IsSerializable 类,或者,如果您想使用 Java 的 Serialization 接口,您必须设置一个策略来允许这样做。在如何将类型添加到 GWT 的序列化策略白名单?. 此外,请查看 GWT 瞄准器以获取有关 IsSerializable 与 Serializable 的更多信息。