Domanda

Sto creando un'app Web della piattaforma Facebook utilizzando GWT e l'hosting su App Engine.

Sto aggiungendo il codice di convalida che utilizza i parametri della stringa di query forniti nell'URL di callback. GWT mi permette di ottenere questi parametri chiamando Window.Location.getParameterMap () e la mappa restituita è immutabile.

Potrei sbagliarmi, tuttavia penso che questo problema non abbia nulla a che fare con FB, GWT o App Engine in particolare ed è più che altro dovuto al mio malinteso riguardo agli oggetti Map.

Non penso che il mio codice tenti di modificare la mappa fornita, ma l'errore che ho visualizzato sembra suggerire che il mio codice sta provando a modificare una mappa immutabile.

Qualcuno può dare un'occhiata e farmi sapere dove sto modificando una mappa non modificabile?

Fornirei una traccia dello stack ma non riesco a trovare un modo per ottenere una traccia dello stack da visualizzare nei registri di App Engine.

Grazie in anticipo per qualsiasi aiuto :-)

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

}
È stato utile?

Soluzione

copia Windows.Location.getParameterMap () in una HashMap e funzionerà:

Quindi invii il nuovo HashMap > (Windows.Location.getParameterMap ()) su RPC che funziona.

Il problema è che unmodifiableMap non è serializzabile per GWT. So che ha un marcatore serializzabile, ma in GWT funziona un po 'diverso. Molte classi di raccolta hanno un'implementazione GWT personalizzata e alcune non sono compatibili al 100%.

Altri suggerimenti

Non vedo raccolte non modificabili.

Il tuo codice è piuttosto complicato. Se ho capito bene, allora dovrebbe essere equivalente. Non userei gli oggetti Map.Entry e TreeMap ha un pratico costruttore per le tue esigenze. E infine, preferirei il ciclo "forall" rispetto all'iteratore.

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

Durante il refactoring ho trovato un possibile bug: quando crei la mappa ordinata nel tuo codice, supponi che tutti gli elenchi nella mappa non siano vuoti. Quindi il primo elenco vuoto provocherà un NPE nel primo ciclo.

Esegui un System.out.println (fbQueryStringParams.getClass ()); all'inizio del messaggio (o registralo o qualsiasi altra cosa sia necessaria per poter vedere di cosa si tratta).

Se tale argomento ti viene passato dal sistema, molto probabilmente viene racchiuso in una raccolta non modificabile poiché non vogliono che tu lo modifichi.

Ho capito bene che stai facendo una Window.Location.getParameterMap nel tuo codice client e lo stai inviando al server in una chiamata RPC? In tal caso ... la domanda è: ParameterMap è serializzabile? Non tutte le implementazioni sono infatti supportate in GWT. Quindi potrebbe essere solo che il tuo codice server non sia nemmeno chiamato ma che si arresti in modo anomalo prima di poter inviare la richiesta. Hai visto degli avvisi durante la compilazione GWT?

Il codice, sebbene l'implementazione possa essere ripulita e in effetti è possibile avere un NPE, NON sta modificando il parametro fornito Mappa o l'elenco nei valori Mappa. Quindi il problema è probabilmente altrove.

Perché non esegui l'applicazione in modalità ospitata (o in modalità di sviluppo come la chiamano in GWT 2.0)?

David

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top