Comment passer “Null” (un vrai nom de famille!) À un service Web SOAP dans ActionScript 3?

Nous avons un employé dont le nom de famille est Null. Notre application de recherche d’employés est supprimée lorsque ce nom de famille est utilisé comme terme de recherche (ce qui arrive souvent). L’erreur reçue (merci Fiddler!) Est:

 soapenv:Server.userException coldfusion.xml.rpc.CFCInvocationException: [coldfusion.runtime.MissingArgumentException : The SEARCHSTRING parameter to the getFacultyNames function is required but was not passed in.] 

Mignon, hein?

Le type de paramètre est ssortingng .

J’utilise:

Notez que l’erreur ne se produit pas lorsque vous appelez le service Web en tant qu’object à partir d’une page ColdFusion.

Le traquer

Au début, je pensais que c’était un bug de coercition où null était forcé à "null" et un test de "null" == null était passé. Ce n’est pas. J’étais proche, mais très, très mal. Désolé pour ça!

J’ai depuis fait beaucoup de bidouillage sur wonderfl.net et suivi le code dans mx.rpc.xml.* . A la ligne 1795 de XMLEncoder (dans la source 3.5), dans setValue , tous les XMLEncoding se résument à

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

qui est essentiellement le même que:

 currentChild.appendChild("null"); 

Ce code, selon mon violon original, renvoie un élément XML vide. Mais pourquoi?

Cause

Selon le commentateur Justin Mclean sur le rapport de bogue FLEX-33664 , ce qui suit est le coupable (voir les deux derniers tests de mon violon qui le vérifient):

 var thisIsNotNull:XML = null; if(thisIsNotNull == null){ // always twigs here, as (thisIsNotNull == null) strangely returns true // despite the fact that thisIsNotNull is a valid instance of type XML } 

Lorsque currentChild.appendChild reçoit la chaîne "null" , il la convertit d’abord en un élément XML racine avec un texte null , puis teste cet élément avec le littéral nul. Il s’agit d’un test d’égalité faible, de sorte que le code XML contenant la valeur NULL est forcé au type NULL ou que le type NULL est forcé à un élément xml racine contenant la chaîne “null”. Une solution pourrait être de toujours utiliser des tests d’ égalité ssortingctes lors de la vérification de XML (ou de tout autre élément) pour la “nullité”.

Solution

La seule solution raisonnable à laquelle je puisse penser, à moins de corriger ce bogue dans chaque version d’ActionScript, consiste à tester les champs pour “null” et à les échapper en tant que valeurs CDATA .

Les valeurs CDATA sont le moyen le plus approprié de muter une valeur de texte entière qui pourrait causer des problèmes de codage / décodage. Le codage hexadécimal, par exemple, est destiné aux caractères individuels. Les valeurs CDATA sont préférées lorsque vous échappez à l’intégralité du texte d’un élément. La principale raison à cela est que cela maintient la lisibilité humaine.

Sur la note de xkcd , le site Web de Bobby Tables a de bons conseils pour éviter une interprétation incorrecte des données utilisateur (dans ce cas, la chaîne “Null”) dans les requêtes SQL en plusieurs langues, y compris ColdFusion .

Il ne ressort pas clairement de la question qu’il s’agit de la source du problème et, compte tenu de la solution indiquée dans un commentaire à la première réponse (incorporation des parameters dans une structure), il semble probable que c’était autre chose.

Le problème pourrait être dans l’encodeur SOAP de Flex. Essayez d’étendre l’encodeur SOAP dans votre application Flex et déboguez le programme pour voir comment la valeur NULL est gérée. Je suppose que c’est passé comme NaN (pas un nombre). Cela gâchera parfois le processus de suppression des messages SOAP (notamment dans le serveur JBoss 5 …). Je me souviens de l’extension de l’encodeur SOAP et de la vérification explicite du traitement de NaN.

(Sur une note de côté, êtes-vous censé faire quelque chose d’utile si l’identifiant de l’employé est Null, n’est-ce pas un problème de validation? Je peux me tromper, car je connais à peine la condition requirejse …)

@ doc_180 avait le bon concept, sauf qu’il se concentrait sur les nombres, alors que l’affiche originale avait des problèmes avec les chaînes.

La solution consiste à changer le fichier mx.rpc.xml.XMLEncoder . C’est la ligne 121

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

[J’ai regardé Flex 4.5.1 SDK; les numéros de ligne peuvent différer dans les autres versions]

Fondamentalement, la validation échoue car «le contenu est nul» et, par conséquent, votre argument n’est pas ajouté au paquet SOAP sortant; provoquant ainsi l’erreur de paramètre manquante.

Vous devez étendre cette classe pour supprimer la validation. Ensuite, il y a une grosse boule de neige dans la chaîne, modifiant SOAPEncoder pour utiliser votre XMLEncoder modifié, puis en modifiant l’Opération pour utiliser votre SOAPEncoder modifié, puis en modifiant WebService pour utiliser votre classe d’opération alternative.

J’ai passé quelques heures dessus, mais je dois continuer. Ça va probablement prendre un jour ou deux.

Vous pourrez peut-être simplement réparer la ligne XMLEncoder et faire un patch pour utiliser votre propre classe.

J’appendai également que si vous utilisez RemoteObject / AMF avec ColdFusion, la valeur NULL est transmise sans problème.


16/11/2013 mise à jour :

J’ai un dernier ajout à mon dernier commentaire sur RemoteObject / AMF. Si vous utilisez CF10; puis les propriétés avec une valeur nulle sur un object sont supprimées de l’object côté serveur. Donc, vous devez vérifier l’existence des propriétés avant d’y accéder ou vous obtiendrez une erreur d’exécution. Vérifiez comme ceci:

      

Ceci est un changement de comportement de CF9; où les propriétés null se transformeraient en chaînes vides.


Modifier le 06/12/2013

Comme il y avait une question sur le traitement des valeurs NULL, voici un exemple d’application rapide pour montrer comment une chaîne “null” se rapportera au mot réservé null.

          

La sortie de trace est la suivante:

La chaîne null n’est pas égale au mot réservé null en utilisant la condition! =

la chaîne null n’est pas égale au mot réservé null en utilisant la condition ==

la chaîne null n’est pas égale au mot réservé null en utilisant la condition ===

Traduire tous les caractères dans leurs équivalents hexadécimaux. Dans ce cas, Null serait converti en E;KC;C;

Ssortingngifier une valeur null dans ActionScript donnera la chaîne "NULL" . Mon soupçon est que quelqu’un a décidé que c’est donc une bonne idée de décoder la chaîne "NULL" en null , provoquant la casse que vous voyez ici – probablement parce qu’ils passaient null objects null et obtenaient des chaînes dans la firebase database, quand ils ne le voulaient pas (alors assurez-vous de vérifier ce type de bogue).

En tant que hack, vous pouvez envisager une gestion spéciale du côté client, en convertissant la chaîne “Null” en quelque chose qui ne se produira jamais, par exemple, XXNULLXX et la reconversion sur le serveur.

Ce n’est pas joli, mais cela peut résoudre le problème pour un tel cas limite.

Eh bien, je suppose que l’implémentation Flex de l’encodeur SOAP semble sérialiser les valeurs NULL de manière incorrecte. Les sérialiser en tant que Ssortingng Null ne semble pas être une bonne solution. La version formellement correcte semble être de passer une valeur nulle comme:

  

Donc, la valeur de “Null” ne serait rien d’autre qu’une chaîne valide, ce qui est exactement ce que vous recherchez.

Je suppose que cela ne devrait pas être difficile à faire. Je vous recommande d’ouvrir un numéro de Jira ou de contacter les membres de la liste de diffusion apache-flex. Cependant, cela ne ferait que corriger le côté client. Je ne peux pas dire si ColdFusion sera capable de travailler avec des valeurs nulles encodées de cette manière.

Voir aussi l’article de Radu Cotescu Comment envoyer des valeurs nulles dans les requêtes soapUI .

C’est un kludge, mais en supposant qu’il y ait une longueur minimale pour SEARCHSTRING , par exemple 2 caractères, on SEARCHSTRING paramètre SEARCHSTRING au second caractère et on le passe en deux parameters: SEARCHSTRING1 ("Nu") et SEARCHSTRING2 ("ll"). Concatenate ensemble lors de l’exécution de la requête dans la firebase database.