checkExist()

checkExist()is one of “standardized” static methods on tables in Dynamics AX. It complements exist() method by showing an error message in infolog (message wording is usually implemented in a separate method txtNotExist()). Many teams create just find() and exist() methods, which is a pity because it’s a common scenario to display a text message in case of a non-existing record and it’s worthless to duplicate such logic in various places calling exist() (you also can’t change the error message in a single central places etc.).

Suprisingly enough, it’s possible to make errors even in such a simple method. I discovered that kind of error today during code reviewing and unfortunately I found it also in many other places, including standard AX code.

Suppose to have the following piece of code, which validates the existence of _bomId in BOMTable and performs some action, if the validation succeeds:

if (BOMTable::checkExist(_bomId))
{
    BOMTable::setCheckBOM(_bomId, false);
}

A logical assumption is that if the code is called with empty _bomId (which can happen easily), setCheckBOM() is not performed and some message about non-existence of BOM is displayed. But the real output is:

“Cannot edit a record in Bills of materials (BOMTable). The record has never been selected.”

The validation apparently succeeded, although no record with empty BOMId exists (it even can’t exist, because it’s a mandatory field). The invalid value was then sent to the subsequent processing and it caused a runtime exception there.

The reason is quite evident from the code of checkExist():

static boolean checkExist(BOMId bomNum)
{
    if (bomNum && ! BOMTable::exist(bomNum))
        return checkFailed(strfmt(BOMTable::txtNotExist(),bomNum));
 
    return true;
}

If bomNum is empty, the first condition in if is not met and the checkExist() method returns true! So the unexpected empty value is validated successfully and the whole validation lost its purpose.

How should it look like?

It’s sufficient to remove the first part of the condition and leave the whole validaton logic to the exist() method. Actually that’s what exist() is for.

static boolean checkExist(BOMId bomNum)
{
    if (!BOMTable::exist(bomNum))
        return checkFailed(strfmt(BOMTable::txtNotExist(),bomNum));
 
    return true;
}

Although not even  exist() method on BOMTable is implemented in the best way, it correctly returns false for an empty value of bomNum. Therefore the condition in checkExist() is met, the method returns false and writes “Bill of materials does not exist” to infolog.