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


у нас есть сотрудник, фамилия которого равна нулю. Наше приложение поиска сотрудников убивается, когда эта фамилия используется в качестве поискового термина (что случается довольно часто в настоящее время). Ошибка получена (спасибо скрипач!) это:

<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 (МЫЛО)
  • Flex 3.5
  • ActionScript 3
  • ColdFusion 8

обратите внимание, что ошибка не происходит при вызове webservice как объекта со страницы ColdFusion.

9   4495   2010-12-16 03:42:14

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

решение

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

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

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

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

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

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

@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" как null, вызывая поломку вы видите здесь-вероятно, потому что они проходили в null объекты и получение строк в базе данных, когда они этого не хотели (так что не забудьте проверить и такую ошибку).

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

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

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

<childtag2 xsi:nil="true" />

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

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

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

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