Ошибка выглядит следующим образом: [com.ctc.wstx.exc.WstxLazyException] Недопустимый символьный объект: символ расширения (код 0x1a\r\n в [строке, столбце {неизвестный источник}]: [1,8035]
Это мой WebService в Springboot с его WebMethod, который получает массив полигонов, из которых одно из его полей содержит недопустимый символ:
@WebService(targetNamespace = "http://example.org.co/", name = "PolizaSoap")
@XmlSeeAlso({ObjectFactory.class})
public interface PolizaSoap {
@WebMethod(operationName = "Polizas", action = "http://example.org.co/Polizas")
@RequestWrapper(localName = "Polizas", targetNamespace = "http://example.org.co/", className = "com.example.Polizas")
@ResponseWrapper(localName = "PolizasResponse", targetNamespace = "http://example.org.co/", className = "com.example.PolizasResponse")
@WebResult(name = "PolizasResult", targetNamespace = "http://example.org.co/")
public ArrayOfPolizas Polizas(
@WebParam(name = "param1", targetNamespace = "http://example.org.co/")
java.lang.String param1,
@WebParam(name = "param2", targetNamespace = "http://example.org.co/")
java.lang.String param2,
@WebParam(name = "param3", targetNamespace = "http://example.org.co/")
java.lang.String param3
);
}
Я пробовал все виды перехватчиков (ClientInterceptor), фильтры (WebFilter), обработчики (SOAPHandler, HandlerInterceptor), и ни один из них не работал у меня, ошибка возникает мгновенно, и я не нашел способ получить ответ XML с недопустимым символом для можно модифицировать и так все работает.
Я начинаю думать, что это невозможно сделать, есть ли какая-либо другая альтернатива, которая не включает в себя просьбу поставщика ответов исправить это? Как я могу перехватить ответ XML с недопустимым символом (0x1a) без/до запуска исключения WebServiceException?
Обновлено: кто-нибудь знает, можно ли использовать FilterInputStream для исправления «XML», который поставляется с недопустимыми символами, прежде чем создавать исключение?
Я согласен с @kjhughes. Ваше внимание должно быть сосредоточено на обнаружении неверных данных, диагностике того, откуда они поступают, и их исправлении в источнике. Попытка восстановить неверные данные в конечном счете отрицательно сказывается на надежности системы. Если кто-то отправляет вам неверные данные, вам следует решить, как устранить свою зависимость от этого источника данных.
Я понимаю, что модифицировать мыльный отклик не лучшее решение, но возможно ли? Было ли это сделано раньше с успехом? Что касается обработки ошибок, если я заставлю WebMethod выдавать исключение типа WebServiceException, я смогу его перехватить. Но все же, хотелось бы узнать, есть ли полное решение.
@MichaelKay Я не могу устранить зависимость от источника данных, потому что это очень важная национальная организация для страховых компаний в моей стране. Должен быть способ.
Нет, не обязательно иметь способ использовать XML-инструменты для данных, отличных от XML.
@kjhughes, а почему я не могу перехватывать данные, отличные от XML, с помощью другой библиотеки или инструментов, чтобы получить данные?
Конечно, вы можете использовать инструменты, отличные от XML, для данных, отличных от XML, но ваш вопрос касается SOAP, протокола на основе XML. Пока вы используете библиотеки на основе SOAP или XML, вам не следует ожидать помощи от этих библиотек для данных, отличных от XML. Если вы хотите работать на уровне HTTP, предварительно обработать данные в виде текста и попытаться восстановить данные в соответствии с нашими рекомендациями, вы можете это сделать. Однако самое большее, чем я мог бы помочь вам пойти по этому нерекомендованному пути, — это предложить Как разобрать недопустимый (плохой / неправильно сформированный) XML?, особенно вариант №1.
Спасибо за ваш ответ, я посмотрю, что я могу сделать с этой информацией. Но этот вопрос все еще открыт для других решений...
Похоже, что в начале ответа есть начальный символ. Лучший способ удаления будет похож на то, как я сделал бы это в С#. Сначала используйте программу чтения, отличную от xml, например StringReader, чтобы прочитать ответ, а затем удалите первые символы. Затем передайте StringReader в качестве входных данных в XmlReader.
Мне не совсем понятно, вызываете ли вы службу SOAP и получаете неверный ответ, или кто-то вызывает вашу службу SOAP и отправляет неверный запрос. Для последнего вы можете перехватить HTTP-запрос с помощью ServletFilter и манипулировать запросом как обычным текстом. Если вы вызываете службу, не находящуюся под вашим контролем, вы можете использовать HTTP-запрос низкого уровня для вызова службы SOAP без каких-либо библиотек SOAP. Затем вы получаете ответ в виде обычного текста, можете исправить ошибку, самостоятельно проанализировать XML и извлечь полезную нагрузку. Что-то вроде SoapUI можно использовать, чтобы показать вам низкоуровневый HTTP-запрос для вызова службы.
@vanje Я вызываю внешнюю службу SOAP, проблема в том, что когда я получаю ответ, там есть недопустимый символ. У вас есть пример того, как его перехватить?
@jdwengn Я пытался перехватить ответ, но не смог.
Если вам нужно обрабатывать данные в формате, отличном от XML, то, конечно, это возможно. Просто не пытайтесь использовать XML-инструменты для работы.
@Olivetz: Вот пример вызова службы SOAP без библиотек SOAP: technology.amis.nl/soa/…
@vanje выглядит хорошо! Я попробую этот подход
@vanje Я пробовал, вроде работает!!!!!!!!
@vanje Если хотите, создайте формальный ответ, и я отмечу вас как правильный ответ.
Если вы вызываете внешнюю службу SOAP и получаете недопустимый XML в качестве ответа, и нет никаких шансов заставить провайдера исправить свою ошибку, то единственный вариант, который у вас есть, — это отказаться от стандартных библиотек SOAP и вызвать службу, используя низкоуровневую HTTP-функции, обработайте ответ как обычный текст и исправьте ошибку, а затем самостоятельно проанализируйте исправленный XML.
Вот пример вызова службы SOAP без библиотек SOAP (взято из https://technology.amis.nl/soa/how-to-call-a-call-a-webservice-directly-from-java-without -веб-сервис-библиотека/ )
public String getWeather(String city) throws MalformedURLException, IOException {
//Code to make a webservice HTTP request
String responseString = "";
String outputString = "";
String wsURL = "http://www.deeptraining.com/webservices/weather.asmx";
URL url = new URL(wsURL);
URLConnection connection = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection)connection;
ByteArrayOutputStream bout = new ByteArrayOutputStream();
String xmlInput =
" <soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:web=\"http://litwinconsulting.com/webservices/\">\n" +
" <soapenv:Header/>\n" +
" <soapenv:Body>\n" +
" <web:GetWeather>\n" +
" <!--Optional:-->\n" +
" <web:City>" + city + "</web:City>\n" +
" </web:GetWeather>\n" +
" </soapenv:Body>\n" +
" </soapenv:Envelope>";
byte[] buffer = new byte[xmlInput.length()];
buffer = xmlInput.getBytes();
bout.write(buffer);
byte[] b = bout.toByteArray();
String SOAPAction = "http://litwinconsulting.com/webservices/GetWeather";
// Set the appropriate HTTP parameters.
httpConn.setRequestProperty("Content-Length",
String.valueOf(b.length));
httpConn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
httpConn.setRequestProperty("SOAPAction", SOAPAction);
httpConn.setRequestMethod("POST");
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
OutputStream out = httpConn.getOutputStream();
//Write the content of the request to the outputstream of the HTTP Connection.
out.write(b);
out.close();
//Ready with sending the request.
//Read the response.
InputStreamReader isr =
new InputStreamReader(httpConn.getInputStream());
BufferedReader in = new BufferedReader(isr);
//Write the SOAP message response to a String.
while ((responseString = in.readLine()) != null) {
outputString = outputString + responseString;
}
//****************************************************************************************************
// Here you have the response as plain text and you can apply your corrections
//****************************************************************************************************
//Parse the String output to a org.w3c.dom.Document and be able to reach every node with the org.w3c.dom API.
Document document = parseXmlFile(outputString);
NodeList nodeLst = document.getElementsByTagName("GetWeatherResult");
String weatherResult = nodeLst.item(0).getTextContent();
System.out.println("Weather: " + weatherResult);
return weatherResult;
}
Если протокол требует, чтобы запрос был XML, а то, что получает ваша служба, не является XML, то ваш единственный способ действий — вернуть ошибку, указывающую, что запрос был неправильно сформирован. Вы должны стараться больше ничего не делать.