0

I have a webscript set up on the repo-side in Alfresco. The webscript uses the POST method, accepts and returns json and is simply designed to set some properties to support a client-side ajax app. The controller code for the script is as follows:

/**
 * Document Bundle Management Property setter method
 *
 * @method POST
 */

function main() {
        var nodeRef=args.doc,
            salesOrderNumber=json.get("salesOrderNumber"),
            stockCode=json.get("stockCode"),
            VIN=json.get("VIN"),
            customerCode=json.get("customerCode"),
            resultObj={result:"failure",problems:[],debug:[]};
        resultObj.debug.push("Webscript begins. Variables:");
        resultObj.debug.push("\tsalesOrderNumber: " + salesOrderNumber);
        resultObj.debug.push("\tstockCode: " + stockCode);
        resultObj.debug.push("\tVIN: " + VIN);
        resultObj.debug.push("\tcustomerCode:" + customerCode);
        if (nodeRef) {
                resultObj.debug.push("Received nodeRef variable. Checking validity");
                doc=utils.getNodeFromString(nodeRef);
                if (doc && doc.isDocument) {
                        resultObj.result="success";
                        resultObj.debug.push("nodeRef valid, checking document type");
                        if (doc.isSubType("my:documentBundle")) {
                                resultObj.debug.push("Document is already of type my:documentBundle. Not specializing");
                        } else {
                                resultObj.debug.push("Document is not of type my:documentBundle. Specializing");
                                doc.specializeType("my:documentBundle");
                        }
                        if (salesOrderNumber && salesOrderNumber.length && salesOrderNumber.length>0) {
                                doc.properties["salesOrderNumber"]=salesOrderNumber;
                                resultObj.debug.push("Set document salesOrderNumber to " + salesOrderNumber);
                        } else {
                                resultObj.debug.push("salesOrderNumber was not received, was blank or of zero length. ignoring");
                        }
                        if (stockCode && stockCode.length && stockCode.length>0) {
                                doc.properties["stockCode"]=stockCode;
                                resultObj.debug.push("Set document stockCode to " + stockCode);
                        } else {
                                resultObj.debug.push("stockCode was not received, was blank or of zero length. ignoring");
                        }
                        if (VIN && VIN.length && VIN.length>0) {
                                doc.properties["VIN"]=VIN;
                                resultObj.debug.push("Set document VIN to " + VIN);
                        } else {
                                resultObj.debug.push("VIN was not received, was blank or of zero length. ignoring");
                        }
                        if (customerCode && customerCode.length && customerCode.length>0) {
                                doc.properties["customerCode"]=customerCode;
                                resultObj.debug.push("Set document customerCode to " + customerCode);
                        } else {
                                resultObj.debug.push("customerCode was not received, was blank or of zero length. ignoring");
                        }
                        doc.save();
                        resultObj.debug.push("document saved");
                } else {
                        resultObj.problems.push("Invalid nodeRef supplied!");
                }
        } else {
                resultObj.problems.push("No nodeRef supplied!");
        }
        model.obj=resultObj;
}

main();

My problem occurs in the 4 lines like: if (salesOrderNumber && salesOrderNumber.length && salesOrderNumber.length>0) {, which always seem to evaluate false even when I am sure the variable contains a string that is not zero length. If I look at the debug property returned I see the following:

0: "Webscript begins. Variables:"
1: "    salesOrderNumber: test"
2: "    stockCode: test"
3: "    VIN: test"
4: "    customerCode:test"
5: "Received nodeRef variable. Checking validity"
6: "nodeRef valid, checking document type"
7: "Document is already of type my:documentBundle. Not specializing"
8: "salesOrderNumber was not received, was blank or of zero length. ignoring"
9: "stockCode was not received, was blank or of zero length. ignoring"
10: "VIN was not received, was blank or of zero length. ignoring"
11: "customerCode was not received, was blank or of zero length. ignoring"  
12: "document saved"

So, I can see that all four variables have the value "test". If in firebug or the js console I enter

a="test";
if (a && a.length && a.length>0) then console.log("true") else console.log("false")

I get true output, as expected. I don't see what could be affecting this - I use this incredibly basic condition almost daily to test strings before I use them but I am obviously missing something this time. help?

Chris O'Kelly
  • 1,863
  • 2
  • 18
  • 35
  • Is a strange situation. Can you reproduce as code that we can test outside of your environment? – Nathan Wall Nov 12 '12 at 05:10
  • I can't reproduce the test returning false anywhere else, firebug, Alfresco's admin console, everywhere else I perform that test on a populated string I get true – Chris O'Kelly Nov 12 '12 at 05:13

1 Answers1

1

Edit: Based on your comment below, I have a new theory. Since these appear to be some sort of objects and not primitive strings, the length method is what's causing the trouble:

This simple test behaves exactly the same way as your problem:

var x = {
    toString: function() { return 'test'; },
    length: function() { return 'something'; }
};

console.log('x is: ' + x);
if (x && x.length && x.length > 0)
    console.log('passed');
else
    console.log('failed');

It reports to be "test" when you concatenate it to a string, but it fails the test because length > 0 is false because length is a function. I would recommend converting it to a string.


Also, I would point out that some of your tests are unnecessary. salesOrderNumber.length > 0 will be false if and only if salesOrderNumber.length is falsey. Likewise, salesOrderNumber.length will only be falsey if and only if salesOrderNumber is the empty string (for a string), so you can simply:

salesOrderNumber = String(salesOrderNumber);
if (salesOrderNumber)
    console.log('ok');
else
    console.log('oops');
Nathan Wall
  • 10,530
  • 4
  • 24
  • 47
  • Hi Nathan, thanks for the help, but I do not think that applies in my case. See in my original question, towards the end, 'So, I can see that all four variables have the value "test".' – Chris O'Kelly Nov 12 '12 at 05:21
  • Hi Nathan, Maybe I have misunderstood some of the js type coercion, so if I have a zero length string, say `a=""`, if I run `if (a)` that will return false? that was essentially the point of the three tests, was to make sure that the variable is not zero length. – Chris O'Kelly Nov 12 '12 at 05:24
  • Ah, so I see. Can you try `console.log(typeof salesOrderNumber, salesOrderNumber);` and tell me the results? – Nathan Wall Nov 12 '12 at 05:24
  • 1
    Yes, the empty string is falsey in JavaScript, which means `if ("")` will evaluate as false. – Nathan Wall Nov 12 '12 at 05:25
  • also, on that note, I had added before each of the tests: `logger.warn(salesOrderNumber + " : " + salesOrderNumber.length);` and got an odd result: `test : function length() {/* int length() */}` although all my experience screams at me that length is a prop, not a function. Even though I am sure they aren't numbers, as such, I am thinking you might have been on the right track with the wrong type thing, they might be some weird JSON String type or something. I'm going to force them into String and see how it goes. – Chris O'Kelly Nov 12 '12 at 05:29
  • 1
    Yes, I am curious where you are getting these values from (basically what your `json.get` function is doing) because it seems to me to be creating objects which try to play tricks on you ;). It's definitely possible to create objects to behave this way in JavaScript, but why anyone would want to, I don't know. Please keep me updated as you investigate, and I'll try to help if I can. – Nathan Wall Nov 12 '12 at 05:33
  • Essentially a form on a page sends an ajax request pointed at the webscripts url. according to Alfresco doco, the servlet "parses a request of mimetype application/json into a JSON object named json". I spent a while yelling at the screen when `logger.warn(json)` output `{salesOrderNumber:"test",customerCode:"test",stockCode:"test",VIN:"test"}` but `json.salesOrderNumber` output undefined, and eventually happened across the json.get() syntax (because obviously javascript was lacking a well defined way of accessing object properties that everyone already understands :p) – Chris O'Kelly Nov 12 '12 at 05:42
  • Hi again Nathan, just popping by to double comment your answer and say this is exactly right. all those variables were of type 'object'. I wrapped the original assignments in String() and got rid of the extraneous tests - the webscript now works exactly as expected. – Chris O'Kelly Nov 12 '12 at 05:46