Comment passer "Null" (un vrai nom de famille!) à un service Web SOAP en ActionScript 3?
nous avons un employé dont le nom de famille est nul. Notre application de recherche d'employés est tué lorsque ce nom de famille est utilisé comme terme de recherche (qui se trouve être assez souvent maintenant). L'erreur reçue (Merci Fiddler!) est:
<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>
Mignon, hein?
le type de paramètre est string
.
j'utilise:
- WSDL (SOAP)
- Flex 3.5
- ActionScript 3
- ColdFusion 8
notez que l'erreur ne se produit pas lorsque vous appelez le service Web comme un objet à partir d'une page de ColdFusion.
9 réponses
Suivi vers le bas
au début, j'ai pensé que c'était un bug de coercition où null
était forcé à "null"
et un test de "null" == null
passait. Il n'est pas. j'étais proche, mais de façon très, très mal. Désolé à ce sujet!
j'ai depuis fait beaucoup de wonderfl.net et traçant le code dans mx.rpc.xml.*
. À la ligne 1795 de XMLEncoder
(au 3.5 source), dans setValue
, tous les XMLEncoding se résume à
currentChild.appendChild(xmlSpecialCharsFilter(Object(value)));
qui est essentiellement le même que:
currentChild.appendChild("null");
ce code, selon mon violon d'origine, renvoie un élément XML vide. Mais pourquoi?
Cause
selon le commentateur Justin Mclean sur le rapport de bogue FLEX-33664 , le suivant est le coupable (voir les deux derniers tests dans mon violon qui le vérifient):
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
}
quand currentChild.appendChild
est passé à la chaîne de caractères "null"
, il le convertit d'abord en un élément XML racine avec le texte null
, puis teste cet élément par rapport à la lettre nulle. Il s'agit d'un test d'égalité faible, donc soit le XML contenant null est contraint au type null, soit le type null est contraint à un élément xml racine contenant la chaîne "null", et le test passe là où il est possible de le soutenir. doit échouer. Une solution pourrait être d'utiliser toujours stricte equality tests lors de la vérification XML (ou n'importe quoi, vraiment) pour "nullness."
Solution
La seule solution raisonnable à laquelle je peux penser, à moins de corriger ce bug dans chaque version d'ActionScript, est de tester les champs pour "null" et en leur échappant comme valeurs CDATA .CDATA les valeurs sont le moyen le plus approprié pour muter une valeur texte entière qui causerait autrement des problèmes d'encodage/décodage. encodage Hex, par exemple, est destiné à des caractères individuels. Les valeurs CDATA sont préférées lorsque vous échappez au texte entier d'un élément. La principale raison en est qu'il maintient la lisibilité humaine.
sur la xkcd note , le Bobby Tables website a de bons conseils pour éviter l'interprétation incorrecte des données de l'utilisateur (dans ce cas, la chaîne" Null") dans les requêtes SQL dans diverses langues, y compris ColdFusion .
il n'est pas clair de la question que ce soit la source du problème, et compte tenu de la solution notée dans un commentaire à la première réponse (intégration des paramètres dans un structure) il semble probable que c'était autre chose.
le problème pourrait être dans le soap encoder de Flex. Essayez d'étendre L'encodeur SOAP dans votre application Flex et déboguez le programme pour voir comment la valeur nulle est traitée. À mon avis, il est passé comme NaN (pas un nombre). Cela va gâcher le processus de démontage des messages SOAP un jour (notamment dans le serveur JBoss 5)...). Je me souviens avoir étendu le soap encoder et avoir fait un contrôle explicite sur la façon dont NaN est traitée.
(Sur une note secondaire, est-ce que l'on s'attend à ce que vous fassiez quelque chose d'utile si l'id de l'employé est nul, n'est-ce pas un problème de validation? Je pourrais me tromper, puisque je connais à peine les conditions...)
@doc_180 avait le bon concept, sauf qu'il est concentré sur les nombres, alors que l'affiche originale avait des problèmes avec les cordes.
la solution est de 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 d'autres versions]
fondamentalement, la validation échoue parce que 'content is null' et donc 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 en haut de la chaîne, qui modifie SOAPEncoder pour utiliser votre xmlencoder modifié, puis qui modifie L'opération pour utiliser votre SOAPEncoder modifié, puis qui moidfie WebService pour utiliser votre classe d'opération alternative.
j'ai passé quelques heures dessus, mais j'ai besoin de passer à autre chose. Ça prendra probablement un jour ou deux.
Vous pouvez être en mesure de réparer la ligne XMLEncoder et de faire quelques corrections singe pour utiliser votre propre classe.
j'ajouterai aussi que si vous passez à L'utilisation de RemoteObject/AMF avec ColdFusion, le null est passé sans problème.
11/16/2013 mise à jour :
j'ai un ajout récent à mon dernier commentaire sur RemoteObject/AMF. Si vous utilisez CF10; puis propriétés avec un null valeur d'un objet sont supprimés du serveur côté de l'objet. 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:
<cfif (structKeyExists(arguments.myObject,'propertyName')>
<!--- no property code --->
<cfelse>
<!--- handle property normally --->
</cfif>
il s'agit d'un changement de comportement par rapport à CF9; où les propriétés nulles se transformeraient en chaînes vides.
Modifier 12/6/2013
Puisqu'il y avait une question sur la façon dont les nulls sont traités voici un échantillon rapide application pour démontrer comment une chaîne de caractères "null" se rapportera au mot réservé 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>
la sortie trace est:
la chaîne nulle n'est pas égale au mot réservé nul en utilisant le != condition
null string n'est pas égal à null reserved word en utilisant la = = condition
null string n'est pas égal à null reserved word en utilisant la = = = condition
traduit tous les caractères en leurs équivalents HEX-entity. Dans ce cas, Null
serait converti en E;KC;C;
Stringifying un null
valeur ActionScript , la chaîne "NULL"
. Mon soupçon est que quelqu'un a décidé qu'il est, par conséquent, une bonne idée de décoder la chaîne "NULL"
comme null
, causant la casse que vous voyez ici -- probablement parce qu'ils passaient dans null
objets et obtenir des chaînes dans la base de données, quand ils ne voulaient pas que (donc assurez-vous de vérifier pour ce genre de bug, aussi).
comme un hack, vous pourriez envisager d'avoir un traitement spécial du côté du client, en convertissant la chaîne 'Null' en quelque chose qui ne se produira jamais, par exemple, XXNULLXX et en convertissant de nouveau sur le serveur.
il n'est pas beau, mais il peut résoudre le problème pour un tel cas limite.
Eh bien, je suppose que L'implémentation par Flex du soap Encoder semble sérialiser incorrectement les valeurs nulles. Les sérialiser comme une chaîne Null ne semble pas être une bonne solution. La version formellement correcte semble être de passer une valeur nulle comme:
<childtag2 xsi:nil="true" />
donc la valeur de" Null " ne serait rien d'autre qu'une chaîne valide, ce qui est exactement ce que vous recherchez.
je pense que réparer ça dans Apache Flex ne devrait pas être si difficile pour obtenir fait. Je recommande d'ouvrir un numéro Jira ou de contacter les gars de la liste de diffusion apache-flex. Toutefois, cela ne ferait que corriger le côté client. Je ne peux pas dire si ColdFusion sera capable de fonctionner avec des valeurs nulles encodées de cette façon.
Voir aussi Radu Cotescu du blog Comment envoyer des valeurs null dans soapUI les demandes .
c'est un kludge, mais en supposant qu'il y a une longueur minimum pour SEARCHSTRING
, par exemple 2 caractères, substring
le paramètre SEARCHSTRING
au deuxième caractère et le passer comme deux paramètres à la place: SEARCHSTRING1 ("Nu")
et SEARCHSTRING2 ("ll").
Concatenate
eux de nouveau ensemble lors de l'exécution de la requête à la base de données.