Как передать "Null" (настоящую фамилию!) На веб-службу SOAP в ActionScript 3?
У нас есть сотрудник, чья фамилия Null. Приложение для поиска сотрудников убивается, когда эта фамилия используется в качестве условия поиска (что часто случается довольно часто). Полученная ошибка (спасибо Fiddler!):
<soapenv:Fault>
<faultcode>soapenv:Server.userException</faultcode>
<faultstring>coldfusion.xml.rpc.CFCInvocationException: [coldfusion.runtime.MissingArgumentException : The SEARCHSTRING parameter to the getFacultyNames function is required but was not passed in.]</faultstring>
Симпатичный, да?
Тип параметра string
.
Я использую:
- WSDL (SOAP).
- Flex 3.5
- ActionScript 3
- ColdFusion 8
Обратите внимание, что ошибка не возникает при вызове веб-службы как объекта со страницы ColdFusion.
Ответы
Ответ 1
Отслеживание вниз
Сначала я думал, что это ошибка принуждения, в которой null
принуждалось к "null"
и проходил тест "null" == null
. Не это. Я был близок, но так очень, очень неправильно. Извините за это!
С тех пор я сделал много прокручивание на wonderfl.net и прослеживая код в mx.rpc.xml.*
. На строке 1795 XMLEncoder
(в источнике 3.5) в setValue
все XMLEncoding сводится к
currentChild.appendChild(xmlSpecialCharsFilter(Object(value)));
который по существу совпадает с:
currentChild.appendChild("null");
Этот код, согласно моей оригинальной скрипке, возвращает пустой элемент XML. Но почему?
Причина
По словам комментатора Justin Mclean о сообщении об ошибке FLEX-33664, следующий виновник (см. последние два теста в моем скрипта, которые подтверждают это):
var thisIsNotNull:XML = <root>null</root>;
if(thisIsNotNull == null){
// always branches here, as (thisIsNotNull == null) strangely returns true
// despite the fact that thisIsNotNull is a valid instance of type XML
}
Когда currentChild.appendChild
передается строка "null"
, она сначала преобразует ее в корневой элемент XML с текстом null
, а затем проверяет этот элемент на нулевом литерале. Это слабый тест на равенство, поэтому либо содержащий XML-символ принуждается к нулевому типу, либо нулевой тип принуждается к корневому элементу xml, содержащему строку "null", и тест проходит там, где он, возможно, должен завершиться ошибкой. Одно исправление может заключаться в том, чтобы всегда использовать строгое равенство при проверке XML (или что-нибудь, действительно) для "nullness."
Решение
Единственное разумное обходное решение, которое я могу придумать, не исправляя эту ошибку в каждой проклятой версии ActionScript, - это проверить поля для "null" и избежать их как значений CDATA.
Значения CDATA являются наиболее подходящим способом для изменения целочисленного текстового значения, которое в противном случае могло бы вызвать проблемы с кодированием/декодированием. Hex-кодирование, например, предназначено для отдельных символов. Значения CDATA предпочтительнее, если вы избегаете всего текста элемента. Самой большой причиной этого является то, что он поддерживает читаемость человека.
Ответ 2
На примечание xkcd, веб-сайт Bobby Tables имеет хорошие рекомендации по недопущению неправильной интерпретации пользовательских данных (в данном случае строки "Null" ) в SQL-запросах на разных языках, включая ColdFusion.
Неясно, что это источник проблемы, и учитывая решение, указанное в комментарии к первому ответу (вложение параметров в структуру), кажется вероятным, что это было что-то еще.
Ответ 3
Проблема может быть в коде Flex SOAP. Попробуйте расширить SOAP-кодировщик в приложении Flex и отладить программу, чтобы увидеть, как обрабатывается нулевое значение. Я предполагаю, что он прошел как NaN (не номер). Это когда-нибудь испортит процесс отмены сообщений SOAP (особенно в JBoss 5 server...). Я помню, как расширил SOAP-кодер и выполнил явную проверку того, как обрабатывается NaN.
(На стороне примечания, вы ожидаете сделать что-то полезное, если идентификатор сотрудника - Null, это не проблема проверки? Возможно, я ошибаюсь, так как я почти не знаю этого требования...)
Ответ 4
@doc_180 имел правильную концепцию, за исключением того, что он фокусировался на числах, тогда как исходный плакат имел проблемы со строками.
Решение состоит в изменении файла mx.rpc.xml.XMLEncoder
. Это строка 121
if (content != null)
result += content;
[Я просмотрел SDK Flex 4.5.1; номера строк могут отличаться в других версиях]
В принципе, проверка не выполняется, потому что "контент имеет значение NULL", и поэтому ваш аргумент не добавляется в исходящий пакет SOAP; что приводит к ошибке отсутствия параметра.
Вы должны расширить этот класс, чтобы удалить проверку. Затем происходит большой снежный ком по цепочке, изменяя SOAPEncoder, чтобы использовать измененный XMLEncoder, а затем изменяя операцию для использования вашего модифицированного SOAPEncoder, а затем moidfying WebService для использования вашего альтернативного класса Operation.
Я потратил несколько часов на это, но мне нужно двигаться дальше. Вероятно, это займет день или два.
Возможно, вы сможете просто исправить строку XMLEncoder и выполнить некоторые исправления для обезьян, чтобы использовать свой собственный класс.
Я также добавлю, что если вы переключитесь на использование RemoteObject/AMF с ColdFusion, нуль передается без проблем.
Обновление за 11/16/2012:
У меня есть еще одно последнее дополнение к моему последнему комментарию о RemoteObject/AMF. Если вы используете CF10; то свойства с нулевым значением для объекта удаляются из объекта на стороне сервера. Таким образом, перед доступом к нему необходимо проверить наличие свойств или получить ошибку времени выполнения. Проверьте следующее:
<cfif (structKeyExists(arguments.myObject,'propertyName')>
<!--- no property code --->
<cfelse>
<!--- handle property normally --->
</cfif>
Это изменение в поведении от CF9; где нулевые свойства превратятся в пустые строки.
Редактировать 12/6/2013
Поскольку возник вопрос о том, как обрабатываются нули, это быстрое примерное приложение, демонстрирующее, как строка "null" будет относиться к зарезервированному слову null.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" initialize="application1_initializeHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function application1_initializeHandler(event:FlexEvent):void
{
var s :String = "null";
if(s != null){
trace('null string is not equal to null reserved word using the != condition');
} else {
trace('null string is equal to null reserved word using the != condition');
}
if(s == null){
trace('null string is equal to null reserved word using the == condition');
} else {
trace('null string is not equal to null reserved word using the == condition');
}
if(s === null){
trace('null string is equal to null reserved word using the === condition');
} else {
trace('null string is not equal to null reserved word using the === condition');
}
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
</s:Application>
Выход трассировки:
нулевая строка не равна нулевому зарезервированному слову, используя условие: = условие
null string не равно нулевому зарезервированному слову, используя условие ==
null string не равно нулевому зарезервированному слову, используя условие ===
Ответ 5
Переведите все символы в их эквиваленты с шестью сущностями. В этом случае Null
будет преобразован в E;KC;C;
Ответ 6
Строка значения null
в ActionScript даст строку "NULL"
. Мое подозрение в том, что кто-то решил, что это хорошая идея, чтобы декодировать строку "NULL"
как null
, вызывая обрыв, который вы видите здесь, вероятно, потому, что они проходили объекты null
и получали строки в в базе данных, когда они этого не хотели (так что обязательно проверяйте эту ошибку).
Ответ 7
В качестве взлома вы можете подумать о специальной обработке на стороне клиента, конвертируя строку "Null" в то, что никогда не произойдет, например, XXNULLXX и преобразование обратно на сервер.
Это не очень, но это может решить проблему для такого граничного случая.
Ответ 8
Ну, я полагаю, что реализация Flex в SOAP Encoder, по-видимому, неправильно упорядочивает нулевые значения. Сериализация их как String Null, похоже, не является хорошим решением. Формально правильная версия, похоже, должна передать пустое значение как:
<childtag2 xsi:nil="true" />
Таким образом, значение "Null" будет не чем иным, как допустимой строкой, что именно то, что вы ищете.
Я предполагаю, что это исправление в Apache Flex не должно быть так сложно сделать. Я бы рекомендовал открыть проблему Jira или связаться с ребятами из списка рассылки apache-flex. Однако это только исправит клиентскую сторону. Я не могу сказать, сможет ли ColdFusion работать с нулевыми значениями, закодированными таким образом.
См. также сообщение в блоге Radu Cotescu Как отправить нулевые значения в soapUI-запросы.
Ответ 9
Это kludge, но при условии, что для SEARCHSTRING
минимальная длина, например, 2 символа, substring
параметр SEARCHSTRING
для второго символа и вместо этого передайте его как два параметра: SEARCHSTRING1 ("Nu")
и SEARCHSTRING2 ("ll").
Concatenate
их обратно вместе при выполнении запроса в базу данных.