flex - Wie kann man in ActionScript 3 "Null"(einen echten Nachnamen!) An einen SOAP-Webservice übergeben?




coldfusion wsdl (6)

Wir haben einen Angestellten mit dem Nachnamen Null. Unsere Mitarbeiter-Suchanwendung wird beendet, wenn dieser Nachname als Suchbegriff verwendet wird (was jetzt häufig vorkommt). Der Fehler (danke Fiddler!) Lautet:

<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>

Süß, nicht wahr?

Der Parametertyp ist string .

Ich benutze:

  • WSDL (SOAP)
  • Flex 3,5
  • ActionScript 3
  • ColdFusion 8

Beachten Sie, dass der Fehler nicht auftritt, wenn der Webservice als Objekt von einer ColdFusion-Seite aufgerufen wird.


Aufspüren

Zuerst dachte ich, dass dies ein Nötigungsfehler war, bei dem null zu "null" gezwungen wurde und ein Test von "null" == null bestand. Es ist nicht. Ich war nah dran, aber so sehr, sehr falsch. Das tut mir leid!

Ich habe seitdem auf Wonderfl.net viel getüftelt und den Code in mx.rpc.xml.* . In Zeile 1795 von XMLEncoder (in der 3.5-Quelle) in setValue alle XMLEncoding auf

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

Das ist im Wesentlichen das Gleiche wie:

currentChild.appendChild("null");

Dieser Code gibt gemäß meiner ursprünglichen Geige ein leeres XML-Element zurück. Aber warum?

Ursache

Laut Kommentator Justin Mclean zum Fehlerbericht FLEX-33664 ist der folgende Fehler der Täter (siehe die letzten beiden Tests in meiner Geige, die dies bestätigen):

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
}

Wenn currentChild.appendChild die Zeichenfolge "null" , konvertiert es es zunächst in ein XML-Stammelement mit dem Text null und testet dieses Element dann anhand des Null-Literal. Dies ist ein schwacher Gleichheitstest. Entweder wird die XML-Datei, die Null enthält, zum Null-Typ oder der Null-Typ zu einem Root-XML-Element, das die Zeichenfolge "Null" enthält, erzwungen, und der Test wird dort bestanden, wo er versagen sollte. Ein Fix könnte darin bestehen, immer strenge Gleichheitstests zu verwenden, wenn Sie XML (oder etwas anderes) auf "Nullheit" prüfen.

Lösung

Die einzige sinnvolle Lösung, die ich mir vorstellen kann, ist, den Fehler in jeder verdammten Version von ActionScript zu beheben , indem die Felder auf "null" getestet und als CDATA-Werte gekennzeichnet werden .

CDATA-Werte sind der geeignetste Weg, um einen gesamten Textwert zu mutieren, der andernfalls Codierungs- / Decodierungsprobleme verursachen würde. Die Hex-Kodierung ist beispielsweise für einzelne Zeichen gedacht. CDATA-Werte werden bevorzugt, wenn Sie den gesamten Text eines Elements schützen. Der Hauptgrund dafür ist, dass es für den Menschen lesbar bleibt.


@ doc_180 hatte das richtige Konzept, nur dass er sich auf Zahlen konzentrierte, während das Originalposter Probleme mit Strings hatte.

Die Lösung besteht darin, die Datei mx.rpc.xml.XMLEncoder zu ändern. Dies ist Linie 121

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

[Ich habe mir Flex 4.5.1 SDK angesehen. Zeilennummern können in anderen Versionen abweichen]

Grundsätzlich schlägt die Überprüfung fehl, da 'content null' ist und daher Ihr Argument nicht zum ausgehenden SOAP-Paket hinzugefügt wird. Dadurch wird der fehlende Parameterfehler verursacht.

Sie müssen diese Klasse erweitern, um die Validierung zu entfernen. Dann gibt es einen großen Schneeball in der Kette, der SOAPEncoder so modifiziert, dass er Ihren modifizierten XMLEncoder verwendet, und dann Operation modifiziert, um Ihren modifizierten SOAPEncoder zu verwenden, und dann WebService missbrauchen, um Ihre alternative Operation-Klasse zu verwenden.

Ich habe ein paar Stunden damit verbracht, muss aber weitermachen. Es wird wahrscheinlich ein oder zwei Tage dauern.

Sie können möglicherweise nur die XMLEncoder-Zeile reparieren und ein paar Affen-Patches durchführen, um Ihre eigene Klasse zu verwenden.

Ich füge hinzu, dass, wenn Sie zur Verwendung von RemoteObject / AMF mit ColdFusion wechseln, die Null ohne Probleme übergeben wird.

16.11.2013 Update :

Zu meinem letzten Kommentar zu RemoteObject / AMF gibt es eine neuere Ergänzung. Wenn Sie CF10 verwenden; dann werden Eigenschaften mit einem Nullwert für ein Objekt aus dem serverseitigen Objekt entfernt. Sie müssen also nach dem Vorhandensein der Eigenschaften suchen, bevor Sie darauf zugreifen, oder Sie erhalten einen Laufzeitfehler. Überprüfen Sie wie folgt:

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

Dies ist eine Verhaltensänderung gegenüber CF9; wo die NULL-Eigenschaften in leere Zeichenfolgen umgewandelt würden.

Bearbeiten Sie den 06.12.2013

Da es eine Frage zum Umgang mit Nullen gab, handelt es sich hier um eine schnelle Beispielanwendung, um zu zeigen, wie eine Zeichenfolge "Null" sich auf das reservierte Wort Null bezieht.

<?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>

Die Trace-Ausgabe lautet:

NULL-Zeichenfolge entspricht nicht dem reservierten NULL-Wort unter Verwendung der Bedingung! =

NULL-Zeichenfolge ist nicht gleich einem reservierten NULL-Wort mit der Bedingung ==

NULL-Zeichenfolge ist nicht gleich reserviertem NULL-Wort unter Verwendung der Bedingung ===


Beim Festlegen eines null in ActionScript wird die Zeichenfolge "NULL" . Meine Vermutung ist, dass jemand entschieden hat, dass es daher eine gute Idee ist, die Zeichenfolge "NULL" als null zu dekodieren, was den Bruch verursacht, den Sie hier sehen - wahrscheinlich, weil sie in null und wann Zeichenfolgen in der Datenbank abgerufen wurden Das wollten sie nicht (also sollte man auch auf diese Art von Fehlern achten).


Das Problem könnte im SOAP-Encoder von Flex liegen. Versuchen Sie, den SOAP-Encoder in Ihrer Flex-Anwendung zu erweitern, und debuggen Sie das Programm, um zu sehen, wie der Nullwert behandelt wird. Meine Vermutung ist, dass es als NaN (Not a Number) übergeben wird. Dies führt dazu, dass die SOAP-Nachricht irgendwann einmal entfernt wird (vor allem bei JBoss 5-Server). Ich erinnere mich, dass ich den SOAP-Encoder erweitert und eine explizite Überprüfung der Handhabung von NaN durchgeführt habe.

(Nebenbei gesagt, wird von Ihnen erwartet, dass Sie etwas Nützliches tun, wenn die Mitarbeiter-ID Null ist. Ist dies nicht ein Validierungsproblem?


Nun, ich schätze, die Flex-Implementierung des SOAP-Encoders scheint Nullwerte falsch zu serialisieren. Das Serialisieren als String Null scheint keine gute Lösung zu sein. Die formal korrekte Version scheint zu sein, einen Nullwert zu übergeben:

<childtag2 xsi:nil="true" />

Der Wert von "Null" wäre also nichts anderes als eine gültige Zeichenfolge. Genau das, wonach Sie suchen.

Ich denke, das Problem in Apache Flex behoben zu bekommen, sollte nicht so schwer sein. Ich würde empfehlen, eine Jira-Ausgabe zu eröffnen oder sich mit den Jungs der Apache-Flex-Mailingliste in Verbindung zu setzen. Dies würde jedoch nur die Client-Seite beheben. Ich kann nicht sagen, ob ColdFusion mit auf diese Weise codierten Nullwerten arbeiten kann.

Siehe auch den Blogbeitrag von Radu Cotescu. So senden Sie Nullwerte in soapUI-Anforderungen .


Wandle alle Charaktere in ihre Entsprechungen in Hex-Entity um. In diesem Fall würde Null in &#4E;&#75;&#6C;&#6C;