2013-04-03 3 views
5

J'ai une application Android qui se connecte à Google App Engine en utilisant les services de repos, l'application fonctionne parfaitement jusqu'à ce qu'elle soit masquée par ProGuard avant la libération.ProGuard - org.codehaus.jackson.map.JsonMappingException: Aucun constructeur approprié trouvé pour le type

L'erreur signalée dans LogCat lors de l'exécution de l'application est brouillée:

Unable to convert a [application/json,UTF-8] representation into an object of 
    class com.enterprisemk.android.bcw.bincollection.WasteCollectionAreasContainer 

org.codehaus.jackson.map.JsonMappingException: No suitable constructor found 
    for type [simple type, class 
    com.enterprisemk.android.bcw.bincollection.WasteCollectionAreasContainer]: 
    can not instantiate from JSON object (need to add/enable type information?) 

je suit dans mon fichier proguard-project.txt:

-keepattributes *Annotation*,EnclosingMethod 

-keep public class org.w3c.** {public private protected *;} 
-dontwarn org.w3c.** 

-keep public class org.joda.time.** {public private protected *;} 
-dontwarn org.joda.time.** 

-keep public class org.restlet.** { *; } 
-dontwarn org.restlet.** 

-keep public class org.codehaus.** { *; } 
-dontwarn org.codehaus.** 

-keepattributes Signature 
-keepnames class com.fasterxml.jackson.** { *; } 
-dontwarn com.fasterxml.jackson.databind.** 

Et ma classe l'erreur fait référence à ressemble à:

public class WasteCollectionAreasContainer { 

public List<WasteCollectionAreas> wasteCollectionAreasList; 

public List<WasteCollectionAreas> getWasteCollectionAreasList() { 
    return wasteCollectionAreasList; 
} 

public void setWasteCollectionAreasist(List<WasteCollectionAreas> wasteCollectionAreasList) { 
    this.wasteCollectionAreasList = wasteCollectionAreasList; 
} 

public WasteCollectionAreasContainer() { 
    wasteCollectionAreasList = new ArrayList<WasteCollectionAreas>(); 
} 

@JsonCreator 
public WasteCollectionAreasContainer(List<WasteCollectionAreas> wasteCollectionAreasList) { 
    this.wasteCollectionAreasList = wasteCollectionAreasList; 
} 
} 

Pour réitérer avant l'obfuscation via ProGuard l'application fonctionne parfaitement.
Quelqu'un peut-il m'aider à résoudre ce problème?

+0

un certain temps progaurd supprime certaines classes du chemin de compilation, en particulier les projets de bibliothèque. – Ankit

+0

Des sons tels que Proguard ont peut-être supprimé le constructeur non paramétré par défaut de 'WasteCollectionAreasContainer'. Cette classe a-t-elle aussi un constructeur surchargé? Proguard supprime le constructeur par défaut * car * il y a une surcharge * et * il pense que le constructeur par défaut n'est utilisé nulle part - cela peut arriver parce que Proguard ne peut pas détecter que Jackson utilise réellement/nécessite un constructeur par défaut pour les POJOs lors de l'exécution. –

+0

MH - cela m'a mis dans la bonne direction pour corriger le problème - merci –

Répondre

1

Le message d'erreur

org.codehaus.jackson.map.JsonMappingException: No suitable constructor found for type 
    [simple type, class com.enterprisemk.android.bcw.bincollection.WasteCollectionAreasContainer]: 
    can not instantiate from JSON object (need to add/enable type information?) 

suggère que la bibliothèque Jackson tente de désérialiser votre classe en utilisant la réflexion, avec son nom d'origine et son constructeur annoté. ProGuard ne peut pas prévoir cela, il peut donc avoir supprimé ou renommé la classe et son constructeur. Vous avez probablement besoin de les préserver explicitement:

-keep class com.enterprisemk.android.bcw.bincollection.WasteCollectionAreasContainer { 
    <init>(java.util.List); 
} 

Il peut y avoir d'autres classes similaires/domaines/méthodes qui doivent être conservés pour les mêmes raisons.

+0

Eric - essentiellement, c'est ce que j'ai fait. Et tu avais raison, j'avais d'autres classes/champs/méthodes qui devaient être préservées de la même façon. Merci pour la réponse bang-on. –

2

Ajoutez ce qui suit à votre Proguard.config. Cela vous aidera à localiser le problème.

-verbose 
-dump class_files.txt 
-printseeds seeds.txt 
-printusage unused.txt 
-printmapping mapping.txt 

je suit dans mon fichier proguard-project.txt

Je crois que vous devriez utiliser proguard-android-optimize.txt, et non proguard-android.txt.

Pour être complet, merci Riley Hassell au Android Security Discussions pour les trucs.

+1

Les versions standard Ant/Eclipse contiennent déjà les options -print; vous devriez trouver les fichiers résultants dans le répertoire bin/proguard.L'étape d'optimisation de ProGuard traite le code un peu plus; cela ne résout généralement pas les problèmes de configuration. Pourtant, il est recommandé pour les meilleurs résultats. –

1

Une meilleure solution, au cas où quelqu'un d'autre a ce problème, est la suivante:

# keep anything annotated with @JsonCreator 
-keepclassmembers public class * { 
    @com.fasterxml.jackson.annotation.JsonCreator *; 
} 

qui maintient toute méthode annotée avec JsonCreator, qui est sans doute voulu faire dans ce cas. Si vous devez charger plusieurs classes, vous pouvez éviter d'avoir à spécifier chaque classe individuellement.

Questions connexes