Как передать «Null» (настоящую фамилию!) Веб-службе SOAP в ActionScript 3? - PullRequest
4567 голосов
/ 16 декабря 2010

У нас есть сотрудник по фамилии 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.

Ответы [ 9 ]

1084 голосов
/ 01 августа 2013

Отслеживание

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

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

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

Решение

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

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

294 голосов
/ 28 апреля 2012

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

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

236 голосов
/ 16 января 2011

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

(Следует отметить, что ожидается, что вы сделаете что-нибудь полезное, если идентификатор сотрудника имеет значение Null, это не проблема проверки?

126 голосов
/ 03 мая 2012

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

Решение состоит в том, чтобы изменить файл mx.rpc.xml.XMLEncoder.Это строка 121

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

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

По сути, проверка завершается неудачно, поскольку 'content is null' и, следовательно, ваш аргумент не добавляется в исходящий пакет SOAP;таким образом вызывая ошибку отсутствующего параметра.

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

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

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

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


11/16/2013 update :

У меня есть еще одно недавнее дополнение к моему последнему комментарию о 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>

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

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

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

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

63 голосов
/ 30 апреля 2012

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

50 голосов
/ 29 апреля 2012

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

37 голосов
/ 28 апреля 2012

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

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

30 голосов
/ 17 июля 2013

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

<childtag2 xsi:nil="true" />

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

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

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

21 голосов
/ 28 апреля 2012

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

...