Pregunta

Estoy creando una aplicación web de plataforma de Facebook con GWT y la hospedé en App Engine.

Estoy agregando un código de validación que usa los parámetros de cadena de consulta provistos en la url de devolución de llamada. GWT me permite obtener estos parámetros llamando a Window.Location.getParameterMap () y el mapa devuelto es inmutable.

Puede que esté equivocado, sin embargo, creo que este problema no tiene nada que ver con FB, GWT o App Engine específicamente, y es más bien mi malentendido acerca de los objetos del Mapa.

No creo que mi código intente modificar el Mapa provisto, pero el error que recibo parece sugerir que mi código está intentando modificar un Mapa inmutable.

¿Alguien puede echar un vistazo y hacerme saber dónde estoy modificando un mapa no modificable?

Proporcionaría un seguimiento de pila, pero no puedo encontrar una manera de obtener un seguimiento de pila para que esto se muestre en los registros de App Engine.

Gracias de antemano por cualquier ayuda :-)

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

}
¿Fue útil?

Solución

copie Windows.Location.getParameterMap () en un HashMap y funcionará:

Entonces, envías un nuevo HashMap > (Windows.Location.getParameterMap ()) a través de RPC que funciona.

El problema es que unmodifiableMap no es serializable para GWT. Sé que tiene un marcador Serializable, pero en GWT funciona un poco diferente. La mayoría de las clases de recopilación tienen una implementación GWT personalizada y algunas no son 100% compatibles.

Otros consejos

No veo ninguna colección no modificable.

Tu código es bastante complicado. Si lo entendí bien, entonces esto debería ser equivalente. No usaría los objetos Map.Entry y TreeMap tiene un constructor útil para sus necesidades. Y finalmente, prefiero el bucle 'forall' sobre el iterador.

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

Al refactorizar encontré un posible error: cuando creas el mapa ordenado en tu código, asumís que todas las listas en el mapa no están vacías. Así que la primera lista vacía causará un NPE en el primer bucle.

Haz un System.out.println (fbQueryStringParams.getClass ()); al comienzo del mensaje (o regístrelo o lo que necesite para poder ver qué es).

Si ese argumento se te pasa desde el sistema, es muy probable que esté envuelto como una colección no modificable, ya que no quieren que lo alteres.

¿Comprendí correctamente que está haciendo un Window.Location.getParameterMap en su código de cliente y lo está enviando al servidor en una llamada RPC? En ese caso ... la pregunta es: ¿es ese ParameterMap serializable? No todas las implementaciones son compatibles con GWT. Por lo tanto, podría ser que ni siquiera se llame al código del servidor, sino que se bloquee antes de que pueda enviar la solicitud. ¿Viste alguna advertencia durante la compilación de GWT?

El código, aunque la implementación se puede limpiar y, de hecho, puede tener un NPE, NO está modificando el parámetro provisto Mapa o la Lista en los valores del Mapa. Así que el problema probablemente esté en otra parte.

¿Por qué no ejecuta su aplicación en modo hospedado (o modo de desarrollo como lo llaman en GWT 2.0)?

David

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top