2010-11-17 9 views
10

Ho un enum nella parte client di un'applicazione GWT e sto ricevendo un'eccezione quando provo ad eseguirlo che è correlato a problemi di serializzazione. Sto facendo qualcosa di sbagliato? Ho letto che le enumerazioni sono supportate da GWT e sto usando l'ultima versione.Problemi con GWT ed Enum

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

} 

L'eccezione:

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

quale pacchetto è l'enum, e quali percorsi sono elencati nei tag sorgente di gwt.xml? –

+1

Sembra esserci un problema/bug con enumerazioni e GWTRPC! Ho testato il tuo codice con GWT 2.0.3, e funziona (un costruttore no-arg non è nemmeno richiesto). Ma quando uso 'setDescription (" nuovo valore ")' prima di chiamare il metodo di servizio, quella modifica a 'description' è ** lost ** durante il trasferimento al server - cioè il server vede' description' come ancora impostato su " Item a description ". Non l'ho provato con l'ultima versione di GWT, ma forse Google ha tentato di risolvere quel problema per GWT 2.1, ma ha introdotto il problema di serializzazione. –

+5

Appena trovato qualcosa nella [documentazione] (http://code.google.com/webtoolkit/doc/latest/DevGuideServerCommunication.html) su questo: "Le costanti di enumerazione sono serializzate solo come nome, nessuno dei valori dei campi è serializzato ". Pertanto, probabilmente non è una buona idea usare enum con campi mutabili insieme a GWTRPC. –

risposta

14

Aggiungi l'interfaccia IsSerializable, un costruttore no-arg con scope predefinito e assicurati che si trovi in ​​uno dei percorsi elencati nei tag di origine nel file gwt.xml. <source path="client">

Penso davvero che il terzo suggerimento sia il problema; Ricordo di aver avuto questo problema prima ed era perché avevo un dto al di fuori dei percorsi di origine.

È possibile avere più tag di origine.

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

Un modello è di mettere oggetti persistenti direttamente sotto com.mysite.common, e mashup di oggetti persistenti che vengono trasferiti sul filo in com.mysite.common.dto, e naturalmente il codice client GUI nel client.

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

L'ho già fatto e non funziona. La cosa divertente è che l'applicazione ha sempre funzionato con quell'enumerazione. Ha smesso di funzionare quando ho cambiato il nome di alcune delle costanti enum, ma non c'è nulla di sbagliato in questo. – AntonioJunior

+0

Non riesco più a riprodurre il bug ... –

+1

Grazie! Il tuo suggerimento ha risolto il mio problema. Anche dopo aver fatto quello che mi hai suggerito, non funzionava. Si scopre che avevo bisogno di pulire il mio progetto in Eclipse per farlo funzionare. – AntonioJunior

1

penso che hai bisogno di un costruttore senza arg.

+1

Ciao, Nick. Grazie per la pronta risposta. L'ho provato, ma non ha funzionato. – AntonioJunior

-1

a) È assolutamente necessario un costruttore no-op per la serializzazione.

b) È possibile estendere la classe IsSerializable di GWT oppure, se si desidera utilizzare l'interfaccia di serializzazione di Java, è necessario impostare un criterio per consentire ciò. C'è un post relativo a questo allo How do I add a type to GWT's Serialization Policy whitelist?. Inoltre, controlla la vista GWT per ulteriori informazioni su IsSerializable vs. Serializable.

+2

a) questo talmente sbagliato in caso di enumerazione. – jusio

1

ho studiato sopra per risolvere un certo codice GWT scritto nel 2008, quando aggiornato a GWT SDK 2.4.0 (con l'ultimo GXT * .jar) mi dà:

[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) 

Quella classe noto è il seguente (a cura di seguire le idee riportate in questa discussione):

public class AdempiereGXTUtil { 

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

     LoginStage(){ 
     } 
    }; 

} 

Pensando a Andrej's answer per aggiungere il tipo a white-list ma enum non è un nuovo myType, giusto? Comunque qui è qualche riferimento nei codebase (campi non rilevanti rimosso):

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(); 

con:

public interface AdempiereServiceAsync { 

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

Originariamente l'AdempiereGXTUtil non ha attuato IsSerializable, Serializable né ha costruttore vuoto ma mettendoli in precedenza e la pulizia del progetto in Eclipse non modifica gli stessi errori. La versione di Eclipse utilizzata è Indigo su Java 1.6 in ambiente Mac Lion. Sperando di ottenere di più da questo thread, che tra l'altro è sorprendente nella sua profondità tecnica.

+1

Sembra che la soluzione di Andrej collegata sopra sia la strada da percorrere. L'ho risolto avvolgendo l'Enum in modo che fosse usata una normale classe serializzata. Quindi non ha più colpito l'errore. Gli ho dato un +1 al suo posto. Mille grazie, Andrej! Se qualcuno vuole sapere che è la sua soluzione di Dummy dummy (Dummy d) (2 ° post lì). Se qualcuno sta chiedendo posso postare le modifiche che ho fatto al mio codice sopra. –

+0

Ho caricato un film su YouTube su come ho usato l'idea di Andrej e risolto il mio problema sopra. http://youtu.be/gGqvM9pc4mg –

4

Si può provare questa lista di controllo:

  1. Verificare che la classe ha un costruttore di default (senza argomenti)
  2. Verificare che la classe implementa Serializable o IsSerializable o implementa un'interfaccia che si estende Serializable o si estende una classe che implementano Serializable
  3. Verificare che la classe è in un client. * pacchetto o ...
  4. Verificare, se la classe non è in cliente. * pacchetto, che è comp iled in la definizione del modulo xml GWT. Per impostazione predefinita è presente . Se la tua classe è in un altro pacchetto devi aggiungerlo al numero . Ad esempio se la tua classe è in dominio. * Devi aggiungerlo a xml come. Si noti che la classe non può appartenere al pacchetto server! Maggiori dettagli sulla pagina GWT: http://code.google.com/webtoolkit/doc/latest/DevGuideOrganizingProjects.html#DevGuideModuleXml
  5. Se si include la classe da un altro progetto GWT, è necessario aggiungere alla configurazione del modulo xml. Ad esempio se la tua classe Foo si trova nel pacchetto com.dummy.domain devi aggiungere alla definizione del modulo. Maggiori dettagli qui: http://code.google.com/webtoolkit/doc/latest/DevGuideOrganizingProjects.html#DevGuideInheritingModules
  6. Se si include la classe da un altro progetto GWT rilasciato come un vaso verificare che il vaso contiene anche il codice sorgente a causa GWT ricompilazione anche la fonte di Java per le classi passati al client.

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

0

In questo caso, Enum non può essere in classe. Devi creare un Enum esterno.