Pergunta

Eu estou construindo um aplicativo de plataforma facebook web usando GWT e hospedá-lo no App Engine.

Estou adicionando código de validação que usos fornecido consulta parâmetros de string na URL de retorno. GWT me permite obter estes parâmetros chamando Window.Location.getParameterMap () eo retornou Mapa é imutável.

Posso estar errado no entanto eu acho que este problema não tem nada a ver com FB, GWT ou App Engine especificamente e é mais baixo para o meu mal-entendido algo sobre Mapa objetos.

Eu não acho que as minhas tentativas de código para modificar o fornecido Map mas o erro que recebo parece sugerir que meu código está tentando modificar um Mapa imutável.

Alguém por favor pode dar uma olhada e deixe-me saber onde eu estou modificando um unmodifiable Mapa?

Eu iria fornecer um rastreamento de pilha, mas não consigo encontrar uma maneira de obter um rastreamento de pilha para que isso exibição em toras App Engine.

Agradecemos antecipadamente para toda e qualquer ajuda: -)

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

}
Foi útil?

Solução

copiar o Windows.Location.getParameterMap () em um HashMap e irá funcionar:

Assim que você enviar new HashMap> (Windows.Location.getParameterMap ()) sobre RPC que funciona.

O problema é que unmodifiableMap não é Serializable para GWT. Eu sei que ele tem um marcador Serializable, mas em GWT funciona um pouco diferente. A maioria das classes de coleção tem um costume implementação GWT e alguns não são 100% compatíveis.

Outras dicas

Não vejo qualquer cobrança não-modificáveis.

Seu código é muito complicado. Se eu entendi bem, então este deve ser equivalente. Eu não usaria objetos Map.Entry eo TreeMap tem um construtor acessível para as suas necessidades. E, finalmente, eu prefiro o loop 'forall' sobre o 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();
}

Durante a refatoração eu encontrei um possível bug: quando você cria o mapa ordenada em seu código, você assume, todas as listas do mapa não estão vazios. Assim, a primeira lista vazia fará com que uma NPE no primeiro loop.

Faça um System.out.println (fbQueryStringParams.getClass ()); no início da mensagem (ou registrá-lo ou o que você precisa para ser capaz de ver o que é).

Se esse argumento é passado para você a partir do sistema é muito provável embrulhado como uma coleção unmodifiable uma vez que eles não querem que você alterá-lo.

Será que eu entendi corretamente que você está fazendo um Window.Location.getParameterMap em seu código de cliente e enviá-lo para o servidor em uma chamada RPC? Nesse caso ... a pergunta é: é que serializável parameterMap? Nem todas as implementações são, de facto suportado em GWT. Portanto, pode ser que o código do servidor não é mesmo chamado, mas que deixa de funcionar antes que possa enviar o pedido. Você viu qualquer aviso durante a compilação GWT?

O código, embora a implementação pode ser limpo e, na verdade você pode ter um NPE, não modificando o parâmetro fornecido mapa ou na lista nos valores do mapa. Portanto, o problema é provavelmente em outro lugar.

Por que você não executar o aplicativo no modo hospedado (ou modo de desenvolvimento como eles chamam no GWT 2.0)?

David

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top