3 votes

XStream lance une exception "constructeur sans argument" sur Android

Je suis en train d'essayer d'utiliser XStream pour (dé)sérialiser une HashMap de certaines de mes propres classes dans une application Android. Par exemple, l'une des classes est Word, qui a les variables suivantes:

private String word;
private boolean capitalizable;
private int useCount;
private HashMap endPunctuation;
private HashSet nextWritables;

J'ai déjà tout mis en place dans une application Java standard, je suis juste en train d'essayer de l'emballer dans une interface utilisateur Android (ce qui fonctionne bien). La sérialisation fonctionne bien en Android. Le problème que j'ai, c'est lorsque je désérialise, j'obtiens l'erreur suivante:

com.thoughtworks.xstream.converters.ConversionException: Impossible de construire chatai.Word car il n'a pas de constructeur sans arguments : Impossible de construire chatai.Word car il n'a pas de constructeur sans arguments
---- Informations de débogage ----
message : Impossible de construire chatai.Word car il n'a pas de constructeur sans arguments
cause-exception : com.thoughtworks.xstream.converters.reflection.ObjectAccessException
cause-message : Impossible de construire chatai.Word car il n'a pas de constructeur sans arguments
classe : java.util.HashMap
type-requis : chatai.Word
chemin : /map/entry/chatai.Word
numéro de ligne : 1
-------------------------------

Je reçois cette erreur si j'utilise une version de XStream autre que 1.4.1 sur mon application de bureau. Je reçois toujours l'erreur sur mon application Android, peu importe la version de XStream. Je suis sûr que celui de bureau a ce problème car il fonctionne sur Java 7. Je ne suis pas sûr pour Android. Cela a quelque chose à voir avec la réflexion, en raison de cet avertissement lors de l'ajout du xstream-1.4.1.jar:

[2011-09-07 21:06:52 - DroidBot] Avertissement Dx : Ignorer l'attribut InnerClasses pour une classe interne anonyme
(com.thoughtworks.xstream.XStream$2) qui ne comporte pas d'attribut EnclosingMethod associé. Cette classe a probablement été produite par un compilateur qui ne ciblait pas le format de fichier .class moderne. La solution recommandée est de recompiler la classe à partir de la source, en utilisant un compilateur à jour et sans spécifier d'options de type "-target". La conséquence de l'ignorance
de cet avertissement est que les opérations de réflexion sur cette classe indiqueront incorrectement
qu'il ne s'agit *pas* d'une classe interne.

Un test rapide me montre que sérialiser et désérialiser un objet String dans Android fonctionne bien. Comment puis-je me débarrasser de cette erreur?

2voto

MikeWeber Points 36

Oui, cette question est ancienne, mais pour le chercheur curieux sur internet :

La désérialisation nécessite xstream pour construire un objet et définir tous ses champs membres aux valeurs spécifiées dans le xml. Si l'objet que vous essayez de désérialiser n'a pas de constructeur sans argument, alors xstream a besoin d'aide de la part de la VM pour construire l'objet en dehors du processus normal d'instanciation et d'initialisation de l'objet. Cette aide est disponible uniquement dans certaines VM ; elle n'est pas disponible sous la VM Dalvik lorsqu'elle s'exécute sur un appareil Android.

Si vous vérifiez le fournisseur utilisé pour désérialiser votre xml, vous constaterez que sur votre ordinateur de bureau le fournisseur est probablement le Sun14ReflectionProvider, qui utilise un support spécial de la VM pour construire des objets sans appeler leurs constructeurs. Sous Android, le fournisseur sera le PureJavaReflectionProvider, qui ne peut pas désérialiser des objets sans constructeur sans argument.

XStream xstream = new XStream();

ReflectionProvider rp = xstream.getReflectionProvider();
if(null != rp)
{
    System.out.println("Classe du fournisseur : " + rp.getClass().getName());
    if(rp instanceof Sun14ReflectionProvider)
        System.out.println("Utilisation de Sun14ReflectionProvider");
    else if(rp instanceof PureJavaReflectionProvider)
        System.out.println("Utilisation de PureJavaReflectionProvider");
}

En résumé : Vous ne pouvez pas désérialiser un objet sans constructeur sans argument en utilisant XStream dans un environnement Android. Si vous avez le contrôle sur l'objet, refactorisez-le pour avoir un constructeur sans argument. Si vous n'avez pas le contrôle sur l'objet, vous êtes malchanceux en ce qui concerne XStream.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X