Уже поздно, но на случай, если кто-то наткнется на это.
Изменить:
Я занимаюсь этим уже два месяца и, наконец, нашел жизнеспособное решение вышеуказанной проблемы.
Эта проблема возникает из-за того, что иногда Bugzilla :: Webservice в ответ на удаленный вызов процедуры отправляет недопустимый символ в ответе XML.
Когда XML-RPC Apache пытается проанализировать этот ответ, он выдает следующую ошибку:
XmlRpcClientException: обнаружен недопустимый символ XML (Unicode: 0x8)
Чтобы решить эту проблему, необходимо расширить клиент Apache XML-RPC, чтобы очистить ответ от недопустимых символов XML, прежде чем пытаться его проанализировать.
Найдите исходный код apache-xmlrpc как проект Eclipse здесь. (Импортируйте этот проект вместо файлов jar)
Для этого нам сначала нужно расширить класс BufferedReader
, чтобы заменить любой недопустимый символ XML перед его возвратом.
Итак, добавьте /apache-xmlrpc-3.1.3-src/client/src/main/java/org/apache/xmlrpc/client/util/XMLBufferredReader.java
, например:
package org.apache.xmlrpc.client.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
/**
* @author Ahmed Akhtar
*
*/
public class XMLBufferredReader extends BufferedReader
{
/**
* @param in
*/
public XMLBufferredReader(Reader in)
{
super(in);
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException
{
int ret = super.read(cbuf, off, len);
for(int i = 0; i < ret; i++)
{
char current = cbuf[i];
if(!((current == 0x9) ||
(current == 0xA) ||
(current == 0xD) ||
((current >= 0x20) && (current <= 0xD7FF)) ||
((current >= 0xE000) && (current <= 0xFFFD)) ||
((current >= 0x10000) && (current <= 0x10FFFF))))
{
cbuf[i] = 'r';
}
}
return ret;
}
}
Позже нам нужно отправить расширенный XMLBufferedReader
в InputSource
метода parse
.
Функцию readResponse
в файле /apache-xmlrpc-3.1.3-src/client/src/main/java/org/apache/xmlrpc/client/XmlRpcStreamTransport.java
необходимо изменить на:
protected Object readResponse(XmlRpcStreamRequestConfig pConfig, InputStream pStream) throws XmlRpcException
{
BufferedReader in = new XMLBufferredReader(new BufferedReader(new InputStreamReader(pStream, StandardCharsets.UTF_8)));
InputSource isource = new InputSource(in);
XMLReader xr = newXMLReader();
XmlRpcResponseParser xp;
try {
xp = new XmlRpcResponseParser(pConfig, getClient().getTypeFactory());
xr.setContentHandler(xp);
xr.parse(isource);
} catch (SAXException e) {
throw new XmlRpcClientException("Failed to parse server's response: " + e.getMessage(), e);
} catch (IOException e) {
throw new XmlRpcClientException("Failed to read server's response: " + e.getMessage(), e);
}
if (xp.isSuccess()) {
return xp.getResult();
}
Throwable t = xp.getErrorCause();
if (t == null) {
throw new XmlRpcException(xp.getErrorCode(), xp.getErrorMessage());
}
if (t instanceof XmlRpcException) {
throw (XmlRpcException) t;
}
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
throw new XmlRpcException(xp.getErrorCode(), xp.getErrorMessage(), t);
}
После этого расширения для клиента Apache XML-RPC все должно работать нормально.
Примечание. Остальная часть этого сообщения - это исходное решение, которое я опубликовал, и это обходной путь в случае, если кто-то не хочет расширять клиент Apache XML-RPC.
Старое сообщение:
Если вы используете Bugzilla :: Служебная функция Webservice :: Bug :: search с некоторыми параметрами offset
и limit
вместе с критериями поиска.
Вы получите это исключение для некоторых конкретных значений, скажем, x
из offset
и y
из limit
, которые вы можете узнать, запустив в режиме отладки.
Теперь вызовите функцию search
, сохранив x
как смещение, а 1
как limit
, а затем выполните цикл и увеличивайте x
, пока не достигнет значения x + y
как смещения, сохраняя limit
как 1
.
Таким образом, вы будете извлекать ошибки по очереди и, работая в режиме отладки, вы можете определить точную ошибку, которая вызывает исключение.
Для x = 21900
и y = 100
сделайте что-нибудь вроде:
for(int i = 21900; i <= 22000; i++)
{
result = ws.search(searchCriteria, i, 1);
}
Запустив это в режиме отладки, я обнаружил, что фактическая offset
, вызывающая ошибку, была 21963
, поэтому я написал код, чтобы избежать этой конкретной ошибки:
if(offset != 21900)
{
result = obj.search(productNames, offset, limit);
bugsObj = (Object[])result.get("bugs");
}
else
{
result = obj.search(productNames, 21900, 63);
Object[] bugsObj1 = (Object[])result.get("bugs");
result = obj.search(productNames, 21964, 36);
Object[] bugsObj2 = (Object[])result.get("bugs");
bugsObj = new Object[bugsObj1.length+bugsObj2.length];
for(int i = 0; i < bugsObj1.length + bugsObj2.length; i++)
{
bugsObj[i] = i < bugsObj1.length ? bugsObj1[i] : bugsObj2[i - bugsObj1.length];
}
}
person
Ahmed Akhtar
schedule
29.04.2016