java.util.Collections $ UnmodifiableMap проблема: код включен - PullRequest
0 голосов
/ 26 ноября 2009

Я создаю веб-приложение на платформе 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();

}

Ответы [ 4 ]

2 голосов
/ 27 ноября 2009

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

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

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

1 голос
/ 26 ноября 2009

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

Ваш код довольно сложный. Если я правильно понял, то это должно быть эквивалентно. Я бы не использовал объекты 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 в первом цикле.

0 голосов
/ 27 ноября 2009

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

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

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

David

0 голосов
/ 26 ноября 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...