Вопрос

Я создаю веб-приложение для платформы Facebook, используя GWT, и размещаю его на App Engine.

Я добавляю код проверки, который использует предоставленные параметры строки запроса в URL-адресе обратного вызова.GWT позволяет мне получать эти параметры, вызывая Window.Location.getParameterMap(), и возвращаемая карта является неизменяемой.

Я могу ошибаться, однако я думаю, что эта проблема не имеет ничего общего с FB, GWT или App Engine и больше связана с моим непониманием чего-то об объектах Map.

Я не думаю, что мой код пытается изменить предоставленную карту, но полученная ошибка, похоже, предполагает, что мой код пытается изменить неизменяемую карту.

Может кто-нибудь взглянуть и сообщить мне, где я изменяю неизменяемую карту?

Я бы предоставил трассировку стека, но не могу найти способ получить трассировку стека для отображения в журналах App Engine.

Заранее спасибо за любую помощь :-)

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

}
Это было полезно?

Решение

скопируйте Windows.Location.getParameterMap () в HashMap, и он будет работать:

Таким образом, вы отправляете новый HashMap > (Windows.Location.getParameterMap ()) через RPC, который работает.

Проблема в том, что unmodifiableMap не является сериализуемым для GWT. Я знаю, что у него есть маркер Serializable, но в GWT он работает немного по-другому. Большинство классов коллекций имеют собственную реализацию GWT, а некоторые не на 100% совместимы.

Другие советы

Я не вижу неизменяемых коллекций.

Ваш код довольно сложный. Если я правильно понял, то это должно быть эквивалентно. Я бы не использовал объекты Map.Entry, а TreeMap имеет удобный конструктор для ваших нужд. И, наконец, я бы предпочел цикл 'forall' над итератором.

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

При рефакторинге я обнаружил одну возможную ошибку: когда вы создаете отсортированную карту в своем коде, вы предполагаете, что все списки на карте не пусты. Таким образом, первый пустой список вызовет NPE в первом цикле.

Сделать System.out.println (fbQueryStringParams.getClass ()); в начале сообщения (или зарегистрируйте его или что-то еще, что вам нужно, чтобы увидеть, что это такое).

Если этот аргумент передается вам из системы, он, скорее всего, будет заключен в неизменяемую коллекцию, поскольку они не хотят, чтобы вы его изменяли.

Правильно ли я понял, что вы выполняете Window.Location.getParameterMap в своем клиентском коде и отправляете его на сервер при вызове RPC?В таком случае ...вопрос в том:это сериализуемый параметрParameterMap?На самом деле не все реализации поддерживаются в GWT.Таким образом, возможно, код вашего сервера даже не вызывается, но он выходит из строя, прежде чем сможет отправить запрос.Видели ли вы какое-либо предупреждение во время компиляции GWT?

Код, хотя реализацию можно очистить и действительно иметь NPE, НЕ изменяет предоставленный параметр Map или список значений Map.Так что проблема скорее всего где-то в другом.

Почему бы вам не запустить свое приложение в размещенном режиме (или в режиме разработки, как его называют в GWT 2.0)?

Дэйвид

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top