Как пройти "Null" (настоящая фамилия!) для веб-службы SOAP в ActionScript 3?

у нас есть сотрудник, фамилия которого равна нулю. Наше приложение поиска сотрудников убивается, когда эта фамилия используется в качестве поискового термина (что случается довольно часто). Ошибка получена (спасибо 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.

9 ответов


следопыт

сначала я подумал, что это ошибка принуждения, где null принуждали "null" и тест "null" == null проходил мимо. Это не так. я был близок, но очень, очень ошибался. Прости за это!

С тех пор я сделал много возиться wonderfl.net и трассировка через код в mx.rpc.xml.*. В строке 1795 XMLEncoder (в источнике 3.5), в setValue, все XMLEncoding сводится к

currentChild.appendChild(xmlSpecialCharsFilter(Object(value)));

что по существу то же самое, что:

currentChild.appendChild("null");

этот код, согласно моей оригинальной скрипке, возвращает пустой элемент XML. Но почему?

причина

по словам комментатора Джастина Маклина об ошибке 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, а затем проверяет этот элемент против литерала null. Это слабый тест равенства, поэтому либо XML, содержащий null, принуждается к типу null, либо тип null принуждается к корневому элементу xml, содержащему строку "null", и тест проходит там, где он, возможно, должен завершиться ошибкой. Одним из исправлений может быть всегда использовать строгое равенство тесты при проверке XML (или что угодно) для "nullness."

решение

Единственное разумное решение, которое я могу придумать, не исправляя эту ошибку в каждой чертовой версии ActionScript, - это проверить поля на "null" и избежать их как значения CDATA.

значения CDATA-наиболее подходящий способ мутировать целое текстовое значение, которое в противном случае вызвало бы проблемы кодирования/декодирования. шестнадцатеричное кодирование, например, предназначено для отдельных символов. Значения CDATA предпочтительнее, когда вы экранируете весь текст элемента. Самая большая причина для этого что она поддерживает людскую удобочитаемость.


на xkcd Примечание на веб-сайт таблицы Бобби имеет хороший совет для избежания неправильной интерпретации пользовательских данных (в данном случае строки "Null") в SQL-запросах на разных языках, включая ColdFusion.

из вопроса не ясно, что это источник проблемы, и учитывая решение, отмеченное в комментарии к первому ответу (встраивание параметров в структуру), кажется вероятным, что это было что-то еще.


проблема может быть в кодировщике SOAP Flex. Попробуйте расширить кодировщик SOAP в приложении Flex и отладить программу, чтобы увидеть, как обрабатывается значение null. Я предполагаю, что это прошло как Нэн (Не число). Это испортит процесс unmarshalling сообщения SOAP когда-нибудь (особенно в JBoss сервер 5...). Я помню, как расширил кодировщик SOAP и выполнил явную проверку того, как обрабатывается NaN.

(на стороне записки, вы должны сделайте что-нибудь полезное, если идентификатор сотрудника равен Null, это не проблема проверки? Я могу ошибаться, так как едва ли знаю, что требуется...)


@doc_180 имел правильную концепцию, за исключением того, что он сосредоточен на числах, тогда как оригинальный плакат имел проблемы со строками.

решение изменить . Это строка 121

    if (content != null)
        result += content;

[Я посмотрел на Flex 4.5.1 SDK; номера строк могут отличаться в других версиях]

в принципе, проверка не выполняется, потому что "содержимое равно null", и поэтому ваш аргумент не добавляется в исходящий пакет SOAP; таким образом, вызывая ошибку отсутствующего параметра.

вы должны расширить этот класс, чтобы удалить проверки. Затем есть большой снежный ком вверх по цепочке, изменяя SOAPEncoder использовать модифицированный XMLEncoder, а затем изменение операции использовать модифицированный SOAPEncoder, а затем moidfying WebService использовать альтернативный класс операции.

Я потратил на это несколько часов, но нужно двигаться дальше. Это займет день или два.

вы можете просто исправить линию XMLEncoder и сделать некоторые обезьяны исправление для использования собственного класса.

Я также добавлю, что если вы переключитесь на использование RemoteObject/AMF с ColdFusion, null будет передан без проблем.


обновление 11/16/2013:

у меня есть еще одно недавнее дополнение к моему последнему комментарию о RemoteObject/AMF. Если вы используете CF10; затем Свойства с нулевым значением на объекте удаляются из объекта на стороне сервера. Таким образом, вы должны проверить наличие свойств перед доступ к нему или вы получите ошибку времени выполнения. Проверьте вот так:

<cfif (structKeyExists(arguments.myObject,'propertyName')>
 <!--- no property code --->
<cfelse>
 <!--- handle property  normally --->
</cfif>

это изменение в поведении от CF9; где свойства null превратятся в пустые строки.


изменить 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>

вывод трассировки:

пустая строка не равно нулю зарезервированного слова с помощью != условие

нулевая строка не равна нулевому зарезервированному слову, используя условие==

нулевая строка не равна нулевому зарезервированному слову, используя условие===


перевести все символы в их hex-эквивалентные сущности. В этом случае Null будет преобразовано в &#4E;&#75;&#6C;&#6C;


Stringifying a null значение ActionScript даст строку "NULL". Мое подозрение в том, что кто-то решил, что это, следовательно, хорошая идея декодировать строку "NULL" as null, вызывая поломку, которую вы видите здесь-вероятно, потому, что они проходили null объекты и получение строк в базе данных, когда они этого не хотели (поэтому обязательно проверьте и такую ошибку).


в качестве взлома вы можете рассмотреть возможность специальной обработки на стороне клиента, преобразования строки "Null" в то, что никогда не произойдет, например, XXNULLXX и преобразования обратно на сервер.

Это не очень красиво, но это может решить проблему для такого граничного случая.


Ну, я думаю, что реализация Flex кодировщика SOAP, похоже, сериализует нулевые значения неправильно. Сериализация их как String Null не кажется хорошим решением. Формально правильная версия, похоже, передает нулевое значение как:

<childtag2 xsi:nil="true" />

таким образом, значение "Null" будет не чем иным, как допустимой строкой, что именно то, что вы ищете.

Я думаю, что это исправить в Apache Flex не должно быть так сложно сделать. Я бы рекомендовал Открытие проблемы Jira или связаться с ребятами Apache-flex mailinglist. Однако это только исправит клиентскую сторону. Я не могу сказать, сможет ли ColdFusion работать с нулевыми значениями, закодированными таким образом.

Смотрите также блог Раду Cotescu после как отправить нулевые значения в soapUI запросы.


это kludge, но при условии, что есть минимальная длина для SEARCHSTRING, например 2 знака, substring на SEARCHSTRING параметр на втором символе и передать его как два параметра вместо:SEARCHSTRING1 ("Nu") и SEARCHSTRING2 ("ll"). Concatenate их вместе при выполнении запроса к базе данных.