Правильный способ декодирования ответа в Java-клиенте Dojo cometd
Вопрос
Я хочу передавать произвольные объекты Java, закодированные в XMLEncoded, туда и обратно, используя каналы Dojo cometd, и у меня проблема с правильным декодированием полезной нагрузки.
Чтобы сделать это, у меня есть этот метод отправки в урезанной версии демонстрационной программы клиента чата:
private void send(String string) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("intArray", new int[] {1});
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XMLEncoder xmlEncoder = new XMLEncoder(baos);
xmlEncoder.writeObject(map);
xmlEncoder.close();
Map<String, Object> encodedMap = new HashMap<String, Object>();
try {
String encoded = baos.toString("UTF-8");
encodedMap.put("xmlpayload", encoded);
} catch (Exception e) {
throw new RuntimeException("could not use UTF-8", e);
}
bayreuxClient.publish("/prototype/a", encodedMap, String.valueOf(System.currentTimeMillis()));
}
Который на данный момент создает фрагмент XML, сведенный к потоку байтов в кодировке UTF-8 (я знаю, что мне также нужно позаботиться о кодировке, но сейчас это не проблема).
Прослушиватель сообщений, принимающий это, выглядит следующим образом:
listener = new MessageListener() {
@Override
public void deliver(Client fromClient, Client toClient, Message msg) {
if (!_connected) {
_connected = true;
synchronized (this) {
this.notify();
}
}
Object data = msg.getData();
if (data instanceof Map) {
Map map = (Map) data;
Object rawPayload = map.get("xmlpayload");
if (rawPayload instanceof String) {
System.out.println("xmlpayload = " + rawPayload);
ByteArrayInputStream bais;
try {
String xmlPayload = ((String) rawPayload).replaceAll(">",">").replaceAll("<", "<").replaceAll("&","&");
bais = new ByteArrayInputStream(xmlPayload.getBytes("UTF-8"));
XMLDecoder xmlDecoder = new XMLDecoder(bais);
Object o = xmlDecoder.readObject();
xmlDecoder.close();
System.out.println(">> decoded payload=" + o + ", class=" + o.getClass());
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("no UTF-8", e);
}
}
}
}
};
address = new Address("localhost", 8080);
bayreuxClient = new BayeuxClient(httpClient, address, "/cometd/cometd");
bayreuxClient.addListener(listener);
Как вы можете видеть, методом проб и ошибок я обнаружил, что отправленная строка защищена символами less than, greater than и ampersand, которые я затем снимаю с защиты и вызываю XMLDecode.
Результатом является:
xmlpayload = <?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0_16" class="java.beans.XMLDecoder">
<object class="java.util.HashMap">
<void method="put">
<string>intArray</string>
<array class="int" length="1">
<void index="0">
<int>1</int>
</void>
</array>
</void>
</object>
</java>
>> decoded payload={intArray=[I@2f1e75}, class=class java.util.HashMap
так что это обратимо.Мои эксперименты с помещением этих символов внутри строковых объектов, которые были XMLEncoded / XMLDecoded, не были хорошими - они не были обработаны дважды, - поэтому мое грубое декодирование также повлияло на них.
Вопрос в том,:Что такое надлежащий способ декодирования этих строк?Есть ли библиотека JSON, которую мне нужно использовать вместо моего быстрого и грязного кода?Мог ли я обнаружить ошибку в клиентской библиотеке Java для cometd?
(Примечание:Для этого эксперимента я использовал библиотеки cometd-1.0.0rc0).
Редактировать:Оказалось, что связь произошла через другое развертывание на том же веб-сервере, чем тот, на котором я мысль позаботился о коммуникациях cometd, и это развертывание содержало filter.json, который выполнял защиту XML.
http://groups.google.com/group/cometd-users/browse_thread/thread/6fbdaae669e5f9d3
Другими словами, проблема с конфигурацией вне моего кода.Надеемся, что пересмотренное развертывание исправит эту проблему.
Решение
Лучшей библиотекой для удаления XML является Apache Commons Lang,
StringEscapeUtils.unescapeXml();
Похоже, это ошибка в используемом вами Java-клиенте Bayeux.Его кодирование / декодирование не являются симметричными.Я собирался им воспользоваться.Теперь я дважды подумаю :)