Cómo pasar "Null" (¡un apellido real!) a un servicio web SOAP en ActionScript 3

Resuelto bill asked hace 13 años • 9 respuestas

Tenemos un empleado cuyo apellido es Nulo. Nuestra aplicación de búsqueda de empleados se elimina cuando se utiliza ese apellido como término de búsqueda (lo que ocurre con bastante frecuencia ahora). El error recibido es:

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

El tipo de parámetro es string.

Estoy usando:

  • WSDL ( jabón )
  • Flex 3.5
  • ActionScript 3
  • Fusión Fría 8

Tenga en cuenta que el error no ocurre al llamar al servicio web como un objeto desde una página de ColdFusion.

bill avatar Dec 16 '10 07:12 bill
Aceptado

Rastreándolo

Al principio pensé que se trataba de un error de coerción en el que nulllo obligaban y pasaba "null"una prueba . "null" == nullQue no es. Estuve cerca, pero muy, muy equivocado. ¡Lo lamento!

Desde entonces, he manipulado mucho en Wonderfl.net y rastreado el código en mx.rpc.xml.*. En la línea 1795 de XMLEncoder(en la fuente 3.5), en setValue, todo XMLEncoding se reduce a

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

que es esencialmente lo mismo que:

currentChild.appendChild("null");

Este código, según mi violín original, devuelve un elemento XML vacío. ¿Pero por qué?

Causa

Según el comentarista Justin Mclean en el informe de error FLEX-33664 , el siguiente es el culpable (consulte las dos últimas pruebas en mi violín que verifican esto):

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
}

Cuando currentChild.appendChildse pasa la cadena "null", primero la convierte en un elemento XML raíz con texto nully luego prueba ese elemento con el literal nulo. Esta es una prueba de igualdad débil, por lo que el XML que contiene null se convierte en el tipo null, o el tipo null se convierte en un elemento xml raíz que contiene la cadena "null", y la prueba pasa donde posiblemente debería fallar. Una solución podría ser utilizar siempre pruebas de igualdad estrictas al comprobar XML (o cualquier cosa, en realidad) en busca de "nulidad".

Solución

La única solución alternativa razonable que se me ocurre, aparte de corregir este error en todas las malditas versiones de ActionScript, es probar los campos en busca de "nulos" y escaparlos como valores CDATA .

Los valores CDATA son la forma más adecuada de mutar un valor de texto completo que, de otro modo, causaría problemas de codificación/decodificación. La codificación hexadecimal, por ejemplo, está destinada a caracteres individuales. Se prefieren los valores CDATA cuando se escapa el texto completo de un elemento. La razón principal de esto es que mantiene la legibilidad humana.

Ben Burns avatar Aug 01 '2013 17:08 Ben Burns

En la nota xkcd , el sitio web Bobby Tables tiene buenos consejos para evitar la interpretación inadecuada de los datos del usuario (en este caso, la cadena "Null") en consultas SQL en varios idiomas, incluido ColdFusion .

De la pregunta no queda claro que esta sea la fuente del problema y, dada la solución señalada en un comentario a la primera respuesta (incrustar los parámetros en una estructura), parece probable que fuera otra cosa.

Alex Dupuy avatar Apr 27 '2012 20:04 Alex Dupuy

El problema podría estar en el codificador SOAP de Flex. Intente ampliar el codificador SOAP en su aplicación Flex y depure el programa para ver cómo se maneja el valor nulo.

Supongo que se pasa como NaN (no es un número). Esto arruinará el proceso de resolución de mensajes SOAP en algún momento (más notablemente en el servidor JBoss 5...). Recuerdo haber extendido el codificador SOAP y haber realizado una verificación explícita de cómo se maneja NaN.

billygoat avatar Jan 16 '2011 08:01 billygoat

@doc_180 tenía el concepto correcto, excepto que se centra en los números, mientras que el cartel original tenía problemas con las cadenas.

La solución es cambiar el mx.rpc.xml.XMLEncoderarchivo. Esta es la línea 121:

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

(Miré el SDK de Flex 4.5.1; los números de línea pueden diferir en otras versiones).

Básicamente, la validación falla porque 'el contenido es nulo' y por lo tanto su argumento no se agrega al paquete SOAP saliente; provocando así el error de parámetro faltante.

Tienes que extender esta clase para eliminar la validación. Luego hay una gran bola de nieve en la cadena, modificando SOAPEncoder para usar su XMLEncoder modificado, y luego modificando Operation para usar su SOAPEncoder modificado, y luego modificando WebService para usar su clase Operation alternativa.

Le dediqué algunas horas, pero necesito seguir adelante. Probablemente tomará uno o dos días.

Es posible que puedas simplemente arreglar la línea XMLEncoder y hacer algunos parches para usar tu propia clase.

También agregaré que si cambias a usar RemoteObject/AMF con ColdFusion, el valor nulo se pasa sin problemas.


Actualización del 16/11/2013 :

Tengo una adición más reciente a mi último comentario sobre RemoteObject/AMF. Si está utilizando ColdFusion 10; luego, las propiedades con un valor nulo en un objeto se eliminan del objeto del lado del servidor. Por lo tanto, debe verificar la existencia de las propiedades antes de acceder a ellas o obtendrá un error de tiempo de ejecución.

Comprueba así:

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

Este es un cambio de comportamiento con respecto a ColdFusion 9; donde las propiedades nulas se convertirían en cadenas vacías.


Editar 6/12/2013

Dado que hubo una pregunta sobre cómo se tratan los valores nulos, aquí hay una aplicación de muestra rápida para demostrar cómo se relacionará una cadena "nulo" con la palabra reservada nulo.

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

La salida del seguimiento es:

La cadena nula no es igual a la palabra reservada nula usando la condición! =

la cadena nula no es igual a la palabra reservada nula usando la condición ==

la cadena nula no es igual a la palabra reservada nula usando la condición ===

JeffryHouser avatar May 03 '2012 15:05 JeffryHouser

Al encadenar un nullvalor en ActionScript se obtendrá la cadena "NULL". Mi sospecha es que alguien ha decidido que, por lo tanto, es una buena idea decodificar la cadena "NULL"como null, lo que provoca la rotura que ve aquí, probablemente porque estaban pasando nullobjetos y obteniendo cadenas en la base de datos, cuando no querían eso (así que asegúrese de comprobar también ese tipo de error).

Andrew Aylett avatar Apr 28 '2012 20:04 Andrew Aylett

Como truco, podría considerar tener un manejo especial en el lado del cliente, convirtiendo una cadena 'nula' en algo que nunca ocurrirá, por ejemplo, XXNULLXX y convirtiéndola nuevamente en el servidor.

No es bonito, pero puede resolver el problema de un caso límite de este tipo.

Mark avatar Apr 28 '2012 08:04 Mark