Frage

Ich baue einen Facebook-Plattform Web-App mit GWT und auf App Engine-Hosting.

Ich füge Validierungscode, die Query-String-Parameter in der Callback-URL geliefert verwendet. GWT ermöglicht es mir, um diese Parameter zu erhalten, indem Aufruf Window.Location.getParameterMap () und der zurückgegebene Karte ist unveränderlich.

ich falsch sein kann, aber ich denke, das Problem hat nichts mit FB, GWT oder App Engine speziell und ist bis zu meinem Missverständnis etwas über Kartenobjekte zu tun.

Ich glaube nicht, dass mein Code versucht, die mitgelieferte Karte zu ändern, aber der Fehler ich scheint erhalten zu legen nahe, dass mein Code versucht, eine unveränderliche Karte zu ändern.

Kann jemand bitte werfen Sie einen Blick und lassen Sie mich wissen, wo ich eine unveränderbare Karte bin modifizieren?

Ich würde einen Stack-Trace liefern, aber ich kann nicht einen Weg finden, ein Stack-Trace erhalten für diese in App Engine-Protokollen angezeigt werden.

Vielen Dank im Voraus für jede und alle Hilfe: -)

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

}
War es hilfreich?

Lösung

Kopieren Sie die Windows.Location.getParameterMap () in einer HashMap und es wird funktionieren:

So können Sie neue HashMap senden> (Windows.Location.getParameterMap ()) über RPC, das funktioniert.

Das Problem ist, dass unmodifiableMap nicht Serializable für GWT ist. Ich weiß, dass es einen Serializable Marker hat, aber in GWT funktioniert es ein wenig anders. Die meisten Collection-Klassen haben eine benutzerdefinierte GWT Implementierung und einige sind nicht zu 100% kompatibel.

Andere Tipps

Ich sehe keine unveränderbaren Sammlungen.

Der Code ist ziemlich kompliziert. Wenn ich es richtig verstanden hat, dann sollte dies gleichwertig sein. Ich würde nicht Map.Entry Objekte und die TreeMap hat ein handliches Konstruktor für Ihre Bedürfnisse verwenden. Und schließlich, ich würde es vorziehen, die ‚forall‘ Schleife über den Iterator.

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

Während Refactoring ich einen möglichen Fehler gefunden: Wenn Sie die sortierte Karte in Ihrem Code erstellen, können Sie davon ausgehen, alle Listen in der Karte nicht leer ist. So ist die erste leere Liste wird eine NPE in der ersten Schleife führen.

Starten Sie eine System.out.println (fbQueryStringParams.getClass ()); am Anfang der Nachricht (oder es dich einzuloggen oder was auch immer Sie in der Lage sein muß, um zu sehen, was es ist).

Wenn das Argument Sie aus dem System geleitet wird, ist es sehr wahrscheinlich als unveränderbare Sammlung gewickelt ist, da sie nicht wollen Sie es zu ändern.

Habe ich es richtig verstehe, dass Sie einen Window.Location.getParameterMap in Ihrem Client-Code tun, und sie an den Server in einem RPC-Aufruf zu senden? In diesem Fall ... die Frage ist: ist, dass parameterMap serializable? Nicht alle Implementierungen sind in der Tat in GWT unterstützt. So könnte es nur sein, dass Ihr Server-Code nicht einmal genannt wird, sondern dass es abstürzt, bevor die Anforderung senden kann. Hast du irgendeine Warnung bei GWT Kompilation?

Der Code, obwohl die Implementierung bis gereinigt werden kann und in der Tat können Sie eine NPE haben, ist nicht die angegebenen Parameter Karte oder die Liste in der Karte Werte ändern. Das Problem ist also wahrscheinlich woanders.

Warum nicht Sie führen Sie Ihre Anwendung in Host-Modus (oder Entwicklungsmodus, wie sie es in GWT nennen 2.0)?

David

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top