2010-11-17 99 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

在這種情況下,枚舉不能在類。你必須創建一個外部枚舉。