Question

Je construis une application Web pour plate-forme facebook en utilisant GWT et l'héberge sur App Engine.

J'ajoute un code de validation qui utilise les paramètres de chaîne de requête fournis dans l'URL de rappel. GWT me permet d’obtenir ces paramètres en appelant Window.Location.getParameterMap () et la carte renvoyée est immuable.

Je me trompe peut-être, mais je pense que ce problème n'a rien à voir avec FB, GWT ou App Engine en particulier, mais plutôt parce que j'ai mal compris quelque chose au sujet des objets Map.

Je ne pense pas que mon code tente de modifier la carte fournie, mais l'erreur que je reçois semble suggérer que mon code tente de modifier une carte immuable.

Quelqu'un peut-il s'il vous plaît jeter un coup d'oeil et laissez-moi savoir où je modifie une carte non modifiable?

Je voudrais fournir une trace de pile, mais je ne trouve pas le moyen d'obtenir une trace de pile à afficher dans les journaux d'App Engine.

Merci d'avance pour toute aide: -)

/**
 * Validation Test
 * To generate the signature for these arguments:
 * 1. Remove the fb_sig key and value pair.
 * 2. Remove the "fb_sig_" prefix from all of the keys.
 * 3. Sort the array alphabetically by key.
 * 4. Concatenate all key/value pairs together in the format "k=v".
 * 5. Append your secret key.
 * 6. Take the md5 hash of the whole string.
 * @param fbQueryStringParams
 * @return String
 */
public String test(Map<String,List<java.lang.String>> fbQueryStringParams) {

    String appSecret = TinyFBClient.APP_SECRET;
    String fbSig = fbQueryStringParams.get("fb_sig").get(0);
    StringBuilder sb = new StringBuilder();     
    TreeMap<String,String> sortedMap = new TreeMap<String,String>();

    // Get a Set view of the Map of query string parameters.
    Set<Map.Entry<String,List<java.lang.String>>> mapEntries = fbQueryStringParams.entrySet();

    // Iterate through the Set view, inserting into a SortedMap all Map.Entry's
    // that do not have a Key value of "fb_sig".
    Iterator<Map.Entry<String,List<java.lang.String>>> i = mapEntries.iterator();
    while(i.hasNext()) {

        Map.Entry<String,List<java.lang.String>> mapEntry = i.next();

        if(!mapEntry.getKey().equals("fb_sig")) { // 1. Remove the fb_sig key and value pair.

            sortedMap.put(mapEntry.getKey(),mapEntry.getValue().get(0)); // 3. Sort the array alphabetically by key.

        }

    }

    // Get a Set view of the Map of alphabetically sorted Map.Entry objects.
    Set<Map.Entry<String,String>> sortedMapEntries = sortedMap.entrySet();

    // Iterate through the Set view, appending the concatenated key's and value's
    // to a StringBuilder object.
    Iterator<Map.Entry<String,String>> ii = sortedMapEntries.iterator();
    while(ii.hasNext()) {

        Map.Entry<String,String> mapEntry = ii.next();

        // 4. Concatenate all key/value pairs together in the format "k=v".
        sb.append(mapEntry.getKey().replaceAll("fb_sig_","")); // 2. Remove the "fb_sig_" prefix from all of the keys.
        sb.append("=");
        sb.append(mapEntry.getValue());

    }

    sb.append(appSecret); // 5. Append your secret key.

    String md5 = DigestUtils.md5Hex(sb.toString()); // 6. Take the md5 hash of the whole string.

    // Build and return an output String for display.
    StringBuilder output = new StringBuilder();
    output.append("fbSig = "+fbSig);
    output.append("<br/>");
    output.append("md5 = "+md5);
    return output.toString();

}
Était-ce utile?

La solution

copiez Windows.Location.getParameterMap () dans un HashMap et cela fonctionnera:

Vous envoyez donc un nouveau HashMap > (Windows.Location.getParameterMap ()) via RPC qui fonctionne.

Le problème est que unmodifiableMap n'est pas sérialisable pour GWT. Je sais qu'il a un marqueur Serializable, mais dans GWT cela fonctionne un peu différemment. La plupart des classes de collection ont une implémentation GWT personnalisée et certaines ne sont pas compatibles à 100%.

Autres conseils

Je ne vois aucune collection non modifiable.

Votre code est assez compliqué. Si j'ai bien compris, alors cela devrait être équivalent. Je n'utiliserais pas les objets Map.Entry et TreeMap a un constructeur pratique pour vos besoins. Et enfin, je préférerais la boucle "forall" à l'itérateur.

public String test(Map<String, List<java.lang.String>> fbQueryStringParams) {
    String appSecret = TinyFBClient.APP_SECRET;
    String fbSig = fbQueryStringParams.get("fb_sig").get(0);
    StringBuilder sb = new StringBuilder();
    TreeMap<String, List<String>> sortedMap = new TreeMap<String, List<String>>(fbQueryStringParams);
    sortedMap.remove("fbSig"); // remove the unwanted entry

    for (String key, sortedMap.keySet()) {
        List<String> values = sortedMap.get(key);
        String printableKey = key.replaceAll("fb_sig_", ""));
        String value = "EMPTY LIST";

        if (!values.isEmpty()) {
            // This could have been your problem, you always
            // assume, all lists in the map are not empty
            value = values.get(0);
        }

        sb.append(String.format("%s=%s", printableKey, value);
    }

    sb.append(appSecret);
    String md5 = DigestUtils.md5Hex(sb.toString());

    // Build and return an output String for display.
    StringBuilder output = new StringBuilder();
    output.append("fbSig = " + fbSig);
    output.append("<br/>");
    output.append("md5 = " + md5);
    return output.toString();
}

Lors du refactoring, j’ai trouvé un bug possible: lorsque vous créez la carte triée dans votre code, vous supposez que toutes les listes de la carte ne sont pas vides. Ainsi, la première liste vide entraînera un NPE dans la première boucle.

Effectuez System.out.println (fbQueryStringParams.getClass ()); au début du message (ou connectez-le ou tout ce dont vous avez besoin pour voir ce que c'est).

Si cet argument vous est transmis par le système, il est très probablement encapsulé comme une collection non modifiable car il ne veut pas que vous le changiez.

Ai-je bien compris que vous faites un Window.Location.getParameterMap dans votre code client et que vous l'envoyez au serveur dans un appel RPC? Dans ce cas ... la question est: est-ce ParameterMap sérialisable? Toutes les implémentations ne sont en fait pas prises en charge dans GWT. Il se peut donc que votre code serveur ne soit même pas appelé, mais qu'il se bloque avant de pouvoir envoyer la demande. Avez-vous vu un avertissement lors de la compilation de GWT?

Le code, bien que l'implémentation puisse être nettoyée et que vous puissiez disposer d'un NPE, NE modifie PAS le paramètre fourni Map ou la liste dans les valeurs Map. Le problème est donc probablement ailleurs.

Pourquoi n'exécutez-vous pas votre application en mode hébergé (ou en mode de développement comme ils l'appellent dans GWT 2.0)?

David

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top